分布式存储架构设计

       发一个分布式存储的架构设计,看有没有感兴趣的同学一起讨论下,也非常欢迎高手指教。

  最底层类似Ceph(个人认为Ceph实在是太复杂),为一个统一的分布式存储引擎。上层提供对象存储服务,文件系统服务,块存储服务。

  (本帖只讲底层的分布式存储引擎。)

  分布式存储的典型问题:
  1) 海量文件(数量可达万亿级)的管理,
  2) 数据高可靠,
  3) 服务高可用,
  4) 存储机器扩容缩容,
  5) 故障自动处理,
  6) 高性能。

  首先:
  整体上采用集中式模式,由管理节点(在内存中)统一管理元数据,管理节点为新数据分配存储节点,管理节点还负责存储节点健康监控,故障恢复调度等。数据存放在存储节点上。
  这种方式比Ceph的方式优点更多:数据分布任意,扩容缩容极为方便(扩容时可以不迁移数据),磁盘利用率高。至于性能,读数据可在客户端缓存数据位置,定位数据的总体性能不会比Ceph差多少。
  Ceph的crush算法会导致一个非常严重的问题,在机器故障或者扩容缩容时,会导致大量数据重新平衡,而数据平衡期间服务不可用(不能读写),服务不可用时间可能会长达几十个小时。所有基于算法来确定数据位置的方式都会有类似的问题,例如S3的基于一致性哈希来定位数据也会遇到数据再平衡的问题。
  Ceph的元数据持久化方式(集中存放到RocksDB中)也会导致一个严重的问题,即单个集群文件(此处文件指的是各个对象数据)数量会非常有限,基本只能到亿级。远不能满足互联网的应用场景。一般只能创建多个集群来满足应用需要,但这极大的增加了运维工作量,以及浪费机器资源。所有集中式持久化元数据的方案都有类似问题,就算元数据存放到数据库,同样会占用一个规模不小的数据库集群(试想,这里是可能有千亿万亿个文件的元数据要集中持久化)。再补充一点,各个文件的元数据没必要集中持久化,这没有意义。文件(此处的文件指的是posix接口的文件)存储中的路径管理,可以考虑集中持久化到RocksDB或者MySQL等,一般来说互联网场景下文件存储的应用规模不大(网盘除外,网盘一般都是存到MySQL上),绝大多数都是对象存储。

  典型问题的处理思路:
  1)海量文件(数量万亿级)的管理”的解决方式:
  小文件(用户的文件或对象,或块)合并为大文件管理和存储。各个小文件在大文件内部依次紧密存放(这样小文件的修改就不方便,后面有讲),且每个小文件有一个固定长度的元数据区,元数据区包含该小文件的id,size,delete_flag,crc,user_id等。例如:大文件大小为1GB(集群中大文件大小可有多种规格,以适应对象存储,文件存储和块存储),小文件大小不定(通常是几十KB)。这样整个集群大文件数据最多亿级,小文件数据可以过万亿。
  大文件以物理文件方式直接存放到磁盘上。每个大文件3副本(或其他副本数,或EC)。
  小文件名(很重要)由大文件名(一般是UUID,长度20多位)及小文件在大文件内部的id组成,格式为:大文件名小文件ID

  大文件的元数据(主要是大文件所在的存储节点ip,version等)不专门持久化(这是一个创新点,持久化会带来一些列问题,增加了系统的复杂性),当然元数据自然的持久化在其各个副本的数据中。存储节点启动时向管理节点汇报各自所拥有的大文件名称及version等,这样管理节点就能汇总到所有的大文件及其副本的位置(包括副本缺失也能知道)。大文件元数据直接存放在管理节点内存中(管理节点内存中不存放小文件元数据,内存不够)。

  小文件从存储节点的磁盘加载后元数据存放在存储节点内存中(单个存储节点上的小文件数据有限,基本可以全部加载到内存中,或采用LRU算法来淘汰)。

  这样,读写小文件时(肯定知道小文件名,也就知道了对应的大文件名),客户端首先位到管理节点找到小文件对应的大文件所在的存储节点,然后访问到主副本的存储节点(主副本规则,后面讲),打开大文件,再根据ID找到小文件的位置,进行读写。
  

  “2)数据高可靠”的解决方式:
  用多副本(通常是3副本)或EC模式来保证。
  一致性协议:用raft(其实raft不适合高并发场景,心跳开销太大太耗性能,跨机房部署时光纤估计被其耗光,然后写数据时写放大一倍),或者,自研一套一致性协议(借助管理节点和客户端)。

  “3)服务高可用”的解决方式:
  管理节点采用主备(其实也可以不主备,同时多写)方式,用raft无日志状态下的选举(这个要简单很多)来确定主节点。
  存储节点每个文件在不同机器上总计有3副本。同时有故障自动处理机制来保证及时发现和补全丢失的副本。
  扩容缩容,机器故障(丢失1个副本)时都不影响数据读写。

  “4)存储机器扩容缩容”的解决方式:
  扩容时直接加存储节点即可,可以不用平衡数据(可选择在凌晨时平衡数据)。
  缩容时,只涉及本台机器数据的补全(补全的同时依据平衡了)。

  其实,我这个方案中,所有的存储节点,除了考虑故障域,所有存储节点之间完全没有关联,完全对等。有些其他方案中把存储节点分组或分区,这对扩容缩容以及故障处理很不利,也不能实现热点数据的随意迁移。这比Ceph好太多,Ceph数据量大的时候,平衡数据可能需要几十小时,且期间不能读写。Ceph的crush算法看似不错,其实完全没有实际意义,反而导致了一些列严重的缺陷。

  “5)故障自动处理”的解决方式:
  管理节点会负责监控存储节点的健康状态,在发现存储节点故障后,按照一定的策略来补全大文件的副本。
  管理节点自身通过主备切换(或者分组多写及分组调整)模式来实现故障自动处理。

  我总结下创新点:
  1)管理节点不持久化文件的元数据(自然的持久化在存储节点的各个副本数据中)。这能很大程度的减低系统的复杂度,提高性能。
  2)元数据分散持久化(自然的持久化在存储节点的各个副本数据中,和内容数据放到一起),这能保证集群基本无容量上限(万亿级文件,数千台存储节点)。
  3)管理节点多写。这也是集群无容量上限的一个保证。
  4)一致性协议不采用raft(raft真不适合高并发场景)。

 

  其他问题:

  1)修改文件的问题。由于各个小文件在大文件内部依次紧密存放,因此修改文件成为一个难题(如果增加了文件大小,则没有空余空间可用)。可以采用链接的方式来解决,即修改时重新创建一个全新的文件(可能被存放到其他存储节点的其他大文件中),然后在当前小文件的元数据上存放一个新小文件名称作为链接,后续读写该小文件时,通过该链接转到新的地方去。这样性能上会差一些,但是客观的讲,互联网场景下一般修改操作很少(至于块存储,因为对应的小文件大小固定,可以直接修改)。

  2)自定义一致性协议,性能和简单性都比raft好很多。专门写了一篇:https://mp.csdn.net/console/editor/html/105975918

  有兴趣的同学可以讨论下,这个大方案有没有什么问题。欢迎指出。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值