木鸟杂记

分布式系统,程序语言,算法设计

Meta 链式复制的对象存储——Delta

来源https://engineering.fb.com/2022/05/04/data-infrastructure/delta/

导读:偶然看到群里同学分享的 Meta 博客新公开的高可用、强一致、链式复制的对象存储。由于我也做过一段时间的对象存储,也分享过 Facebook 家的小文件存储:Haystack(做 batch) 和 F4(冷热分开、EC), 顿时来了兴致,好奇这次 Meta 又带来了什么干货。

看完之后觉得的确有点意思,下面简单梳理下文章要点,感兴趣的同学可以去看看博客原文,还有华人小姐姐解说的相关视频哦。

Delta 是什么?

Delta 是简单、可靠、可扩展、低依赖的对象存储,只提供四个基本操作:put、get、delete 和 list。在架构设计上,Delta 牺牲了读写延迟存储效率,来换取架构的简单性可靠性

Delta 不是:

  1. 通用存储系统。Delta 只追求弹性、可靠和最小依赖。
  2. 文件系统。Delta 只是简单的对象存储,不提供 POSIX 语义。
  3. 为存储效率而优化的系统。Delta 并没有针对存储效率、延迟和吞吐做优化,而是专注简单和弹性。

作者:木鸟杂记 https://www.qtmuniao.com/2022/05/06/meta-object-store-delta 转载请注明出处

总结来说,定位是一个基座式存储服务,就是性能可以不高,但要简单、弹性、可靠。其定位坐标如下图:

storage-system-cordinate-system.png

Delta 的架构有何特点?

  1. 链式复制

对于一个逻辑上的 Bucket(对象存储的命名空间)中的数据,首先使用一致性哈希进行分片(Partition),对于每个分片,使用链式复制(Chain Replication)进行冗余。通常每个分片有四个副本,每个副本放在不同的容错阈。

chain-with-4-nodes.png

读写流程:所有的写入都在链表头,依照链表顺序复制后,等到链表尾复制完成后返回成功(同步复制);所有的读取都被路由到链表尾,以保证强一致

可以看出,由于是同步写,Delta 的写入延迟比较高;由于是只读尾节点,读吞吐也不高。

当然,Delta 对读取稍稍做了个优化——分摊查询,即允许客户端读任何一个副本,但该副本必须要和尾节点通信确定数据可靠版本(clean version)后才能返回数据给客户端,以保证一致性。

read-all-nodes.png

其依据是,相比客户端查询,内部版本确认查询要轻量的多。

  1. 投票剔除和挂尾加回

Delta 通过心跳和投票来剔除故障节点:即当同时有一定数量的节点标记某一个节点心跳超时后,就将该节点上所有副本从复制链中剔除。其中有两个阈值需要慎重选择:

  • 心跳超时。过短的话,受网络抖动影响太大,过长的话又会加重相关链的写入延迟。
  • 可疑票数。设置为 1 显然不行,因为很可能有两个节点间网络不好会互相投票;过多也不行,会导致故障节点在链中停留过长时间。Delta 一般设置为 2,并且配合自动化的机器故障修复。

在故障节点修复之后,可以通过一系列操作加回副本链:

  1. 将其上副本重新追加回原链结尾
  2. 读取上游节点(原尾结点)同步数据
  3. 同步完成前将读请求都路由给上游节点
  4. 同步完成后变成新的正常尾结点

Delta-Visuals_v03-04.gif

  1. 自动修复

Delta 使用一个控制平面服务(CPS,control plane service)对故障节点进行自动检修。每个 CPS 实例监控一组 Delta Bucket 列表,其主要策略有:

  • 在修复桶时,维持其副本的合理故障阈分布
  • 保证所有服务器上的复制链均匀分布,避免局部过载。
  • 在链中副本缺失时,倾向修复而非新建,以最小化数据复制。
  • 在添加新的服务器到链中,会对服务器进行严格的健康检查。
  • 维护一个健康服务器池,在某个链过半副本故障时,才往其中添加一个节点。

解释下最后一条:即能修复先修复,只有坏到不能再坏(超过一半)才从池子中拨出一个副本给他,从而保证池子里有充足备用弹药。

文中还提到了全球地理复制和与用归档服务进行冷备。并提到 Delta 下一步是想充当 Meta 中所有需要数据备份和恢复的服务的存储后端。


我是青藤木鸟,一个喜欢摄影的分布式系统程序员。如果你觉得文章还不错,欢迎关注我的公众号:“木鸟杂记”,比心~
wx-distributed-system-s.jpg