Facebook Delos 中的虚拟共识协议

背景
Facebook 的软件系统栈一般包括两层:上层是数据平面, 下层是控制平面。

facebook software stack

数据平面包括大量的服务,他们需要存储和处理海量数据。控制平面用来支撑数据平面,起到一些控制作用:调度、配置、命名、切片等等。控制平面通常是有状态的,比如控制的元信息,为了存储这些元信息,控制平面需要有自己的存储。控制平面对存储有以下要求:

容错:零依赖、可持久化、高可用。
丰富的 API:事务,范围查询,二级索引。
在 17 年的时候,  Facebook 使用几种组件来充当控制平面的存储,包括:

MySQL:API 丰富,表达能力强,但是不支持容错。
ZooKeeper:容错,零依赖,但是 API 表达能力弱。
可以看出,他们都不能很好的同时满足控制平面对存储的需求。此外,作为单体架构,上述组件都比较难改造成同时支持容错和丰富 API 的系统。此外,还有一大问题,团队当时所面临的工期非常紧。最终,他们交出的答卷是 —— Delos。

架构
Delos 是一个基于共享日志(shared log)的控制面存储系统。db 层的实例通过 append 和 read 与共享日志进行交互,从而保持对外状态的一致性。根据近几十年的研究,使用共享日志作为 API,可以很好的向 db 层隐藏共识协议的大量细节。

design based sharedlog

读写流程

 

read write procedure via shared log

存储服务可以分为两层,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 的过程 。

virtualizing consensus via the VirtualLog

定制 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 。

 

the 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 模式)。前者能够获取更好的本地读性能,并且让数据库实例和日志实例生命周期绑定。后者将数据库层和日志层分离,可以避免不同层的资源争夺,并允许各自按需伸缩。

converged vs disaggregated

下图是一个替换 NativeLoglet 后的性能提升对比:

 

NativeLoglet compare

StripedLoglet
为了进一步提升性能,在 VirtualLog 的抽象下,Delos 利用分片思想又造出了一种叫做 StripedLoglet 的实现。该实现在底层组合了多个 Loglets 实例,当 Append 请求到来时,将其 round robin 的打到各个底层 Loglet 系统中,从而极大提升性能。

此外,StripedLoglet 允许多个 DelosRuntime 使用不同策略进行并行 Append,并且允许暂时的空洞存在,之后使用类似滑动窗口的机制,进行捎带 ACK,从而进一步提升性能。

底层多个 Loglet 系统可以视情况共享一个集群或分散到多个集群.

striped loglet

The Last Thing:VirtualLog Triming
此外值得一说的细节是,VirtualLog 提供的 Trim 操作。得益于虚拟化的抽象,Delos 可以通过删除映射,将老的日志进行移除。当然,一种更好的做法是,将老的日志移动到 BackupLoget 的冷集群中,然后改变映射,对外提供一种无限日志的抽象,进而允许按年龄对不同日志段进行细粒度的存储控制。

另一方面,通过修改 MetaStore 中的映射,Delos 允许修改单个日志记录,对某些有问题的日志进行删除,以避免系统 hang 住或者反复重启宕机。这是之前的一致性协议无法做到的。

 

trimming the VirtualLog

结语
Delos 位于 Facebook 系统的底层(用于控制面的存储),它采用分层的设计,使得:

在项目之初,可以在某些层复用现有系统,进行快速上线,投入使用。
在上线之后,允许不停机的替换更高性能的组件、实验更新的一致性协议。

summary

虚拟共识之于分布式系统,有点像虚拟内存之于单机系统,通过分层解耦,使得设计者在系统构建时有更多腾挪空间。至于该思想是否能够实至名归,还得等待时间和实践的检验。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/94119.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【React】组件实例三大属性state、props、refs

state React 把组件看成是一个状态机(State Machines)。通过与用户的交互,实现不同状态,然后渲染 UI,让用户界面和数据保持一致。 React 里,只需更新组件的 state,然后根据新的 state 重新渲染用…

Linux实用操作(固定IP、进程控制、监控、文件解压缩)

目录 一、快捷键 1、ctrl c强制停止 2、ctrl d退出或登出 3、历史命令搜索history 4、光标移动快捷键 5、清屏 二、软件安装 1、CentOS的yum命令 2、Ubantu的apt命令 三、systemctl命令 四、软连接 五、日期、时区 1、date命令 2、修改Linux时区为东八区 3、nt…

车牌文本检测与识别:License Plate Recognition Based On Multi-Angle View Model

论文作者:Dat Tran-Anh,Khanh Linh Tran,Hoai-Nam Vu 作者单位:Thuyloi University;Posts and Telecommunications Institute of Technology 论文链接:http://arxiv.org/abs/2309.12972v1 内容简介: 1)方向&#x…

2023蓝帽杯半决赛电子取证+CTF部分题解

文章目录 电子取证123456789101112131415 CTFWeb | MyLinuxBotWeb | AirticleShareCrypto | ezrsaPwn | AdminPwn | uafmisc|排排坐吃吃果果 电子取证 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 CTF Web | MyLinuxBot Web | AirticleShare import requests import times reques…

Java中处理千万级数据的最佳实践:性能优化指南

在今天的数字化时代,处理大规模数据已经成为许多Java应用程序的核心任务。无论您是构建数据分析工具、实现实时监控系统,还是处理大规模日志文件,性能优化都是确保应用程序能够高效运行的关键因素。本指南将介绍一系列最佳实践,帮…

TinyWebServer学习笔记-互斥锁、信号量、条件变量

为什么要使用锁、信号量、条件变量? 网站不可能是单线程的,否则网站的性能和响应都会收到严重的影响。因此,这个项目一定是运行在多线程条件下的。而在多线程条件下,对共享资源的互斥访问就极其重要。 为什么要将资源封装成类&a…

IDEA中的神仙插件——Smart Input (自动切换输入法)

推荐专栏:开发环境配置攻略 致力于记录学习过程中各种软件的安装及环境配置操作,并提供详细的步骤说明和丰富的配图。涵盖了 Java、Python、IntelliJ IDEA、Tomcat、MySQL 等常见开发工具和服务器组件的配置,为初学者提供一个实用、全面的配置…

Pandas进阶修炼120题-第五期(一些补充,101-120题)

目录 往期内容:第一期:Pandas基础(1-20题)第二期:Pandas数据处理(21-50题)第三期:Pandas金融数据处理(51-80题)第四期:当Pandas遇上NumPy&#xf…

Vue2 第一次学习

本章为超级浓缩版,文章过于短,方便复习使用哦~ 文章目录 1. 简单引入 vue.js2. 指令2.1 事件绑定指令 v-on (简写 )2.2 内容渲染指令2.3 双向绑定指令 v-model2.4 属性绑定指令 v-bind (简写 : )2.5 条件渲染指令2.6 循环指令 v-for 3. vue 其他知识3.1 侦听器 watch3.2 计算属…

WOL唤醒配置(以太网、PHY、MAC)

目录 wol 以太网 MAC PHY RMII 通信配置 总结 wol Wake-on-LAN简称WOL,WOL(网络唤醒) 是一种标准网络协议,它的功效在于让已经进入休眠状态或关机状态的计算机,透过局域网(多半为以太网&#xff…

lv8 嵌入式开发-网络编程开发 01什么是互联网

目录 1 计算机网络的定义与分类 1.1 按照网络的作用范围进行分类 1.2 按照网络的使用者进行分类 2 网络的网络 2.1 名词解释 2.2 边缘与核心 3 互联网基础结构发展的三个阶段 3.1 第一阶段:1969 – 1990 3.2 第二阶段:1985 – 1993 3.3 第三阶…

HTML5高级部分

目录 一、拖拽API1.1 拖拽元素1.2 监听事件1.3 dataTransfer传递数据 二、媒体API2.1 常用监听事件2.2 常用API 三、画布API3.1 canvas 标签3.2 创建canvas对象3.3 常用API 四、地理API4.1 方法 一、拖拽API 1.1 拖拽元素 页面中设置了draggable"true"的元素可以进…

【Java-LangChain:使用 ChatGPT API 搭建系统-11】用 ChatGPT API 构建系统 总结篇

第十一章,用 ChatGPT API 构建系统 总结篇 本课程详细介绍了 LLM 工作原理,包括分词器(tokenizer)的细节、评估用户输入的质量和安全性的方法、使用思维链作为 Prompt、通过链式 Prompt 分割任务以及返回用户前检查输出等。 本课…

linux MySQL高阶语句

linux MySQL高阶语句 1、MySQL高级语言1.1order by排序1.2group by分组1.3limit前几行1.4as别名1.5通配符1.6子查询1.7in1.8not in1.9exists 2、视图2.1视图概念2.2功能2.3应用场景2.4视图和表的区别和联系2.5创建视图 3、null值3.1null值3.2null值与空值的区别3.3验证null和空…

僵尸进程的产生原因和解决方法

僵尸进程的产生原因 当一个进程(通常是父进程)创建了一个子进程,但是在子进程终止后,父进程没有及时处理子进程的终止状态,就会导致僵尸进程的产生。这个时候,子进程虽然已经终止,但是其进程表…

Autowired和Resource的关系

相同点对于下面的代码来说,如果是Spring容器的话,两个注解的功能基本是等价的,他们都可以将bean注入到对应的field中 不同点但是请注意,这里说的是基本相同,说明还是有一些不同点的: byName和byType匹配顺…

IDEA的Maven换源

前言 IDEA是个好东西,但是使用maven项目时可能会让人很难受,要么是非常慢,要么直接下载不了。所以我们需要给IDEA自带maven换源,保证我们的下载速度。 具体操作 打开IDEA安装路径,然后打开下面的文件夹 plugins\m…

Armv8/9-A cpu在安全/非安全世界切换时,是否需要对共享内存进行cache维护操作?

安全之安全(security)博客目录导读 问题:当Armv8/9-A cpu在安全世界和非安全世界之间切换时,是否需要对这两个世界的共享内存进行缓存维护操作? 答案: 不需要。 1)运行在非安全世界的软件只能对内存进行非安全访问&#xff0c…

第10章 MySQL(一)

10.1 谈谈MySQL的架构 难度:★★ 重点:★ 白话解析 要想彻底的理解MySQL,它的架构一定要先弄清楚,当Java程序员通过JDBC或者Mybatis去执行一条SQL的时候,到底经历了什么。下边先看一幅图: 户端:Java程序员通过JDBC或者Mybatis去拿MySQL的驱动程序,实际上就是拿客户端。…

java基础之构造器

构造器 学习java对于构造器应该很熟悉,但是有些人会认为构造器不是必要的,这就是对于构造器没有深入的了解。 每一个java类中都必须至少有一个显式或隐式的构造器,很多时候看到类中并没有定义构造器,有人会认为构造器不是必须的&a…