Facebook Delos 中的虚拟共识协议
本文整理自OSDI 2020 Virtual Consensus in Delos 论文演讲,探讨了分布式系统中控制面的存储组件的实现,提出了一种基于分层抽象思想的分布式架构。其核心在于提出了一种逻辑协议层,使得物理层可以按需进行实现、移植和迁移,有点类似于单机系统中虚拟内存之于物理内存的味道。
背景
Facebook 的软件系统栈一般包括两层:上层是数据平面, 下层是控制平面。
数据平面包括大量的服务,他们需要存储和处理海量数据。控制平面用来支撑数据平面,起到一些控制作用:调度、配置、命名、切片等等。控制平面通常是有状态的,比如控制的元信息,为了存储这些元信息,控制平面需要有自己的存储。控制平面对存储有以下要求:
-
容错:零依赖、可持久化、高可用。 -
丰富的 API:事务,范围查询,二级索引。
在 17 年的时候, Facebook 使用几种组件来充当控制平面的存储,包括:
-
MySQL:API 丰富,表达能力强,但是不支持容错。 -
ZooKeeper:容错,零依赖,但是 API 表达能力弱。
可以看出,他们都不能很好的同时满足控制平面对存储的需求。此外,作为单体架构,上述组件都比较难改造成同时支持容错和丰富 API 的系统。此外,还有一大问题,团队当时所面临的工期非常紧。最终,他们交出的答卷是 —— Delos。
架构
Delos 是一个基于共享日志(shared log)的控制面存储系统。db 层的实例通过 append 和 read 与共享日志进行交互,从而保持对外状态的一致性。根据近几十年的研究,使用共享日志作为 API,可以很好的向 db 层隐藏共识协议的大量细节。
读写流程
存储服务可以分为两层,db API 层和共享日志 runtime 层。如上图,以表格存储为例,在上层,DelosTable 负责提供表格存储的 API;在下层,DelosRuntime 负责共享日志的读写。则,一个典型的写流程如下:
-
客户端发起一个写请求 -
DelosTable 层将其转发给 DelosRuntime -
DelosRuntime 将该请求序列化后追加到共享日志 -
各个服务器侦听到该追加后,读取其内容,以同一种顺序将其应用到本地状态机
在该架构中,有两个关键的设计点:
-
共享日志层提供了具有线性一致性保证的极简 API -
基于该简明 API,上层可以方便的提供不同存储接口的实现
虚拟共识
到此为止,该架构设计看起来相当简单,但我们知道,复杂性只能被转移,但不可能凭空消失。可以看到,最复杂的共识协议被隐藏在了共享日志后面,于是问题随之而来:
-
我们需要如何快速实现一个满足共识协议的的共享日志组件? -
随着技术的发展,如果我们之后想用更好的共识协议,该如何进行替换?
为了解决这些问题,Delos 提出了虚拟共识(Virtual Consensus)。通过抽象出一层虚拟共识协议,Delos 的共享日志组件可以快速复用现有实现,比如 Zookeeper;之后为了提高性能,也可以借助此该层对下层进行不停机迁移。
在 Delos 中,虚拟共识协议的承载层被称为 VirtualLog。对上,db 层基于 VirtualLog 层进行实现;对下,VirtualLog 被映射成一组物理共享日志,称为 Loglets。每个 loget 提供和共享日志同样的 API,外加一个 seal 命令。一旦被 seal,Loglet 便不再接受追加。为了存储 VirtualLog 逻辑空间到 Loglets 物理空间的映射,Delos 引入了新的组件:MetaStore。
MetaStore 是一个带版本的简单 KV 存储。通过存储的不同版本的 Loglet 的切换,VirtualLog 就自然的将流量打到新的 Loglet 上。如下图展示了 VirtualLog 向 MetaStore put 一个新版本(ver0 -> ver1)的映射信息,将流量无宕机的从 Zookeeper 切换到了 LogDevice 的过程 。
定制 Loglet
在满足基本需求后,为了进一步提升性能,Delos 想自己定制 Loglet,以满足以下特点:
-
简单:simple -
快速:fast -
容错:fault tolerant
NativeLoglet
只实现其中两点,比较容易;若要三者皆得,有点困难。Delos 通过分治策略,将其分解为两个组件:
-
MetaStore:进行容错 -
Loglet:专注性能
此时,所有一致性的来源便都移到了 MetaStore 之上。而 MetaStore 功能相对简单,只需保存空间映射,并提供容错的 reconfiguration 源语(即对映射进行操作,比如 loglet 切换),且 reconfiguration 是个低频操作。因此 MetaStore 的实现无需关注性能优化,只需要按照 Lamport 最初的 Paxos 进行实现即可,可以保证 MetaStore 实现的简洁性。
同时,将 Loglet 职能弱化,不再需要提供完全的容错机制,只需提供一个高可用的 seal 命令即可。如此一来,当一个 Loget 不可用时,VirtualLog 只需将其 seal,然后将流量切向其他 Loglet 即可。
据此,Delos 实现了新的 Loglet 实例——NativeLoglet 。
直观感觉来说,NativeLoglet 类似一个弱化版的 LogDevice。其交互流程如下:
-
正常运行时,集群中某个 LogServer 充当 Sequencer -
所有 DelosRuntime 发出的 Append 请求都要通过 Sequencer 定序后,追加到各个 LogServer -
当 Sequencer 所在 LogServer 宕机后,DelosRuntime 直接向所有 LogServer 发送 CheckTail 请求,以 quorum 协议确定 tail -
所有 DelosRuntime 都可以发起 seal 请求,对 NativeLoglet 进行 seal
注意,NativeLoget 中所有 LogServer 可以和 DelosRuntime 部署在一块(称作 Converged 模式),也可以单独部署(称作 Disaggregated 模式)。前者能够获取更好的本地读性能,并且让数据库实例和日志实例生命周期绑定。后者将数据库层和日志层分离,可以避免不同层的资源争夺,并允许各自按需伸缩。
下图是一个替换 NativeLoglet 后的性能提升对比:
StripedLoglet
为了进一步提升性能,在 VirtualLog 的抽象下,Delos 利用分片思想又造出了一种叫做 StripedLoglet 的实现。该实现在底层组合了多个 Loglets 实例,当 Append 请求到来时,将其 round robin 的打到各个底层 Loglet 系统中,从而极大提升性能。
此外,StripedLoglet 允许多个 DelosRuntime 使用不同策略进行并行 Append,并且允许暂时的空洞存在,之后使用类似滑动窗口的机制,进行捎带 ACK,从而进一步提升性能。
底层多个 Loglet 系统可以视情况共享一个集群或分散到多个集群。
The Last Thing:VirtualLog Triming
此外值得一说的细节是,VirtualLog 提供的 Trim 操作。得益于虚拟化的抽象,Delos 可以通过删除映射,将老的日志进行移除。当然,一种更好的做法是,将老的日志移动到 BackupLoget 的冷集群中,然后改变映射,对外提供一种无限日志的抽象,进而允许按年龄对不同日志段进行细粒度的存储控制。
另一方面,通过修改 MetaStore 中的映射,Delos 允许修改单个日志记录,对某些有问题的日志进行删除,以避免系统 hang 住或者反复重启宕机。这是之前的一致性协议无法做到的。
结语
Delos 位于 Facebook 系统的底层(用于控制面的存储),它采用分层的设计,使得:
-
在项目之初,可以在某些层复用现有系统,进行快速上线,投入使用。 -
在上线之后,允许不停机的替换更高性能的组件、实验更新的一致性协议。
虚拟共识之于分布式系统,有点像虚拟内存之于单机系统,通过分层解耦,使得设计者在系统构建时有更多腾挪空间。至于该思想是否能够实至名归,还得等待时间和实践的检验。
参考
-
OSDI 20 该论文的讲解视频:https://www.youtube.com/watch?v=wd-GC_XhA2g
-
谷歌工程文章:https://engineering.fb.com/2019/06/06/data-center-engineering/delos/
-
论文 Virtual Consensus in Delos:https://research.fb.com/publications/virtual-consensus-in-delos/
本文分享自微信公众号 - 分布式点滴(distributed-system)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
微服务架构Day21-SpringCloud之分布式配置中心
SpringCloud Config SpringCloud整合了微服务中的整体解决方案:分布式配置中心,分布式锁,分布式任务调度平台,分布式事务,分布式日志收集 产生背景:在微服务中如果使用传统的方式管理配置文件,配置文件管理器将会非常复杂;在生产环境中,配置文件改变时,需要重新配置war包,重新读取配置文件信息到JVM中 SpringCloud Config分布式配置中心: 在微服务中使用同一个服务器管理所有服务配置文件信息 在服务器运行的过程中,如果配置文件发生改变,不需要重启服务器就可以实时更改配置文件信息 Config配置文件的实时刷新不等同于热部署 热部署的底层实现其实还是重启服务器,不适合于生产环境,只适合于本地的开发测试 Config架构 当一个系统中的配置文件发生改变的时候,需要重新启动该服务,才能使配置文件生效 SpringCloud Config可以实现微服务中所有系统的配置文件的统一管理,还可以实现当配置文件发生变化时,系统会自动更新获取新的配置 分布式配置中心框架 阿波罗: 携程的分布式配置中心框架,有图形界面可以管理配置文件信息,配置文件信息存放在数据库中 ...
- 下一篇
一文读懂 SuperEdge 拓扑算法
杜杨浩,腾讯云高级工程师,热衷于开源、容器和Kubernetes。目前主要从事镜像仓库、Kubernetes集群高可用&备份还原,以及边缘计算相关研发工作。 前言 SuperEdge 介绍 SuperEdge 是基于原生 Kubernetes 的边缘容器管理系统。该系统把云原生能力扩展到边缘侧,很好的实现了云端对边缘端的管理和控制。同时 superedge 自研了 service group 实现了基于边缘计算的服务访问控制,极大简化了应用从云端部署到边缘端的过程。 SuperEdgeservicegroup拓扑感知特性 SuperEdge service group 利用 application-grid-wrapper 实现拓扑感知,完成了同一个 nodeunit 内服务的闭环访问。 在深入分析 application-grid-wrapper 之前,这里先简单介绍一下社区 Kubernetes 原生支持的拓扑感知特性[1] Kubernetes service topology awareness 特性于v1.17发布 alpha 版本,用于实现路由拓扑以及就近访问特性。...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- CentOS8安装Docker,最新的服务器搭配容器使用
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Docker安装Oracle12C,快速搭建Oracle学习环境
- CentOS7设置SWAP分区,小内存服务器的救世主
- CentOS7安装Docker,走上虚拟化容器引擎之路