聊透分布式系统一致性

一、强一致性

 


一致性大家庭中,虽然细分种类很多,但是实际上只有两大类,其中之一就是强一致性,其具体包含了严格一致性(也叫原子一致性或者线性一致性)和顺序一致性。

  • 严格(原子/线性)一致性

严格一致性代表着,当数据更新后,所有Client的读写都是在数据更新的基础上。如下图所示,我们假设每份数据有三个副本,分别落到三个节点上。当Client1尝试将X的值置为1时,严格一致性要求当Client1完成更新操作以后,所有Client都要在最新值的基础上进行读写,这里的Client10读取到的值是x=1,在同一时刻Client100的更新操作也是在x=1的基础上进行x+=1操作,在下一个时刻Client1000读到的任意一个副本,X的值都会是2。

此时你会发现一切似乎都是很完美的。但是仔细想想,严格一致性的背后有什么潜台词呢?

1)数据同步复制

严格一致性代表着,所有数据在写入操作的时候是同步复制的,即写多副本都成功,才算写入成功,HDFS是不是就是最好的例子。并且具有原子性,对于写入操作来说,结果要么写成功,要么写失败,不存在中间状态。这也是为什么称为原子一致性的原因。

2)严格一致性不考虑客户端

在网上有很多人在解释一致性时,尝试从客户端和服务端分别解析;但是在上一篇我们分析CAP的时候,也有提到不要带Client玩,那么究竟谁对谁错呢?

这里我们再来看下,在考虑分布式系统的一致性时我们更关注什么?是多个Client发送读写请求到达后端的时间和先后顺序嘛?不,我们真正关注的是每个请求,对应服务端完成时间点的先后顺序。还是参考上面的例子,Client1000读取到x=2这个结果,实际上是以Client100这个写操作完成为基础的,如果Client100写操作一直不完成,那么强一致性要求Client1000读取到的X是1而不是2。因此我们更需要关注的是完成操作的具体时间点,而不是操作发起的时间点,对于一致性来说考虑Client的意义就不大了。当然在同一时刻多个Client操作的幂等性还是一定要保证的。

换个角度,Client才是一致性需求的甲方,不是嘛。而分布式系统端作为乙方,只能满足甲方需求,或者拒绝甲方需求,而不是要求甲方作出任何改变!

3) 基于严格的全局时钟

上面我们提到操作行为完成时间点的顺序是十分重要的。再仔细看一下上面举例的内容,相信你会发现一切的行为都在时间这个维度上,行为顺序是:Client1更新x=1 -> Client10读取x=1/Client100在x=1的基础上更新x+=1 -> Client1000读取x=2。所以每个操作都是在前一个操作完成的基础上进行的,在分布式服务中,需要有一个基准时间来衡量每个操作行为的顺序。此时你会问了,机器上不是都有NTP做时间校准嘛?现在的问题就是无法保证每一台机器的时间都是绝对相同的。

举个例子,数据D2所在的节点相比D1节点时间提前了几秒,当Client1的更新请求完成后(用时500ms),Client10的请求开始执行并完成,如果将机器时间作为基准就会发现Client10的读取操作竟然在Client1的更新操作之前,这显然是违背强一致性的。

我们一般我们会如何保证全局时钟?这里简单聊聊三种种常见解法

  1. 混合逻辑时钟 Hybrid Logic Clock

在混合逻辑时钟中同时比较了节点本地的物理时间、逻辑时间和其他节点发送消息中的物理时间。kudu和Cockroachdb也都是使用的这个方法,HLC虽然加上了物理时间,但是仍然强依赖于机器的NTP,并不是严格意义上精确的时钟,在HLC中需要为时钟定义一个边界,比如kudu中定义了maximum check error(最大时钟错误),如果本地NTP没启动,kudu在启动的时候就直接失败了;如果误差超过了maximum check error,依旧会报错,这也就意味着当超过HLC所设定的偏差边界,HLC就不能正常工作了。

在看HLC的实现逻辑时,发现步骤比较多,逻辑时间存在的意义就是在时间比对时,当作中间值或者备份值。这里由于不是本篇重点,不再赘述了,感兴趣的小伙伴可以看下论文:https://cse.buffalo.edu/tech-reports/2014-04.pdf。

  1. True Time

上一篇文章中也有讲到,谷歌依赖强大的基建实力降低了网络分区发生的概率,而面全局时钟问题,Google的Spanner采用的是GPS + Atomic Clock(原子时钟的含义可以百度一下)这种纯硬件方式来对集群的机器进行校时,其精度在ms级别,这里我们用ε来表示时间精度的误差,时间的精度误差的范围也就是[t-ε,t+ε]这个范围之间。此时回到上面的操作中,按照此种方式Client10的机器时间相比Client1的机器时间最多提前或者滞后2个ε的时间,因此Spanner引入了commit wait time这个方案,说白了就是操作执行完成后多等一会,等过了这个精度误差的范围自然就全局有序了,Google将精度误差控制在几ms级别,当然对于Spanner这种全球性、跨地域的分布式系统来说,多等个几ms问题也不大。

但很遗憾,Google的这套硬件解决方案,并没有开源出来,适用性有限,我们就望梅止渴吧。

  1. 授时中心 TimeStamp Oracle

在生活中也有”授时中心“的存在,貌似在陕西,具体位置可以查查,他的作用是什么呢?为中国各种基建、系统提供了一个准确的时间,避免误差。(个人YY:万一打起仗,总不能因为其他国家干扰了基准时间,咱们所有基建就瘫痪吧,因此授时中心的意义巨大。) 

在分布式服务中,实际上也有类似的方案。这里以Tidb举例,Tidb为了校准时间,就是采用了TSO这个方案,对于Tidb来说所有行为事件统一由PD节点分配时间,虽然这种方案会产生非常高频的互相调用,但是按照Tidb官方介绍,在同IDC网络环境下网络传输开销非常低,只有0.xms。当然如果面对跨IDC的网络,就可以尝试将PD节点和Tidb节点混部(Tikv依然需要独立部署,为的是存储计算分离)。这就不需要走网络的开销了,当然如果是Client端跨IDC的话,还是没有太好的方法。

  • 顺序一致性

上面我们说到了严格一致性(线性/原子),想做到全局时钟下的全局绝对有序是有难度的,HLC实现比较复杂,谷歌的原子钟+GPS又没有开源出来,TSO又增加了系统的复杂度。想实现全局时钟好难!

这里我们是否可以退一步,舍弃“时间”这个有序的计数器,尝试构造一个更好维护的计数器,不保证全局行为绝对有序,只保证分布式服务全局相对有序?

如下图所示,D1先后更新了x=1,x=2,D3先后更新了a=1,a=2。当Client读取到D2节点时,按照顺序一致性要求,所有节点的操作相对顺序都是相同的,一定是x=1在x=2之前,a=1在a=2之前,下图举例的是顺序一致性的其中一种情况。

1)逻辑时钟 Logic Clock

逻辑时钟Logic Clock,这个名字你陌生的话,或许他的另一个名字Lamport Timestamp会让你浮想连连,如果你还是没啥印象的话,那么Paxos你是否知道呢?(如果做大数据的你不知道paxos,那你需要好好补习下基础了😄。)Lamport Timestamp和Paxos的作者实际就是同一个人——Lamport,Paxos在分布式系统一致性算法中是教义般的存在,由此可见逻辑时钟Logic Clock也不会差到哪里。

如上图所示,在Logic Clock算法中,每台机器内部都会记录一个时间戳,以A、B举例 ,其初始值是0。每当机器A、B执行了一个事件,那么他们各自的时间戳就会+1,当A向B发起通信的时候,A会附带自己的时间戳,比如<message,timestamp>,这时B会比较消息中的时间戳和本地时间戳,选取最大值max(local timestamp,message timestamp)更改本地的时间戳。通过这种方式构建了一个新的计数器,实现了全局相对的顺序性即本地:timestamp +=1 && 远端:选择max timestamp,即使各个节点时间不同,但是操作执行是有序的;但是问题也很明显,就是新的计数器无法和实际时间做匹配。

2)ZooKeeper是怎样的一致性?

这里我们暂时不谈共识算法Paxos(请持续关注后续文章)。我们直接来说说ZooKeeper的一致性,网上很多资料都说zk是最终一致性,很抱歉,zk是强一致性的,并且是强一致性中的顺序一致性。为什么不说zk是最终一致性的原因呢?

<1> 就好比你考试考了99分,你非得说考了60分。这不止代表着分数,最终一致性拉低zk的档次,直接从强力档拉到了弱鸡档。

<2> 此外你参考本篇中最开头的图来看,zk是CP系统。从CAP反向来推导,如果zk是最终一致性,那么意味着是AP系统,但是zk在选举的时候实际上是不可用的,也就是A达不到,此时就发生矛盾了。

ZooKeeper中的Zxid实际上就是逻辑时钟Logic Clock中自造的计数器,可以发现,以Zxid为基准可以做到所有节点识别到的操作顺序都是相同的。就像上面说的Zxid是是无法跟实际时间相对应的。网上很多资料说,ZooKeeper的写入是线性一致性,对此我是不认同的,涉及到的两段式提交(后面的文章会讲到),不带回滚却会主动同步,某种意义上讲是线性的,但是当commmit阶段时,发生了网络分区了,这时数据就不会同步到异常节点上,如果此时再有一个Client访问到这个节点,此时读到的就是旧数据了。其写失败意味着所有节点都写失败,而写成功却意味着不一定所有节点都写成功。因此个人认为只能算顺序一致性,而不能算线性一致性。

3)举个栗子

如果对顺序一致性还没有什么概念,那么你可以理解为分布式系统就是微信朋友圈,当我我发了一个朋友圈之后,周杰伦看到我的朋友圈后开始评论,紧接着王力宏又评论了😄。顺序一致性代表着当我们共同的朋友林俊杰看朋友圈时,一定是先看到周杰伦的评论,再看到王力宏的评论,当朋友吴亦凡看到时,可能只能看到周杰伦的,但是王力宏的评论也许会迟到,但永远不会缺席。并且永远不会存在王力宏的评论在前,而周杰伦的评论在后的情况。


三、弱一致性

一致性家族中的另一大类就是弱一致性了,相比强一致性,弱一致性在保证可用性的基础上,允许出现数据不一致的情况。

  • 为什么一致性会分强弱?

按照上一篇CAP的理论,CAP中的一致性。而在实际需求中,会发现越来越多的分布式系统都更看重可用性A,而不是一致性C。高可用性要求我们的系统,面对Client的读写请求在规定时间内必须返回结果,并且不会报错。

面对不同场景,各类AP系统也只能在弱一致性方面下大功夫。也因此出现了非常多的弱一致性模型,下面我们就逐个来分析下。

  • 最终一致性

上一篇我们在BASE中所提到的就是最终一致性,其并不保证在任意时刻、任意节点上的同一份数据都是完全一致的,但是随着时间的迁移,不同节点上的同一份数据总是在向一致的方向变化。其中数据不一致的时间段,称为非一致性窗口。简单说,就是数据写入的一段时间后,各节点的数据最终会达到一致状态。如下图所示。

  • 因果一致性

    因果一致性强调了数据之间的因果关系,初始状态X的值为1,当D1将X的更新为2后,这时D1会和D2节点进行通信,将<D1,D2,X,2>这条消息,传递给D2,后续D2节点所有的读写都是在新值基础上进行的。此时D3节点还是会在非一致窗口内,读到X的旧值1。因此D1更新数据,并通信D2为因,D2接受通信,修改本地状态为果,此为因果一致性。

  • “读你所写”一致性

什么是读你所写一致性呢?顾名思义,读到你所写的数据,在因果一致性中,定义的是集群节点间更新通知的机制,而对于“读你所写”一致性来说,也是沿用这个思路,不过这里通信的是本节点,影响的也是本机后续的的所有读写请求,因此读你所写一致性,其实是因果一致性的特殊场景,由于原理相似,下面直接放图。

  • 会话一致性

会话一致性以会话为基础,通常应用于类数据库系统的场景。每一个会话相当于一个独立的访问链接,在这个会话中,可以执行很多具体的读写操作,且会话之间是相对独立的。

如下图所示,会话一致性要求,只要会话1还存在,会话内就保证“读你所写”一致性。如果D1的会话1终止,那么当重新建立会话2时,在不一致窗口内即使是同一个节点的会话,也不保证数据一致。因此会话一致性又是读你所写一致性的特例(是不是感觉有点乱,一个特例又一个特例的,没关系,最后的时候我们聊下各种一致性的关系,加油!)

  • 单调一致性

    单调一致性,分为读、写两个层面,即单调读一致性和单调写一致性。实际上很好理解,单调读保证了整个系统读必须有序的,假设X的值递增,读X=2一定是在读X=1之后。而单调写保证了写必须有序的,对于整个系统来说写X=2一定是在写X=1之后。这里比较好理解,我就不正图了(画图画吐了!)。个人认为单调写一致性应该是大部分分布式服务的基础。否则如果你写入顺序无法保证,你想想都会感到痛苦。

三、各种一致性的关系和常见误区

  • 各种一致性的关系

如下图所示,一图厘清一致性之间的关系,如果此时相关概念有忘记,可以再重新看下上面的解析~

  • 误区一:强一致性=线性一致性?

网上非常多的资料动不动就强一致性就是线性一致性,或者把顺序一致性放到和强一致性相同的级别来比对,这些其实都是错误的,正如我们上面看到的,强一致性包含线性一致性和顺序一致性。也因此强一致性不一定是线性一致性,但线性一致性一定是强一致性。

  • 误区二:一致性并不是非黑即白的

强弱一致性之间并不是泾渭分明的,一个分布式系统可能同时满足其中的一种或者多种。咱们还是回到ZooKeeper上,其同时符合顺序一致性,最终一致性。一致性种类满足的越多,符合的场景也就越多,当然其复杂度也就越高。从这一点我们就可以看出,没有一个能满足所有场景的分布式系统,如果真的有,那么他的数据一致性逻辑必然十分复杂。

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

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

相关文章

使用jquery打造一个动态的预览产品颜色效果

在浏览一些电子商务网站的时候&#xff0c;选择一件产品的时候&#xff0c;我们经常会看到点击衣服的颜色&#xff0c;同一件衣服的颜色就会切换&#xff0c;让我们觉得真是比较有意思&#xff0c;这样做的效果给用户的体验比较好&#xff0c;今天就给大家分享一下这种效果的实…

Java Word转Html

最近转换的需求比较多&#xff0c;最近做了一个Word转Html的 这个要导一个包和配置一个文件 1.jacob.jar 2.与jacob.jar相对应的jacob.dll&#xff08;放在windows/sys32下或者放在jre下面&#xff09; 代码 1 packagetest;2 3 importjava.io.File;4 5 importcom.jacob.activeX…

leveldb中为什么L 0层中每个sst文件中key的范围都是有重叠的?

在leveldb中&#xff0c;level 0层中的sst文件是由immutable memtable通过后台线程flush得到的&#xff0c;但是由于immutable memtable中的key可能是由重复的&#xff0c;因此在leveldb中将sst文件中key的范围有重叠的所有sst文件都放在了level 0层中&#xff0c;而其他level层…

文本分类的一种对抗训练方法

最近阅读了有关文本分类的文章&#xff0c;其中有一篇名为《Adversarail Training for Semi-supervised Text Classification》, 其主要思路实在文本训练时增加了一个扰动因子&#xff0c;即在embedding层加入一个小的扰动&#xff0c;发现训练的结果比不加要好很多。 模型的网…

在leveldb中,为什么要有immutable memtable?

目的是&#xff1a;为了防止写入kv时被阻塞。 设想&#xff0c;如果没有immutable memtable&#xff0c;当memtable满了之后后台线程需要将memtable 立即flush到新建的sst中&#xff0c;在flush的过程中&#xff0c;新的KV记录是无法写入的&#xff0c;只能等待&#xff0c;就…

密码强弱提示(27)

密码的强弱提示是对用户填写登陆密码的复杂程度来给出提示&#xff0c;使用密码的强弱提示可以增强用户对密码的保护意识&#xff0c;对如今的网络是非常有必要的&#xff0c;本程序中当用户输入完密码后&#xff0c;网页会自动的对用户输入的密码给出强弱判断。 使用JavaScrip…

《In Search of an Understandable Consensus Algorithm》翻译

Abstract Raft是一种用于管理replicated log的consensus algorithm。它能和Paxos产生同样的结果&#xff0c;有着和Paxos同样的性能&#xff0c;但是结构却不同于Paxos&#xff1b;它让Raft比Paxos更易于理解&#xff0c;并且也为用它构建实际的系统提供了更好的基础。为了增强…

深度点评五种常见WiFi搭建方案

总结十年无线搭建经验&#xff0c;针对企业常见的五种办公室无线网络方案做个简要分析&#xff0c;各种方案有何优劣&#xff0c;又适用于那种类型的企业。方案一&#xff1a;仅路由器或AP覆盖简述&#xff1a;使用路由器或AP覆盖多个无线盲区&#xff0c;多个AP的部署实现整体…

深入理解Presto

深入理解Presto 简介 Presto是一个facebook开源的分布式SQL查询引擎&#xff0c;适用于交互式分析查询&#xff0c;数据量支持GB到PB字节。presto的架构由关系型数据库的架构演化而来。presto之所以能在各个内存计算型数据库中脱颖而出&#xff0c;在于以下几点&#xff1a; …

设置VS2017背景图片

设置方法很简单&#xff1a;安装扩展ClaudiaIDE 1、在这里下载扩展&#xff0c;https://visualstudiogallery.msdn.microsoft.com/9ba50f8d-f30c-4e33-ab19-bfd9f56eb817 2、然后双击即可完成安装。 之后重启VS&#xff0c;就可以看到编程背景上多了一个萌妹子&#xff0c;据说…

证书的应用之一 —— TCPSSL通信实例及协议分析(上)

SSL(Security Socket Layer)是TLS(Transport Layer Security)的前身&#xff0c;是一种加解密协议&#xff0c;它提供了再网络上的安全传输&#xff0c;它介于网络通信协议的传输层与应用层之间。 为实现TCP层之上的ssl通信&#xff0c;需要用到数字证书。本文通过具体例子来说…

ClickedOnce部署方法

1.ClickedOnce部署时有些DLL和配置文件无法自动部署到系统当中&#xff0c;只能用Manifest Manager Tool 修改manifest 文件 /Files/Tonyyang/Software/ManifestManagerUtility.rar 2.部署文件结构 3.部署方法 首先用VS自带的ClickedOnce发布应用程序&#xff08;博客园有&…

树莓派安装MySQL数据库与卸载

出处&#xff1a; 1、http://www.cnblogs.com/liyangLife/p/4500115.html 2、https://blog.csdn.net/huayucong/article/details/49736427 3、https://www.imooc.com/article/23132?block_idtuijian_wz 4、http://www.runoob.com/mysql/mysql-install.html&#xff08;Debian系…

Visual Studio.net 2010 Windows Service 开发,安装与调试

本示例完成一个每隔一分钟向C:\log.txt文件写入一条记录为例&#xff0c;讲述一个Windows Service 程序的开发,安装与调试 原程序&#xff0c;加文档示例下载 /Files/zycblog/SourceCode.rar 目录索引 1 开发工具 2 开发过程 3 安装 4 开发调试 5 注意事项 6 参考资料…

ArcGis dbf读写——挂接Excel到属性表 C#

ArcMap提供了挂接Excel表格信息到属性表的功能&#xff0c;但是当数据量较大到以万计甚至十万计的时候这个功能就歇菜了&#xff0c;当然&#xff0c;你可以考虑分段挂接。这个挂接功能只是做了一个表关联&#xff0c;属性记录每个字段的信息需要通过“字段计算器”计算过来。 …

VisualStudioAddIn2017.vsix的下载安装和使用

本加载项是用于Visual Studio的&#xff0c;下载以后按照如下步骤进行安装&#xff1a; 完全退出Visual Studio把下载了的文件解压缩&#xff0c;会产生一个VisualStudioAddIn2017.vsix文件双击该文件&#xff0c;按照提示安装重启Visual Studio安装完成后的使用方法&#xff0…

Presto基本概念

Presto基本概念 Presto是Facebook开源的MPP SQL引擎&#xff0c;旨在填补Hive在速度和灵活性&#xff08;对接多种数据源&#xff09;上的不足。相似的SQL on Hadoop竞品还有Impala和Spark SQL等。这里我们介绍下Presto的基本概念&#xff0c;为后续的笔记做基础。 Operator …

2019春第六周编程总结

这个作业属于哪个课程C语言程序设计Ⅱ这个作业要求在哪里https://edu.cnblogs.com/campus/zswxy/MS/homework/2829我在这个课程的目标是利用指针知识解决相关实际问题在具体哪方面帮我实现目标设计密码开锁、交换变量解决问题以及电码加密参考文献C语言基础、http://www.w3scho…

Exchange企业实战技巧(26)在Outlook中打开多个邮箱

工作中&#xff0c;有时要需要让某个用户在outlook中同时打开多个exchange邮箱&#xff0c;对于outlook2010来说&#xff0c;是支持多个Exchange邮箱用户账户的并存&#xff0c;而outlook2007则不支持。那该功能有没其他实现方法呢&#xff1f;答案是有的。 如果你的Exchange是…

Emulator Error: Could not load OpenGLES emulati...

为什么80%的码农都做不了架构师&#xff1f;>>> 模拟器提示警告&#xff1a;Emulator Error: Could not load OpenGLES emulation library: Could not load DLL! 亲测可用&#xff1a; 从SDK\tools\lib目录下将一下四个dll文件复制到SDK\tools&#xff0c;重启模…