2、无中心节点
以 ceph 为代表,每个节点都是自治的、自管理的,整个 ceph 集群只包含一类节点,如下图 (最下层红色的 RADOS 就是 ceph 定义的“同时包含 meta 数据和文件数据”的节点) 。
文章插图
ceph
无中心化的最大优点是解决了中心节点自身的瓶颈,这也就是 ceph 号称可以无限向上扩容的原因 。但由 Client 直接和 Server 通信,那么 Client 必须要知道,当对某个文件进行操作时,它该访问集群中的哪个节点 。ceph 提供了一个很强大的原创算法来解决这个问题——CRUSH 算法 。
CRUSH:https://ceph.com/wp-content/uploads/2016/08/weil-crush-sc06.pdf
五、持久化
对于文件系统来说,持久化是根本,只要 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、存储节点的伸缩
当在集群中加入一台新的存储节点,则它主动向中心节点注册,提供自己的信息,当后续有创建文件或者给已有文件增加数据块的时候,中心节点就可以分配到这台新节点了,比较简单 。但有一些问题需要考虑 。