图数据库 | 18、高可用分布式设计(中)

news2025/7/4 19:40:36

上文我们聊了在设计高性能、高可用图数据库的时候,从单实例、单节点出发,一般有3种架构演进选项:主备高可用,今天我们具体讲讲分布式共识,以及大规模水平分布式

主备高可用、分布式共识、大规模水平分布式,我们都知道这3套系统的实现复杂度是从低到高渐进的,但这并不意味着复杂度更高的系统在不同的应用场景、用户需求、查询模式、查询复杂度、数据特征条件下就能获得更好的效果。


分布式共识系统

前面提到即便在最简单的主备系统架构中也可能发生系统内无法保证一致性的情况,这是因为任何分布式系统在本质上都是异步分布式。所有操作(网络传输、数据处理、发送回执、信息同步、程序启动或重启等)都需要时间来完成,任何交易、任何事务处理在一个实例内都是异步的,而在多个实例之间这种异步性会被放大很多。分布式系统设计最重要的一个原则就是与异步性共存,不追求完美的一致性,但可以假设整个系统在大部分时间内是正常工作的,即便部分进程或网络出现问题,整个系统依然可以对外提供服务。

分布式共识系统,特别是分布式共识算法就由此应运而生,被用来保证即便在分布式系统中出现了各种各样的问题,但是整体服务依然可以保持在线。

分布式共识算法有3个核心特性:合法有效(validated proposal)​、达成一致(reaching agreement或unanimity)​、快速终止(processcan be terminated)​。

合法有效指的是进程间的指令信息传播需要基于合理有效的数据,且能让有效的进程集合达成一致,并且最终形成共识,进而终止同步过程的时耗需要在合理的、较短的时间内完成。在高性能分布式系统中可毫秒级完成同步,而在较大规模跨地域的分布式共识系统中,可能会出现秒级甚至需要人工介入的分钟级形成共识,具体的终止时间延迟取决于具体的业务需求。

达成一致等同于形成共识,类似于多个进程间的民主选举,一旦它们形成了共识,任何参与了选举的进程都不再允许对结果产生异议或按照与结果不符的方式或内容执行任务——这种情况就是我们前面提到过的分布式系统无法解决的“两军通信问题”​“拜占庭将军问题”​。

图1示意了多任务(多进程)间形成共识的过程,这一过程与我们日常生活中的行为并无本质不同。

图1: 多任务间形成共识


A、B、C、D四个人在一起讨论晚上去哪里,一开始A提议去看电影,得到了B的赞同,但是C很快提出去吃晚餐,D赞同C的提议,随后B改口赞同C的提议,最终A也改为同意C的提议。此时,四人达成了晚上去吃晚餐的共识。这就是多任务共识形成的简单例子。在实际的分布式共识算法中还会引入如角色、阶段以及如何终止共识等问题,下面逐一分析。

形成共识的过程需要有明确的终止算法,否则就会出现悬而不决、无限等待的问题。例如当某个实例(进程)下线后,剩余进程如果无限等待其重新上线,或是如图1所示,A、B、C、D四个进程出现层出不穷的新方案,以至于四人永远无法达成共识。共识算法需要考虑这些情况,并规避其发生。本质上,无论采用何种跨进程的集群内通信方式,都要使用尽可能简洁的算法,让共识的达成(进而终止)代价较低。

那么,分布式共识系统应该采用何种通信手段呢?前面提到过网络系统的3种通信方式:中心化(广播式)​、去中心化(分层区域广播或多播式)以及点对点分布式,对小型分布式系统而言,最简单和最直接的方式是广播式,因为发起广播者与信息接收者之间的互动逻辑决定了这个交互过程是属于“尽人事听天命”类型的单向一次性传送模式,还是其他更可靠的交互模式。

理解这个过程需要考虑这样一种可能发生的情况,即如果发起者A在发出请求给B、C后下线,但是并没有向D发送,那么在广播算法中,就需要考虑加上B、C可以向D继续广播的逻辑。从通信的复杂度角度看,这样的实现就是一种“可靠广播”模式,在有N个实例的分布式系统中,其复杂度为O(N^{2}),显然,这种漫灌式重度通信模式(floodingcommunication)对于大型分布式系统是不合适的,但是它已经具备了通过冗余通信来实现系统完整性、一致性的特征。

下面分析如何在分布式共识通信的过程中保证消息的有序性,即至少需要实现2个功能:多消息的事务性(原子性、不可分割性)和序列性。

一种比较简单的原子广播算法是分布式KV项目Apache Zookeeper中的ZAB(Zookeeper Atomic Broadcast)​,它把Zookeeper集群内的所有进程分为两个角色:领导者(leader)和跟随者(follower)​,3种状态:跟随(following)​、领导(leading)和选举(election)​;它的通信协议分为4个阶段:启动选举阶段(leader election phase)​、发现阶段(discovery phase)​、同步阶段(synchronization phase)​、广播阶段(broadcasting phase)​。

在启动选举阶段(阶段0)​,某个进程在选举状态中开始执行启动选举算法,并找到集群内的其他进程投票成为领导者。

在发现阶段(阶段1)​,进程检查选票并判断是否要成为两个角色之一,被选举为潜在领导者的进程称作意向领导(prospective leader)​,之后该进程通过与其他跟随进程通信发现最新的被接受的事务执行顺序。

在同步阶段(阶段2)​,发现过程被终止,跟随进程通过意向领导更新的历史记录进行同步。如果跟随进程自身的历史记录不晚于意向领导的历史,则向意向领导进程发送确认信息。当意向领导得到了主体选举人(quorum)的确认后,它会发送确认(commit)信息,这时意向领导成为确认领导(established leader)​。该阶段的算法逻辑如下:

在广播阶段(阶段3)​,如果没有新的宕机类问题发生,集群会一直保持在本阶段。在此阶段,不会出现两个领导进程,当前领导进程会允许新的跟随者加入,并接受事务广播信息的同步。

ZAB的阶段1~3都采用异步的方式,并通过定期的跟随进程与领导进程间的心跳信息来探测是否出现故障。如果领导进程在预定的超时时间内没有收到心跳,它会切换至选举状态,并进入阶段0,同样地,跟随进程也可以在没有收到领导进程心跳后进入阶段0。

在ZAB的具体实现逻辑中,leader选举是最核心的部分,ZAB采用的策略是拥有最新历史记录的进程会被选举为leader,并且假设拥有全部已提交事务(commitedtransactions)的进程同样拥有最新的已提议事务(most recent proposed transaction)​。当然,这个假设的前提是集群内的ID序列化及顺序增长,这一假设让leader选举的逻辑大幅简化,因此称为快速领导选举(Fast Leader Election,FLE)​。即便如此,FLE过程中的判断逻辑,特别是各种边界情况的考量依然很多,下面是节选的参与选举进程的FLE实现代码逻辑: 

 

ZAB最早是作为Yahoo!内部Hadoop项目的一个子项目,后来被拆分独立出来作为一款分布式服务器间进程通信及同步框架,并在2010年后成为Apache开源社区中的一个顶级项目。从上面的伪码中就可以看出,ZAB所采用的算法逻辑和通信步骤较为复杂。类似地,Paxos类算法的实现对于跨地理区域的系统实例间时钟同步有着严苛的要求,且算法逻辑复杂,不容易被理解。头部企业谷歌在其Spanner系统中通过原子钟的帮助实现基于Paxos的大规模分布式共识系统,但是对缺少同等系统架构把控能力的企业而言,Paxos就显得门槛过高了。 

在2013年之后,更简单、可解释的分布式共识算法应运而生,其中最知名的是2014年DiegoOngaro提出的RAFT算法及一种称作LogCabin的代码实现。

 在RAFT算法中,集群内的每个共识算法参与进程有3种角色:候选者(candidate)​、领导者(leader)和跟随者(follower)​。

与Poxos通过时钟同步来保证数据(事务)全局顺序一致不同(但是类似于ZAB)​,RAFT把时间块切分为terms(选举任期,类似于ZAB中的epoch)​,在每个任期期间(系统采用唯一的ID来标识每个任期,以保证不会出现任期冲突)​,领导者具有唯一性和稳定性。

RAFT算法有3个主要组件(或阶段)​:选举阶段、定期心跳阶段和广播及日志复制阶段。

图2示意了在一个3节点的RAFT集群中客户端与服务器集群的互动,整个流程围绕领导者角色进程展开,可分解为10步,而这只覆盖了RAFT算法的广播及日志复制阶段。 

图2:RAFT集群C/S工作流程步骤分解

如图3所示,3种角色及所负责的任务内容如下:

· 跟随者,不会主动发起任何通信,只被动接收RPC调用(Remote Procedure Calls)​。

· 候选者,会发起新的选举,对选举任期进行增量控制,发出选票,或重启以上任务。

在该过程中,只有含有全部已提交命令的候选者会成为领导者,并通过RPC调用的方式通知其他候选者选举结果,并避免出现split vote(平票)的问题(在RAFT算法中,通过随机选举超时,例如在0.15~0.3s间随机制造超时来避免因两个实例的候选进程同时发出导致选票计数出现平票)​。

另外,每个进程都维护了自己的一套日志,在原生的RAFT算法实现中称为logcabin(木筏)​。

· 领导者,会定期向所有跟随者发送心跳RPC,以防止因过长的空闲时间而过期(和重新选举)​。领导者通常是最先面向客户端进程请求的,对日志进程进行添加处理以及发起日志复制,提交并更改自身的状态机,并向所有跟随者同步log。

图3:RAFT共识算法集群进程间的角色转换关系


RAFT描述的是一种通用的算法逻辑,它的具体实现有很多种,并且有很大调整空间。例如,原始的RAFT算法与一主多备的架构类似,任何时候只有一个实例在服务客户端请求。如果我们结合图数据库的可能查询请求场景,完全可以分阶段地改造为如下几种(难度从低到高)​。

· 多实例同时接收读请求负载:写入依然通过leader节点实现,读负载在全部在线节点间均衡。

· 多实例同时接收先读再写类请求负载:典型的如回写类的图算法,全部节点都可以承载图算法,回写部分先进行本地回写,再异步同步给其他节点。

 · 多实例同时接收更新请求负载并转发:写入请求可以发送给任意集群内节点,但是跟随者会转发给leader节点处理。

· 多实例同时处理更新请求:这是最复杂的一种情况,取决于具体的隔离层级需求,如果多个请求同时在多个实例上更改同一段数据,并且有不同的赋值,会造成数据的不一致性。在这种情况下实现一致性的最可靠途径就是对关键区域采用序列化访问。这也是本章反复提到的,任何分布式系统在最底层、最细节、最关键的部分一定要考虑到有需要串行处理的情况。

目前已知的RAFT算法可能远超100种,如ETCD、HazelCast、Hashicorp、TiKV、CockrochDB、Neo4j、Ultipa Graph、嬴图等,并且以各种编程语言实现,如C、C++、Java、Rust、Python、Erlang、Golang、C#、Scala、Ruby等,足以体现分布式共识算法及系统的生命力。

在基于共识算法的高可用分布式系统架构中,我们做了一个比较重要的假设,即大多数时候,系统的每个实例上都存有全量的数据。注意,我们限定的是“大多数时候”​,言下之意是在某个时间点或切片下,多个实例间可能存在数据或状态的不一致性,也因此需要在分布式系统内通过共识算法来实现数据同步,以形成最终的数据一致性。

下篇继续聊大规模水平分布式。最近很忙,不过老夫会尽快更文。


· END ·



(文/Ricky - HPC高性能计算与存储专家、大数据专家、数据库专家及学者)

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

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

相关文章

为mysql开启error日志 - phpstudy的数据库启动失败

步骤 找到mysql的配置文件 “my.ini”, windows上直接进入mysql安装目录,或者直接全盘搜; linux上使用命令 locate my.ini 即可搜索 修改"my.ini",找到 组[mysqld] 下面的“log_error”并设置日志文件绝对路径&#x…

Java设计模式——单例模式(特性、各种实现、懒汉式、饿汉式、内部类实现、枚举方式、双重校验+锁)

我是一个计算机专业研0的学生卡蒙Camel🐫🐫🐫(刚保研) 记录每天学习过程(主要学习Java、python、人工智能),总结知识点(内容来自:自我总结网上借鉴&#xff0…

MySQL查询相关内容

创建员工库和表; mysql> create database mydb8_worker; Query OK, 1 row affected (0.01 sec)mysql> use mydb8_worker; Database changed mysql> create table t_worker(-> department_id int(11) not null comment 部门号,-> worker_id int(11)…

微信小程序原生与 H5 交互方式

在微信小程序中,原生与 H5 页面(即 WebView 页面)之间的交互通常有以下几种方式: 1. 使用 postMessage 进行通信 微信小程序的 WebView 页面和原生小程序页面可以通过 postMessage 来进行数据传递。 WebView 页面向原生小程序发…

shell脚本基础练习

1、需求&#xff1a;判断192.168.1.0/24网络中&#xff0c;当前在线的ip有哪些&#xff0c;并编写脚本打印出来。&#xff08;以前10个网络IP为例&#xff0c;可以进行更改&#xff09; #!/bin/bashfor ((i1;i<10;i)) doping -c1 -w1 192.168.1.$i &> /dev/null &…

【全栈开发】----Mysql基本配置与使用

本篇是在已下载Mysql的情况下进行的&#xff0c;若还未下载或未创建Mysql服务&#xff0c;请转到这篇: 2024 年 MySQL 8.0.40 安装配置、Workbench汉化教程最简易&#xff08;保姆级&#xff09;_mysql8.0.40下载安装教程-CSDN博客 本文对于mysql的操作均使用控制台sql原生代码…

Shell的运行原理以及Linux中的权限问题

Shell的运行原理 Linux严格意义上说的是一个操作系统&#xff0c;我们称之为“核心&#xff08;kernel&#xff09;“ &#xff0c;但我们一般用户&#xff0c;不能直接使用kernel。 而是通过kernel的“外壳”程序&#xff0c;也就是所谓的shell&#xff0c;来与kernel沟通。如…

【0x0084】HCI_Set_Min_Encryption_Key_Size命令详解

目录 一、命令概述 二、命令格式及参数 2.1 HCI_Set_Min_Encryption_Key_Size命令格式 2.2. Min_Encryption_Key_Size 三、生成事件及参数 3.1. HCI_Command_Complete 事件 3.2. Status 四、命令的执行流程 4.1. 主机端准备阶段 4.2. 命令发送阶段 4.3. 控制器接收和…

【MATLAB代码】CV和CA模型组成的IMM(滤波方式为UKF),可复制粘贴源代码

该代码实现了一维无迹卡尔曼滤波器(UKF)与交互式多模型(IMM)结合的状态估计。代码分为多个部分,主要功能包括参数定义、观测数据生成、状态估计、模型更新以及结果可视化。 文章目录 运行结果程序代码主要功能代码结构应用场景注意事项运行结果 程序代码 下方源代码直接粘…

机器视觉4-损失函数与梯度计算

机器视觉4-损失函数与梯度计算 损失函数定义公式及变量含义整体理解 多类支撑向量机损失正则项与超参数什么是超参数一、与模型参数的区别二、常见的超参数三、调参方法 什么是优化一、参数优化的重要性二、利用损失函数进行反馈三、调整分类器参数的方法 优化的目标一、最小化…

极客说|Azure AI Agent Service 结合 AutoGen/Semantic Kernel 构建多智能体解决⽅案

作者&#xff1a;卢建晖 - 微软高级云技术布道师 「极客说」 是一档专注 AI 时代开发者分享的专栏&#xff0c;我们邀请来自微软以及技术社区专家&#xff0c;带来最前沿的技术干货与实践经验。在这里&#xff0c;您将看到深度教程、最佳实践和创新解决方案。关注「极客说」&am…

sparkRDD教程之基本命令

作者&#xff1a;nchu可乐百香果 指导者&#xff1a;nchu-YoungDragon 1.前期准备 &#xff08;1&#xff09;从迅雷网盘上面下载这个项目&#xff0c;并且把scala&#xff0c;maven和java环境配置好 网盘链接&#xff1a; 分享文件&#xff1a;SparkRDD.zip 链接&#xf…

基于 Electron 应用的安全测试基础 — 提取和分析 .asar 文件

视频教程在我主页简介或专栏里 目录&#xff1a; 提取和分析 .asar 文件 4.1. .asar 文件提取工具 4.1.1. 为什么选择 NPX&#xff1f; 4.2. 提取过程 4.3. 提取 .asar 文件的重要性 4.3.1 关键词 4.3.2 执行关键词搜索 4.3.2.1 使用命令行工具“grep”进行关键词搜索 4.3.2…

C# 获取PDF文档中的字体信息(字体名、大小、颜色、样式等

在设计和出版行业中&#xff0c;字体的选择和使用对最终作品的质量有着重要影响。然而&#xff0c;有时我们可能会遇到包含未知字体的PDF文件&#xff0c;这使得我们无法准确地复制或修改文档。获取PDF中的字体信息可以解决这个问题&#xff0c;让我们能够更好地处理这些文件。…

Django框架:python web开发

1.环境搭建&#xff1a; &#xff08;a&#xff09;开发环境&#xff1a;pycharm &#xff08;b&#xff09;虚拟环境&#xff08;可有可无&#xff0c;优点&#xff1a;使用虚拟环境可以把使用的包自动生成一个文件&#xff0c;其他人需要使用时可以直接选择导入包&#xff…

2024最新版JavaScript逆向爬虫教程-------基础篇之Chrome开发者工具学习

目录 一、打开Chrome DevTools的三种方式二、Elements元素面板三、Console控制台面板四、Sources面板五、Network面板六、Application面板七、逆向调试技巧 7.1 善用搜索7.2 查看请求调用堆栈7.3 XHR 请求断点7.4 Console 插桩7.5 堆内存函数调用7.6 复制Console面板输出 工…

联通用户管理系统(一)

#联通用户管理系统&#xff08;一&#xff09; 1.新建项目 如果你是windows的话&#xff0c;界面应该是如下的&#xff1a; 2.创建app python manage.py startapp app01一般情况下&#xff1a;我们是在pycharm的终端中运行上述指令&#xff0c;但是pychrm中为我们提供了工具…

【网络编程】基础知识

目录 网络发展史 局域网和广域网 局域网&#xff08;LAN&#xff09; 广域网&#xff08;Wan&#xff09; 光猫 路由器 网线 设备通信的要素 IP地址 基本概念 地址划分 特殊地址&#xff08;后续编程使用&#xff09; IP地址转换 字节序 网络模型 网络的体系结…

生产环境中常用的设计模式

生产环境中常用的设计模式 设计模式目的使用场景示例单例模式保证一个类仅有一个实例&#xff0c;并提供一个访问它的全局访问点- 日志记录器- 配置管理器工厂方法模式定义一个创建对象的接口&#xff0c;让子类决定实例化哪个类- 各种工厂类&#xff08;如视频游戏工厂模式创…

C#读写ini配置文件保存设置参数

本示例使用设备&#xff1a;https://item.taobao.com/item.htm?spma21dvs.23580594.0.0.52de2c1b5P5rkA&ftt&id22173428704 [DllImport("kernel32", CharSet CharSet.Unicode)] public static extern uint GetPrivateProfileString(string lpAppName, stri…