分布式系统:一致性协议

一致性模型本质上是进程与数据存储的约定,通过一致性模型我们可以理解和推理在分布式系统中数据复制需要考虑的问题和基本假设。那么,一致性模型的具体实现有一些呢?本文会介绍一致性协议实现的主要思想和方法。

什么是一致性协议

一致性协议描述了特定一致性模型的实际实现。一致性模型就像是接口,而一致性协议就像是接口的具体实现。一致性模型提供了分布式系统中数据复制时保持一致性的约束,为了实现一致性模型的约束,需要通过一致性协议来保证。

一致性协议根据是否允许数据分歧可以分为两种:

  • 单主协议(不允许数据分歧):整个分布式系统就像一个单体系统,所有写操作都由主节点处理并且同步给其他副本。例如主备同步、2PC、Paxos 都属于这类协议。
  • 多主协议(允许数据分歧):所有写操作可以由不同节点发起,并且同步给其他副本。例如 Gossip、POW。

可以发现,它们的核心区别在于是否允许多个节点发起写操作,单主协议只允许由主节点发起写操作,因此它可以保证操作有序性,一致性更强。而多主协议允许多个节点发起写操作,因此它不能保证操作的有序性,只能做到弱一致性。

值得注意的是,一致性协议的分类方式有很多种,主要是看从哪个角度出发进行归类,常用的另一个归类方式是根据同步/异步复制来划分,这里就不多做讨论了。下面对单主协议和多主协议分别做一些共性的分析,篇幅所限,不会深入到协议细节。

单主协议

单主协议的共同点在于都会用一个主节点来负责写操作,这样能够保证全局写的顺序一致性,它有另一个名字叫定序器,非常的形象。

主备复制

主备复制可以说是最常用的数据复制方法,也是最基础的方法,很多其他协议都是基于它的变种。 主备复制要求所有的写操作都在主节点上进行,然后将操作的日志发送给其他副本。可以发现由于主备复制是有延迟的,所以它实现的是最终一致性。

主备复制的实现方式:主节点处理完写操作之后立即返回结果给客户端,写操作的日志异步同步给其他副本。这样的好处是性能高,客户端不需要等待数据同步,缺点是如果主节点同步数据给副本之前数据缺失了,那么这些数据就永久丢失了。MySQL 的主备同步就是典型的异步复制。

两阶段提交

两阶段提交(2PC)是关系型数据库常用的保持分布式事务一致性的协议,它也属于同步复制协议,即数据都同步完成之后才返回客户端结果。可以发现 2PC 保证所有节点数据一致之后才返回给客户端,实现了顺序一致性。

2PC 把数据复制分为两步:

  1. 表决阶段:主节点将数据发送给所有副本,每个副本都要响应提交或者回滚,如果副本投票提交,那么它会将数据放到暂存区域,等待最终提交。
  2. 提交阶段:主节点收到其他副本的响应,如果副本都认为可以提交,那么就发送确认提交给所有副本让它们提交更新,数据就会从暂存区域移到永久区域。只要有一个副本返回回滚就整体回滚。

可以发现 2PC 是典型的 CA 系统,为了保证一致性和可用性,2PC 一旦出现网络分区或者节点不可用就会被拒绝写操作,把系统变成只读的。由于 2PC 容易出现节点宕机导致一直阻塞的情况,所以在数据复制的场景中不常用,一般多用于分布式事务中(注:实际应用过程中会有很多优化)。

分区容忍的一致性协议

分区容忍的一致性协议跟所有的单主协议一样,它也是只有一个主节点负责写入(提供顺序一致性),但它跟 2PC 的区别在于它只需要保证大多数节点(一般是超过半数)达成一致就可以返回客户端结果,这样可以提高了性能,同时也能容忍网络分区(少数节点分区不会导致整个系统无法运行)。分区容忍的一致性算法保证大多数节点数据一致后才返回客户端,同样实现了顺序一致性。

下面用一个简单的示例来说明这类算法的核心思想。假设现在有一个分布式文件系统,它的文件都被复制到 3 个服务器上,我们规定:要更新一个文件,客户端必须先访问至少 2 个服务器(大多数),得到它们同意之后才能执行更新,同时每个文件都会有版本号标识;要读取文件的时候,客户端也必须要访问至少 2 个服务器获取该文件的版本号,如果所有的版本号一致,那么该版本必定是最新的版本,因为如果前面的更新操作要求必须要有大多数服务器的同意才能更新文件。

以上就是我们熟知的 Paxos、ZAB、Raft 等分区容忍的一致性协议的核心思想:一致性的保证不一定非要所有节点都保持一致,只要大多数节点更新了,对于整个分布式系统来说数据也是一致性的。上面只是一个简单的阐述,真正的算法实现是比较复杂的,这里就不展开了。

分区容忍的一致性协议如 Paxos 是典型的 CP 系统,为了保证一致性和分区容忍,在网络分区的情况下,允许大多数节点的写入,通过大多数节点的一致性实现整个系统的一致性,同时让少数节点停止服务(不能读写),放弃整体系统的可用性,也就是说客户端访问到少数节点时会失败。

值得注意的是,根据 CAP 理论,假设现在有三个节点 A、B、C,当 C 被网络分区时,有查询请求过来,此时 C 因为不能和其他节点通信,所以 C 无法对查询做出响应,也就不具备可用性。但在工程实现上,这个问题是可以被绕过的,当客户端访问 C 无法得到响应时,它可以去访问 A、B,实际上对于整个系统来说还是部分可用性的,并不是说 CP 的系统一定就失去可用性。详细的分析参考分布式系统:CAP 理论的前世今生

多主协议

相比单主协议为了实现顺序一致性,不允许多个节点并发写,多主协议恰恰相反,只保证最终一致性,允许多个节点并发写,能够显著提升系统性能。由于多主协议一般提供的都是最终一致性,所以常用在对数据一致性要求不高的场景中。

Gossip 协议就是一种典型的多主协议,很多分布式系统都使用它来做数据复制,例如比特币,作为一条去中心化的公链,所有节点的数据同步都用的是 Gossip 协议。此外,Gossip 协议也在一些分布式数据库中如 Dynamo 中被用来做分布式故障检测的状态同步,当有节点故障离开集群时,其他节点可以快速检测到。

从名称上就可以看出 Gossip 协议的核心思想,Gossip 是流言八卦的意思,想想我们日常生活人与人之间传八卦的场景,在学校里面一个八卦一旦有一个人知道了,通过人传人,基本上整个学校的人最终都会知道了。因此 Gossip 协议的核心思想就是:每个节点都可以对其他节点发送消息,接收到消息的节点随机选择其他节点发送消息,接收到消息的节点也做同样的事情。

多主协议允许运行多个节点并发写,就一定会出现对一个数据并发写导致数据冲突的情况,因此这类协议都需要解决并发写的问题。单主协议通过主节点控制写入,保证不会出现并发写的情况,因为所有写操作最终都会通过主节点排序,从某种意义上讲,使用单主协议的系统对于写入实际上是串行的,因此其性能是有瓶颈的。而多主协议允许多节点并发写,提搞了写入的性能,但是实际上它是把数据合并的操作延迟了,单主协议在写入的时候就进行了数据合并,因此读取数据的时候如果出现数据冲突的时候,就需要对数据进行合并,保证全局一致性。

前面我们提到比特币使用的是 Gossip 协议做数据复制,那么问题来了,不是说多主协议性能会比较高吗,为什么比特币的性能那么差?这里实际上要分开来看,由于比特币是去中心化的,但是它的支付功能需要保证全局数据一致性,因此它用了一种很巧妙的一致性算法 POW:所有节点都做一道数学题,谁先算出答案谁有权利将交易写到链上,然后利用 Gossip 协议传播它的答案和交易,其他节点验证它的答案正确就将数据保存起来。

到这里你可能会有一个疑问:POW 作为多主协议为什么性能这么低?任何协议都有它适用的场景。在比特币这个场景中,它对于数据一致性是有强需求的,理论上用单主协议是最优的选择。但是比特币作为去中心化的数字货币是不会使用单主协议的,否则又变成中心化的系统了。因此比特币只能选择多主协议,通过 POW 协议将比特币整条链操作进行了近似串行化,这样才能降低出现双花的概率(并发写的时候一个比特币被消费多次),鱼与熊掌不可兼得,既然要强一致性,那么只能牺牲性能来换取。

由于多主协议允许了数据分歧,那么就需要有解决数据冲突的策略来保证最终一致性。如果要严格区分的话,比特币实际上应用了两个一致性协议:

  • POW:决定节点的记账权,起到类似单主协议中定序器的作用。注意 POW 也是多主协议,尽管概率很低,但是它有可能出现多个节点同时算出答案,一起出块(并发写)的情况,此时我们称比特币出现了分叉,即出现了数据冲突。
  • Gossip:用于将出块的交易同步到全球所有节点。由于 POW 会出现并发写的情况,当一个节点同时接受到多个节点写入请求时,就需要解决数据冲突的问题。比特币解决数据冲突的方式就是当出现分叉时,选取最长的那条链作为主链,其他分叉的链上的交易会被回滚,等待重新打包出块。

总结

本文主要从是否允许数据分歧的角度将分布式一致性协议分为两种:单主协议和多主协议。其中单主协议会用一个主节点来负责写操作,这样能够保证全局写的顺序一致性,但因此也牺牲了一部分性能。而多主协议则允许写操作可以由不同节点发起,并且同步给其他副本,只能保证最终一致性,但因此也提升了系统并发写入的性能。对数据一致性要求高的场景例如分布式数据库,主要会使用单主协议,对数据一致性要求不高例如故障检测,主要会使用多主协议来提高性能,当然也有特例,像比特币为了去中心化使用 POW 和 Gossip 结合进行数据复制。

值得注意的是,文中提到的单主、多主协议只是我个人对分布式一致性协议的一种分类方式,帮助我们更好的理解。读者可以看一下参考资料,看一下不同作者对分布式协议是如何分类的,这样对分布式一致性协议会有更深入的理解。

原文链接
本文为云栖社区原创内容,未经允许不得转载。

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

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

相关文章

论程序员的自我修养——我在阿里干了十年开发

究竟是努力重要,还是选择重要?资深阿里技术人毕玄师兄有着自己的见解。 毕玄,阿里巴巴基础设施事业群负责人,资深技术专家。打造了阿里目前使用最为广泛的核心中间件之一的服务框架;设计并带领团队实现了阿里技术发展…

一文了解 Spring Boot 服务监控,健康检查,线程信息,JVM堆信息,指标收集,运行情况监控!...

作者 | Richard_Yi责编 | 徐威龙稿源 | 掘金封图| CSDN 下载于视觉中国本文为作者个人经验,供大家参考。去年我们项目做了微服务1.0的架构转型,但是服务监控这块却没有跟上。这不,最近我就被分配了要将我们核心的微服务应用全部监控起来的任务…

分布式6大核心专题_分布式Session

文章目录一、Session存在服务器上还是tomcat中?1. 创建springboot项目2. 启动项目3. 调用登录接口4. 调用获取用户信息接口5. 重启tomcat调用获取用户信息接口二、Session与Cookie的关系三、传统Session3.1. 启动项目3.2. 浏览器测试四、分布式Session解决方案4.1. …

Nacos: Namespace 和 Endpoint 在生产环境下的最佳实践

随着使用 Nacos 的企业越来越多,遇到的最频繁的两个问题就是:如何在我的生产环境正确的来使用 namespace 以及 endpoint。这篇文章主要就是针对这两个问题来聊聊使用 nacos 过程中关于这两个参数配置的最佳实践方式。 namespce 关于 namespace &#x…

java.lang.ArrayIndexOutOfBoundsException:数组下标越界越界

前台vue初始化 pinIds:[],但是当pinIds前台查询条件传值为空时,pinIds[0]、pinIds[1]取不到值,就会报数组下标越界越界 改为 就可以了

如何实现“持续集成”?闲鱼把研发效率翻了个翻

阿里妹导读:业务的快速发展,需要我们更快速地响应,和更高质量产品的交付。如何从原来大(xiao)迭(pu)代(bu)的开发模式切换为精益开发模式?以 2-1-1(2周需求交付周期,1周需求开发周期,1小时集成时…

分布式Session解决方案_Spring Session + Redis

接上一篇:分布式6大核心专题_分布式Session https://gblfy.blog.csdn.net/article/details/113802195 文章目录1. 安装redis服务并启动2. 引入Spring Session组件3. 分别启动8081端口和8082端口4. 调用8081登录接口5. 调用8081获取用户信息接口6. 调用8082获取用户信…

酸了!华为补贴湖北员工每天最高 2000 元

近日,华为员工发帖称,华为将给武汉研究所现场办公的人员,每人补助2000元(从2020年1月23日开始算,以湖北发布疫情终止之日截止),湖北以外其他地区1000 元,海外每天150美金&#xff08…

java.lang.IllegalArgumentException: invalid comparison: java.time.LocalDateTime and java.lang.String

数据库字段: 数据库中的时间字段handle_time是datatime 前端: xml文件: 运行结果: 原因 这是因为原因是mybatis 中对于时间参数进行比较时的一个bug. 如果拿传入的时间类型参数与空字符串进行对比判断则会引发异常. 所以在上面…

四年从P7到P9,这个阿里小二的秘诀是给自己挖坑

恶魔有一头精彩的头发。 “紫色、灰色、灰色、雾霾蓝色、黄色、蓝色、紫色、绿色、灰色、绿色。” 若有人问起她的染发史,她能准确地报出过去两年里的所有发色。干脆利落,没半个字多余。 恰如她在工作中给大多数人的印象:语速极快&#xf…

分布式Session解决方案_Token + Redis

接上一篇:分布式6大核心专题_分布式Session https://gblfy.blog.csdn.net/article/details/113802195 文章目录1. 安装redis服务并启动2. 依赖代码配置3. 分别启动8081端口和8082端口4. 调用8081登录接口5. 调用8081获取用户信息接口6. 调用8082获取用户信息接口实现…

达摩院首席数据库科学家李飞飞:云原生新战场,我们如何把握先机?

阿里妹导读:云计算大潮来袭,传统数据库市场正面临重新洗牌的情境,包括云数据库在内的一批新生力量崛起,动摇了传统数据库的垄断地位,而由云厂商主导的云原生数据库则将这种“改变”推向了高潮。 云时代的数据库将面临怎…

什么? 搞不定redis分布式锁?

作者:故事凌 分布式锁 1. 什么是分布式锁 分布式锁是控制分布式系统之间同步访问共享资源的一种方式。在分布式系统中,常常需要协调他们的动作。如果不同的系统或是同一个系统的不同主机之间共享了一个或一组资源,那么访问这些资源的时候&am…

ElementUI的el-table隐藏id列

使用场景: 使用el-table进行数据的展示时,查询数据时要获取对象的ID属性,在展示时不需要展示ID这一列,但是在进行编辑时需要获取该ID。 实现方法: 可以通过在el-table-column上添加 v-if"false" 完整示…

阿里云CDN技术掌舵人文景:相爱相杀一路狂奔的这十年

提到阿里云CDN,不得不提技术掌舵人姚伟斌(文景),虽然他不是团队中最“老”的同学,但他却历经了淘宝业务发展最为飞速的几年,见证了从最初服务淘宝和集团内部的CDN,到如今国内服务客户最多的云CD…

分布式Session解决方案_Token + JWT

接上一篇:分布式6大核心专题_分布式Session https://gblfy.blog.csdn.net/article/details/113802195 文章目录1. 引入JWT组件2. 代码配置3. 分别启动8081端口和8082端口4. 调用8081登录接口5. 调用8081获取用户信息接口6. 调用8082获取用户信息接口实现流程 1.引入…

把握数据库发展趋势 DBA应如何避免“踩坑”?

在DTCC 2019大会上,阿里云智能数据库产品事业部高级产品专家萧少聪做了题为《如何构建云时代DBA的知识体系》的演讲,进行云时代以后,IT行业各工种的职责都在发生变化,云数据库使得日常DBA管理实现更多的自动化,大大提高…

Could not load TestContextBootstrapper [null]. Specify @BootstrapWith‘s ‘value‘ attribute...

在测试redis集成短信验证时使用test启动类做单元测试,使用了spring注入。 RunWith(SpringRunner.class) SpringBootTest(classes RbacApplication.class) public class SmsUtilTest extends RbacApplicationTest{Autowiredprivate SmsHelper smsHelper;Autowiredp…

DevOps 转型时如何安全融入?对企业产出有何影响?2019年 DevOps 最新现状研究报告解读 | 原力计划...

作者 | liumiaocn责编 | 徐威龙封图| CSDN 下载于视觉中国2019年DORA发布了DevOps的研究报告,迄今为止这已经是DORA的第八次报告的发布。相较于往年的报告,2019年的报告全篇只聚焦于一个要素:安全。在2018年DORA提供了一个包含五个步骤的模型…

开源性能可视化工具——FlameScope模式识别

FlameScope是一个新的开源性能可视化工具,它使用次秒级偏移热图和火焰图来分析周期活动、方差、扰动。我们在Netflix TechBlog上面,发表了技术文章Netflix FlameScope,以及工具的源代码。火焰图很好理解,次秒级偏移热图理解起来要…