首页 文章 精选 留言 我的

精选列表

搜索[API选型],共10000篇文章
优秀的个人博客,低调大师

ApacheDoris Python UDF:SQL 调用 Python 的技术能力、选型对比与实践

ApacheDoris 通过 Python UDF 能力,让开发者在 SQL 中创建并调用 Python 函数,将 Pandas、PyArrow 等 Python 生态能力引入 Doris 查询链路。核心能力包括:基于 Arrow RecordBatch 的列式批量执行、Pandas Series 向量化计算、UDF/UDAF/UDTF 三类函数形态、内联与模块化代码加载、生产级进程隔离/资源复用/故障自愈机制。SelectDB 已将这一能力纳入商业化产品体系。

优秀的个人博客,低调大师

云溪数据库选型ART树作为数据查找算法

一、数据查找相关定义 数据查找是根据查询要求从一个计算机文件或数据库中提取所需要的数据的技术。如果要查找的数据全部放在计算机内存储器中,这种查找即称为内查找;若要查找的数据不在内存而在外存储器中,这种查找便称为外查找。 数据一般按照数据项、记录、文件三级组织在一定的结构之中。用于组织文件的基本数据项称为关键字。所谓从文件中查找数据是指根据给定的关键字值在文件中找出包含该关键字值的记录。对于不同的文件结构和查询要求,需要用不同的查找技术。 在各种数据集合(包括数组、线性表、树等数据结构)中,数据记录在集合中的实际位置是随机的,和数据记录的关键字之间不存在确定的关系。因此在数据集合中查找数据记录时需要进行一系列关键字的比较。比如在顺序查找时,比较的结果为“=”与“!= "两种可能。在折半查找、二叉排序树查找和树查找时,比较的结果为“>"、“<“ 与“=“ 三种可能。 查找算法大多数是建立在关键字比较的基础上。查找的效率主要决定于查找过程中所进行的比较次数和时长。在同等关键字模式下,以比较次数为最主要的因素。(比较树) 最理想的查找算法是不经过任何比较,一次操作便能得到所查的数据记录。那就必须在数据记录的实际位置和它的关键字之间建立一个唯一确定的对应关系,使每个关键字和数据集合中某个唯一的实际位置相对应。 数据查找三种实现方式: (1)比较树,需要多次关键字的比较,才能找到数值; (2)哈希表:数据记录位置与关键字奖励了对应关系。一次计算就能找到数值,需要一次关键字比较确认找到的是正确的关键字; (3)前缀树:只需要一次关键字的比较,将关键字拆分成多个部分,分别进行比较; 二、比较树 算法的比较树(也被叫作决定树或查找树),获得的方法是,追踪算法行为,用树节点(我们用画圈来表示)来描绘每次键(关键字、key)比较。圈里我们放置用来与目标键做比较的那些键的索引。树枝(线)由圈的位置向下画,表示比较的结果,然后像前边一样被标记上。 比较树,一般使用的都是数字,不是字符串。将整个key进行原子化比较。 2.1 BST 二叉搜索树(BST)又称二叉查找树或二叉排序树。 (1)一棵二叉搜索树是以二叉树来组织的,可以使用一个链表数据结构来表示,其中每一个结点就是一个对象。一般地,除了key和位置数据之外,每个结点还包含属性lchild、rchild和parent,分别指向结点的左孩子、右孩子和双亲(父结点)。 (2)如果某个孩子结点或父结点不存在,则相应属性的值为空(NIL)。根结点是树中唯一父指针为NULL的结点,而叶子结点的孩子结点指针也为NULL。 BST的每个数据项都有各自的关键字(key),并以此与其他的数据项区分。查找某数据项就相当于查找其关键字。这样的访问方式有前提条件,即关键码要支持大小比较与相等比对。 2.2 AVL AVL树是最先发明的自平衡二叉查找树。在AVL树中任何节点的两个子树的高度最大差别为1,所以它也被称为高度平衡树。AVL树本质上还是一棵二叉搜索树,它的特点是: (1)本身首先是一棵二叉搜索树。 (2)带有平衡条件:每个结点的左右子树的高度之差的绝对值(平衡因子)最多为1。 也就是说,AVL树,本质上是带了平衡功能的二叉查找树(二叉排序树,二叉搜索树)。通过左旋和右旋算法调整树结构。 2.3 红黑树 红黑树(Red Black Tree) 是一种自平衡二叉查找树。在进行插入和删除操作时通过特定操作保持二叉查找树的平衡,从而获得较高的查找性能。 红黑树是一种平衡二叉查找树的变体,它的左右子树高差有可能大于 1,所以红黑树不是严格意义上的平衡二叉树(AVL),但进行平衡的代价较低, 其平均统计性能要强于 AVL。 红黑树应用于C++ STL 中 容器 map,set底层以及linux任务调度、虚拟内存等。 红黑树是近似平衡的二叉查找树,它含有以下特性: (1)每个节点要么是红色,要么是黑色; (2)根节点必须是黑色; (3)红色节点不能连续(也即是,红色节点的孩子和父亲都不能是红色); (4)对于每个节点,从该点至null(树尾端)的任何路径,都含有相同个数的黑色节点; (5)每个叶子节点都为黑色; 2.4跳表 增加了向前指针的链表叫作跳表。跳表全称叫做跳跃表,简称跳表。 跳表是一个随机化的数据结构,实质就是一种可以进行二分查找的有序链表。跳表在原有的有序链表上面增加了多级索引,通过索引来实现快速查找。跳表不仅能提高搜索性能,同时也可以提高插入和删除操作的性能。Rocksdb 的 memTable 使用内联跳跃表(Inline Skip List). 跳表的特性: (1)最底层包含所有的元素; (2)每个元素插入时随机生成它的level; (3)如果一个元素出现在level(x),那么它一定出现在x以下的level中; (4)每个索引节点有两个指针,一个向下,一个向右; (5)跳表查询、插入、删除的时间复杂度为O(log n),与平衡二叉树接近; (6)范围遍历性能高 跳表插入、删除、查找元素的时间复杂度跟红黑树都是一样量级的,时间复杂度都是O(logn),而且跳表有一个特性是红黑树无法匹敌的---范围扫描。 所以在工业中,跳表也会经常被用到。由于最大高度是初始时确定的,也就是说,索引的数据量需要提前估算出来。 2.5 B-树 B-树是一种多路搜索树。1970年,R.Bayer和E.mccreight提出了一种适用于 外查找 的树,它是一种平衡的多叉树,称为B树(或B-树、B_树)。 一棵m阶B树(balanced tree of order m)是一棵平衡的m路搜索树。它或者是空树,或者是满足下列性质的树: (1)根结点至少有两个子女; (2)每个非根节点所包含的关键字个数 j 满足:┌m/2┐ - 1 <= j <= m - 1; (3)除根结点以外的所有结点(不包括叶子结点)的度数正好是关键字总数加1,故内部子树个数 k 满足:┌m/2┐ <= k <= m ; (4)所有的叶子结点都位于同一层。 B-树的搜索,从根结点开始,对结点内的关键字(有序)序列进行二分查找,如果命中则结束,否则进入查询关键字所属范围的儿子结点;重复,直到所对应的孩子指针为空,或已经是叶子结点 2.6 B+树 B+ 树是一种树数据结构,是一个n叉树,每个节点通常有多个孩子,一棵B+树包含根节点、内部节点和叶子节点。根节点可能是一个叶子节点,也可能是一个包含两个或两个以上孩子节点的节点。 B+树是应文件系统所需而出的一种B-树的变型树。B+树是为磁盘或其他直接存取辅助设备而设计的一种平衡查找树。B+树是B-树的变体,也是一种多路搜索树: B+树定义基本与B-树同,除了: (1)非叶子结点的子树指针与关键字个数相同; (2)非叶子结点的子树指针P[i],指向关键字值属于[K[i], K[i+1])的子树(B-树是开区间); (3)为所有叶子结点增加一个链指针; (4)所有关键字都在叶子结点出现; B+ 树通常用于数据库和操作系统的文件系统中。NTFS, NSS, XFS, JFS和BFS等文件系统都在使用B+树作为元数据索引。B+ 树的特点是能够保持数据稳定有序,其插入与修改拥有较稳定的对数时间复杂度。B+ 树元素自底向上插入。 三、哈希表 散列表(Hash table,也叫哈希表),是根据关键字(Key)而直接进行访问的数据结构。通过把关键字映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。 给定表M,存在函数f(key),对任意给定的关键字key,代入函数后若能得到包含该关键字的记录在表中的地址,则称表M为哈希(Hash)表,函数f(key)为哈希(Hash) 函数。 Linux内核中大量使用了hash表。 如果两个不同关键字的hash Code相同(在表中的地址),这种现象称为hash冲突。任意长度的消息压缩到固定长度的消息时的信息丢失,是导致hash冲突的根本原因。 哈希表内解决哈希冲突的方法: (1)开发定址法(线性探测再散列,二次探测再散列,伪随机探测再散列):根据当前地址再计算出一个地址 (2)再哈希法:同时构造多个不同的哈希函数 (3)链地址法:所有哈希地址相同的放在同一个链表中 (4)建立一个公共溢出区:哈希表分为基本表和溢出表两部分,凡是和基本表发生冲突的元素,一律填入溢出表 哈希冲突过多,意味着:数据insert/delete的时候需要lock整个冲突链表,同步开销增大。冲突链表过长,造成遍历开销过大。解决冲突的有效办法,就是用更大的hash表,对数据进行rehash。 四、前缀树 trie,又称前缀树或字典树,是一种有序树,用于保存关联数组,其中的键通常是字符串。与二叉查找树不同,键不是直接保存在节点中,而是由节点在树中的位置决定。一个节点的所有子孙都有相同的前缀,也就是这个节点对应的字符串,而根节点对应空字符串。一般情况下,不是所有的节点都有对应的值,只有叶子节点和部分内部节点所对应的键才有相关的值。 它有3个基本性质: (1)根节点不包含字符,除根节点外每一个节点都只包含一个字符; (2)从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的关键字; (3)每个节点的所有子节点包含的字符都不相同。 4.1 基数树 基数树(Radix tree),又称压缩前缀树,是一种更节省空间的Trie(前缀树)。所有节点使用固定大小的数组,用于存储 token 的所有值。以二进制位串为关键字的 trie 树,是一种多叉树形结构,同时又类似多层索引表,每个中间节点包含指向多个子节点的指针数组,叶子节点包含指向实际的对象的指针。 其特性是: (1)树的高度(复杂度)与记录数量无关,仅与 key 值长度有关 (2)更新和删除不涉及到树结构的调整,不同插入顺序产生相同的树 (3)到达叶子节点的路径,表示该节点的 key。 缺点: 在 key 值稀疏情况下,每个 node 内的空间占用很少,导致内存上的浪费,所以 Radix Tree 并没有广泛应用在 DBMS 中。 4.2 ART树 Adaptive Radix Tree(自适应基数/前缀树,ART)可变的基数树,在 Radix tree 的基础上,优化增加可变特性,其核心是优化空间的利用率。每个节点的空间大小不再相同,而是根据需要使用不同的节点类型。 ART树针对基数树的优化点有: 节点划分不同类型、路径压缩、懒扩展。 五、MassTree 可以理解为B+ Tree 和 Radix Tree 的混合体,即将键切分成多个部分,每个部分为一个节点;每个节点内部又是一个 B+ Tree,兼顾空间和性能。 每个虚线框代表一棵 B+ 树,对于每一层(Layer)的 B+ 树,采用8字节进行索引。长度小于 (8h + 8) 字节的 key 会被存放在 layer <=h。比如,两个 key 存放在 layer 1,那么它们的前8字节是相同的。 圆形代表内部节点(interior node,也就是 B+ 树的 branch node),矩形代表边缘节点(border node,也就是 B+ 树的 leaf node),五角星代表 value。border node 的 value 域可能存放的是数据,也可能存放的是下一层子树的根节点。 六、哈希树 哈希树(hash tree、Merkle tree),是一种树形数据结构,每个叶节点均以数据块的哈希作为标签,而除了叶节点以外的节点则以其子节点标签的加密哈希作为标签 。哈希树能够高效、安全地验证大型数据结构的内容。 选择质数分辨算法来建立一棵哈希树。 Root为哈希树的根(深蓝色节点)。 R0和R1为第一层节点(灰色节点)共有2个,对应除数序列中的第一个数。 R00、R01、R02、R10、R11、R12为第二层节点(黄色节点)共6个。其中R00、R01和R02是属于R0的子节点,R10、R11和R12是属于R1的子节点。R0和R1下分别有3个子节点,对应除数序列中的第二个数。 后续的R00、R01、R02、R10、R11和R12节点下又分别有5个子节点(白色节点),对应除数序列中的第三个数。 从2起的连续质数,连续10个质数就可以分辨大约M(10) =2*3*5*7*11*13*17*19*23*29= 6464693230 七、查找算法性能比较 ART :自适应基数树(The Adaptive Radix Tree) CSB :一种内存优化后的B+树(Cache-Sensitive B +-tree [CSB]), kary :每个节点都有k维点的树(k-ary search tree) FAST : 对平衡二叉树查询进行了优化( Fast Architecture Sensitive Tree) GPT :基数树 (Generalized Prefix Tree) • RB :红黑树(red-black tree) , • HT :哈希表(chained hash table,using MurmurHash). 从上面两个比较中,可以发现 ART树拥有极好的性能,几乎可以匹敌哈希表。ART树比哈希表的优势是,支持范围查找。因此,云溪数据库在存储层使用ART树算法进行数据查找。

优秀的个人博客,低调大师

主流分布式文件系统选型,写得太好了!

作者:张轲1983<br> 来源:https://www.jianshu.com/p/fc0aa34606ce 一、概述 分布式文件系统是分布式领域的一个基础应用,其中最著名的毫无疑问是 HDFS/GFS。如今该领域已经趋向于成熟,但了解它的设计要点和思想,对我们将来面临类似场景/问题时,具有借鉴意义。 并且,分布式文件系统并非只有 HDFS/GFS 这一种形态,在它之外,还有其他形态各异、各有千秋的产品形态,对它们的了解,也对扩展我们的视野有所俾益。 本文试图分析和思考,在分布式文件系统领域,我们要解决哪些问题、有些什么样的方案、以及各自的选择依据。 二、过去的样子 在几十年以前,分布式文件系统就已经出现了,以 Sun 在 1984 年开发的“Network File System (NFS)”为代表,那时候解决的主要问题,是网络形态的磁盘,把磁盘从主机中独立出来。 这样不仅可以获得更大的容量,而且还可以随时切换主机,还可以实现数据共享、备份、容灾等,因为数据是电脑中最重要的资产。 NFS 的数据通信图如下: 部署在主机上的客户端,通过 TCP/IP 协议把文件命令转发到远程文件 Server 上执行,整个过程对主机用户透明。 到了互联网时代,流量和数据快速增长,分布式文件系统所要解决的主要场景变了,开始需要非常大的磁盘空间,这在磁盘体系上垂直扩容是无法达到的,必须要分布式,同时分布式架构下,主机都是可靠性不是非常好的普通服务器,因此容错、高可用、持久化、伸缩性等指标,就成为必须要考量的特性。 三、对分布式文件系统的要求 对一个分布式文件系统而言,有一些特性是必须要满足的,否则就无法有竞争力。主要如下: 应该符合 POSIX 的文件接口标准,使该系统易于使用,同时对于用户的遗留系统也无需改造; 对用户透明,能够像使用本地文件系统那样直接使用; 持久化,保证数据不会丢失; 具有伸缩性,当数据压力逐渐增长时能顺利扩容; 具有可靠的安全机制,保证数据安全; 数据一致性,只要文件内容不发生变化,什么时候去读,得到的内容应该都是一样的。 除此之外,还有些特性是分布式加分项,具体如下: 支持的空间越大越好; 支持的并发访问请求越多越好; 性能越快越好; 硬件资源的利用率越高越合理,就越好。 四、架构模型 从业务模型和逻辑架构上,分布式文件系统需要这几类组件: 存储组件:负责存储文件数据,它要保证文件的持久化、副本间数据一致、数据块的分配 / 合并等等; 管理组件:负责 meta 信息,即文件数据的元信息,包括文件存放在哪台服务器上、文件大小、权限等,除此之外,还要负责对存储组件的管理,包括存储组件所在的服务器是否正常存活、是否需要数据迁移等; 接口组件:提供接口服务给应用使用,形态包括 SDK(Java/C/C++ 等)、CLI 命令行终端、以及支持 FUSE 挂载机制。 而在部署架构上,有着“中心化”和“无中心化”两种路线分歧,即是否把“管理组件”作为分布式文件系统的中心管理节点。两种路线都有很优秀的产品,下面分别介绍它们的区别。 1、有中心节点 以 GFS 为代表,中心节点负责文件定位、维护文件 meta 信息、故障检测、数据迁移等管理控制的职能,下图是 GFS 的架构图: 该图中GFS master 即为 GFS 的中心节点,GF chunkserver 为 GFS 的存储节点。其操作路径如下: Client 向中心节点请求“查询某个文件的某部分数据”; 中心节点返回文件所在的位置 (哪台 chunkserver 上的哪个文件) 以及字节区间信息; Client 根据中心节点返回的信息,向对应的 chunk server 直接发送数据读取的请求; chunk server 返回数据。 在这种方案里,一般中心节点并不参与真正的数据读写,而是将文件 meta 信息返回给 Client 之后,即由 Client 与数据节点直接通信。其主要目的是降低中心节点的负载,防止其成为瓶颈。这种有中心节点的方案,在各种存储类系统中得到了广泛应用,因为中心节点易控制、功能强大。 2、无中心节点 以ceph为代表,每个节点都是自治的、自管理的,整个 ceph 集群只包含一类节点,如下图 (最下层红色的 RADOS 就是 ceph 定义的“同时包含 meta 数据和文件数据”的节点)。 无中心化的最大优点是解决了中心节点自身的瓶颈,这也就是 ceph 号称可以无限向上扩容的原因。但由 Client 直接和 Server 通信,那么 Client 必须要知道,当对某个文件进行操作时,它该访问集群中的哪个节点。ceph 提供了一个很强大的原创算法来解决这个问题——CRUSH 算法。 五、持久化 对于文件系统来说,持久化是根本,只要 Client 收到了 Server 保存成功的回应之后,数据就不应该丢失。这主要是通过多副本的方式来解决,但在分布式环境下,多副本有这几个问题要面对。 如何保证每个副本的数据是一致的? 如何分散副本,以使灾难发生时,不至于所有副本都被损坏? 怎么检测被损坏或数据过期的副本,以及如何处理? 该返回哪个副本给 Client? 1、如何保证每个副本的数据是一致的? 同步写入是保证副本数据一致的最直接的办法。当 Client 写入一个文件的时候,Server 会等待所有副本都被成功写入,再返回给 Client。 这种方式简单、有保障,唯一的缺陷就是性能会受到影响。假设有 3 个副本,如果每个副本需要N秒,则可能会阻塞 Client 3N 秒的时间,有几种方式,可以对其进行优化: 并行写:由一个副本作为主副本,并行发送数据给其他副本; 链式写:几个副本组成一个链 (chain),并不是等内容都接受到了再往后传播,而是像流一样,边接收上游传递过来的数据,一边传递给下游。 还有一种方式是采用 CAP 中所说的 W+R>N 的方式,比如 3 副本 (N=3) 的情况,W=2,R=2,即成功写入 2 个就认为成功,读的时候也要从 2 个副本中读。这种方式通过牺牲一定的读成本,来降低写成本,同时增加写入的可用性。这种方式在分布式文件系统中用地比较少。 2、如何分散副本,以使灾难发生时,不至于所有副本都被损坏? 这主要避免的是某机房或某城市发生自然环境故障的情况,所以有一个副本应该分配地比较远。它的副作用是会带来这个副本的写入性能可能会有一定的下降,因为它离 Client 最远。所以如果在物理条件上无法保证够用的网络带宽的话,则读写副本的策略上需要做一定考虑。 可以参考同步写入只写 2 副本、较远副本异步写入的方式,同时为了保证一致性,读取的时候又要注意一些,避免读取到异步写入副本的过时数据。 3、怎么检测被损坏或数据过期的副本,以及如何处理? 如果有中心节点,则数据节点定期和中心节点进行通信,汇报自己的数据块的相关信息,中心节点将其与自己维护的信息进行对比。如果某个数据块的 checksum 不对,则表明该数据块被损坏了;如果某个数据块的 version 不对,则表明该数据块过期了。 如果没有中心节点,以 ceph 为例,它在自己的节点集群中维护了一个比较小的 monitor 集群,数据节点向这个 monitor 集群汇报自己的情况,由其来判定是否被损坏或过期。 当发现被损坏或过期副本,将它从 meta 信息中移除,再重新创建一份新的副本就好了,移除的副本在随后的回收机制中会被收回。 4、该返回哪个副本给 Client? 这里的策略就比较多了,比如 round-robin、速度最快的节点、成功率最高的节点、CPU 资源最空闲的节点、甚至就固定选第一个作为主节点,也可以选择离自己最近的一个,这样对整体的操作完成时间会有一定节约。 六、伸缩性 1、存储节点的伸缩 当在集群中加入一台新的存储节点,则它主动向中心节点注册,提供自己的信息,当后续有创建文件或者给已有文件增加数据块的时候,中心节点就可以分配到这台新节点了,比较简单。但有一些问题需要考虑。 如何尽量使各存储节点的负载相对均衡? 怎样保证新加入的节点,不会因短期负载压力过大而崩塌? 如果需要数据迁移,那如何使其对业务层透明? 1)如何尽量使各存储节点的负载相对均衡? 首先要有评价存储节点负载的指标。有多种方式,可以从磁盘空间使用率考虑,也可以从磁盘使用率 +CPU 使用情况 + 网络流量情况等做综合判断。一般来说,磁盘使用率是核心指标。 其次在分配新空间的时候,优先选择资源使用率小的存储节点;而对已存在的存储节点,如果负载已经过载、或者资源使用情况不均衡,则需要做数据迁移。 2)怎样保证新加入的节点,不会因短期负载压力过大而崩塌? 当系统发现当前新加入了一台存储节点,显然它的资源使用率是最低的,那么所有的写流量都路由到这台存储节点来,那就可能造成这台新节点短期负载过大。因此,在资源分配的时候,需要有预热时间,在一个时间段内,缓慢地将写压力路由过来,直到达成新的均衡。 3)如果需要数据迁移,那如何使其对业务层透明? 在有中心节点的情况下,这个工作比较好做,中心节点就包办了——判断哪台存储节点压力较大,判断把哪些文件迁移到何处,更新自己的 meta 信息,迁移过程中的写入怎么办,发生重命名怎么办。无需上层应用来处理。 如果没有中心节点,那代价比较大,在系统的整体设计上,也是要考虑到这种情况,比如ceph,它要采取逻辑位置和物理位置两层结构,对Client暴露的是逻辑层 (pool 和 place group),这个在迁移过程中是不变的,而下层物理层数据块的移动,只是逻辑层所引用的物理块的地址发生了变化,在Client看来,逻辑块的位置并不会发生改变。 2、中心节点的伸缩 如果有中心节点,还要考虑它的伸缩性。由于中心节点作为控制中心,是主从模式,那么在伸缩性上就受到比较大的限制,是有上限的,不能超过单台物理机的规模。我们可以考虑各种手段,尽量地抬高这个上限。有几种方式可以考虑: 以大数据块的形式来存储文件——比如 HDFS 的数据块的大小是 64M,ceph 的的数据块的大小是 4M,都远远超过单机文件系统的 4k。它的意义在于大幅减少 meta data 的数量,使中心节点的单机内存就能够支持足够多的磁盘空间 meta 信息。 中心节点采取多级的方式——顶级中心节点只存储目录的 meta data,其指定某目录的文件去哪台次级总控节点去找,然后再通过该次级总控节点找到文件真正的存储节点; 中心节点共享存储设备——部署多台中心节点,但它们共享同一个存储外设 / 数据库,meta 信息都放在这里,中心节点自身是无状态的。这种模式下,中心节点的请求处理能力大为增强,但性能会受一定影响。iRODS 就是采用这种方式。 七、高可用性 1、中心节点的高可用 中心节点的高可用,不仅要保证自身应用的高可用,还得保证 meta data 的数据高可用。 meta data 的高可用主要是数据持久化,并且需要备份机制保证不丢。一般方法是增加一个从节点,主节点的数据实时同步到从节点上。也有采用共享磁盘,通过 raid1 的硬件资源来保障高可用。显然增加从节点的主备方式更易于部署。 meta data 的数据持久化策略有以下几种方式: 直接保存到存储引擎上,一般是数据库。直接以文件形式保存到磁盘上,也不是不可以,但因为 meta 信息是结构化数据,这样相当于自己研发出一套小型数据库来,复杂化了。 保存日志数据到磁盘文件 (类似 MySQL 的 binlog 或 Redis 的 aof),系统启动时在内存中重建成结果数据,提供服务。修改时先修改磁盘日志文件,然后更新内存数据。这种方式简单易用。 当前内存服务 + 日志文件持久化是主流方式。一是纯内存操作,效率很高,日志文件的写也是顺序写;二是不依赖外部组件,独立部署。 为了解决日志文件会随着时间增长越来越大的问题,以让系统能以尽快启动和恢复,需要辅助以内存快照的方式——定期将内存 dump 保存,只保留在 dump 时刻之后的日志文件。这样当恢复时,从最新一次的内存 dump 文件开始,找其对应的 checkpoint 之后的日志文件开始重播。 2、存储节点的高可用 在前面“持久化”章节,在保证数据副本不丢失的情况下,也就保证了其的高可用性。 八、性能优化和缓存一致性 这些年随着基础设施的发展,局域网内千兆甚至万兆的带宽已经比较普遍,以万兆计算,每秒传输大约 1250M 字节的数据,而 SATA 磁盘的读写速度这些年基本达到瓶颈,在 300-500M/s 附近,也就是纯读写的话,网络已经超过了磁盘的能力,不再是瓶颈了,像 NAS 网络磁盘这些年也开始普及起来。 但这并不代表,没有必要对读写进行优化,毕竟网络读写的速度还是远慢于内存的读写。常见的优化方法主要有: 内存中缓存文件内容; 预加载数据块,以避免客户端等待; 合并读写请求,也就是将单次请求做些积累,以批量方式发送给 Server 端。 缓存的使用在提高读写性能的同时,也会带来数据不一致的问题: 会出现更新丢失的现象。当多个 Client 在一个时间段内,先后写入同一个文件时,先写入的 Client 可能会丢失其写入内容,因为可能会被后写入的 Client 的内容覆盖掉; 数据可见性问题。Client 读取的是自己的缓存,在其过期之前,如果别的 Client 更新了文件内容,它是看不到的;也就是说,在同一时间,不同 Client 读取同一个文件,内容可能不一致。 这类问题有几种方法: 文件只读不改:一旦文件被 create 了,就只能读不能修改。这样 Client 端的缓存,就不存在不一致的问题; 通过锁:用锁的话还要考虑不同的粒度。写的时候是否允许其他 Client 读? 读的时候是否允许其他 Client 写? 这是在性能和一致性之间的权衡,作为文件系统来说,由于对业务并没有约束性,所以要做出合理的权衡,比较困难,因此最好是提供不同粒度的锁,由业务端来选择。但这样的副作用是,业务端的使用成本抬高了。 九、安全性 由于分布式文件存储系统,肯定是一个多客户端使用、多租户的一个产品,而它又存储了可能是很重要的信息,所以安全性是它的重要部分。 主流文件系统的权限模型有以下这么几种: DAC:全称是 Discretionary Access Control,就是我们熟悉的 Unix 类权限框架,以 user-group-privilege 为三级体系,其中 user 就是 owner,group 包括 owner 所在 group 和非 owner 所在的 group、privilege 有 read、write 和 execute。这套体系主要是以 owner 为出发点,owner 允许谁对哪些文件具有什么样的权限。 MAC:全称是 Mandatory Access Control,它是从资源的机密程度来划分。比如分为“普通”、“机密”、“绝密”这三层,每个用户可能对应不同的机密阅读权限。这种权限体系起源于安全机构或军队的系统中,会比较常见。它的权限是由管理员来控制和设定的。Linux 中的 SELinux 就是 MAC 的一种实现,为了弥补 DAC 的缺陷和安全风险而提供出来。关于 SELinux 所解决的问题可以参考 What is SELinux? RBAC:全称是 Role Based Access Control,是基于角色 (role) 建立的权限体系。角色拥有什么样的资源权限,用户归到哪个角色,这对应企业 / 公司的组织机构非常合适。RBAC 也可以具体化,就演变成 DAC 或 MAC 的权限模型。 市面上的分布式文件系统有不同的选择,像 ceph 就提供了类似 DAC 但又略有区别的权限体系,Hadoop 自身就是依赖于操作系统的权限框架,同时其生态圈内有 Apache Sentry 提供了基于 RBAC 的权限体系来做补充。 十、其他 1、空间分配 有连续空间和链表空间两种。连续空间的优势是读写快,按顺序即可,劣势是造成磁盘碎片,更麻烦的是,随着连续的大块磁盘空间被分配满而必须寻找空洞时,连续分配需要提前知道待写入文件的大小,以便找到合适大小的空间,而待写入文件的大小,往往又是无法提前知道的 (比如可编辑的 word 文档,它的内容可以随时增大); 而链表空间的优势是磁盘碎片很少,劣势是读写很慢,尤其是随机读,要从链表首个文件块一个一个地往下找。 为了解决这个问题,出现了索引表——把文件和数据块的对应关系也保存一份,存在索引节点中 (一般称为 i 节点),操作系统会将 i 节点加载到内存,从而程序随机寻找数据块时,在内存中就可以完成了。通过这种方式来解决磁盘链表的劣势,如果索引节点的内容太大,导致内存无法加载,还有可能形成多级索引结构。 2、文件删除 实时删除还是延时删除? 实时删除的优势是可以快速释放磁盘空间;延时删除只是在删除动作执行的时候,置个标识位,后续在某个时间点再来批量删除,它的优势是文件仍然可以阶段性地保留,最大程度地避免了误删除,缺点是磁盘空间仍然被占着。在分布式文件系统中,磁盘空间都是比较充裕的资源,因此几乎都采用逻辑删除,以对数据可以进行恢复,同时在一段时间之后 (可能是 2 天或 3 天,这参数一般都可配置),再对被删除的资源进行回收。 怎么回收被删除或无用的数据? 可以从文件的 meta 信息出发——如果 meta 信息的“文件 - 数据块”映射表中包含了某个数据块,则它就是有用的;如果不包含,则表明该数据块已经是无效的了。所以,删除文件,其实是删除 meta 中的“文件 - 数据块”映射信息 (如果要保留一段时间,则是把这映射信息移到另外一个地方去)。 3、面向小文件的分布式文件系统 有很多这样的场景,比如电商——那么多的商品图片、个人头像,比如社交网站——那么多的照片,它们具有的特性,可以简单归纳下: 每个文件都不大; 数量特别巨大; 读多写少; 不会修改。 针对这种业务场景,主流的实现方式是仍然是以大数据块的形式存储,小文件以逻辑存储的方式存在,即文件 meta 信息记录其是在哪个大数据块上,以及在该数据块上的 offset 和 length 是多少,形成一个逻辑上的独立文件。这样既复用了大数据块系统的优势和技术积累,又减少了 meta 信息。 4、文件指纹和去重 文件指纹就是根据文件内容,经过算法,计算出文件的唯一标识。如果两个文件的指纹相同,则文件内容相同。在使用网络云盘的时候,发现有时候上传文件非常地快,就是文件指纹发挥作用。云盘服务商通过判断该文件的指纹,发现之前已经有人上传过了,则不需要真的上传该文件,只要增加一个引用即可。在文件系统中,通过文件指纹可以用来去重、也可以用来判断文件内容是否损坏、或者对比文件副本内容是否一致,是一个基础组件。 文件指纹的算法也比较多,有熟悉的 md5、sha256、也有 google 专门针对文本领域的 simhash 和 minhash 等。 十一、总结 分布式文件系统内容庞杂,要考虑的问题远不止上面所说的这些,其具体实现也更为复杂。本文只是尽量从分布式文件系统所要考虑的问题出发,给予一个简要的分析和设计,如果将来遇到类似的场景需要解决,可以想到“有这种解决方案”,然后再来深入研究。 同时,市面上也是存在多种分布式文件系统的形态,下面就是有研究小组曾经对常见的几种分布式文件系统的设计比较。 从这里也可以看到,选择其实很多,并不是 GFS 论文中的方式就是最好的。在不同的业务场景中,也可以有更多的选择策略。 近期热文推荐: 1.1,000+ 道 Java面试题及答案整理(2021最新版) 2.终于靠开源项目弄到 IntelliJ IDEA 激活码了,真香! 3.阿里 Mock 工具正式开源,干掉市面上所有 Mock 工具! 4.Spring Cloud 2020.0.0 正式发布,全新颠覆性版本! 5.《Java开发手册(嵩山版)》最新发布,速速下载! 觉得不错,别忘了随手点赞+转发哦!

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册