分布式系统的一致性与共识算法(二)

Consitency

背景

如买最后一张车票,两个售票处分别通过某种方式确认过这张票的存在。这时,两家售票处几乎同时分别来了一个乘客要买这张票,从各自"观察"看来,自己一方的乘客都是先到的,这种情况下,怎么能达成对结果的共识呢?看起来很容易,卖给物理时间上率先提交请求的乘客即可。然而,对于两个来自不同位置的请求来说,要判断在时间上的"先后"关系并不是那么容易。两个车站的时钟时刻可能是不一致的。时钟计时可能不精确的。根据相对论的观点,不同空间位置的时间是不一致的。因此追求绝对时间戳的方案是不可行的,能做的是要对事件的发生进行排序。这也是解决分布式系统领域很多问题的核心秘诀,把不同时空发生的多个事件进行全局唯一排序,而这个顺序还得是大家都认可的。排了序,一个一个处理就行了,和单机没有任何区别(不考虑突然故障情况,只考虑共识机制)如果存在可靠的物理时钟,实现排序往往更为简单。高精度的石英钟的漂移率为10的-7次方,最准确的原子震荡时钟的漂移率为10的-13次方。Google曾在其分布式数据库Spanner中采用基于原子时钟和GPS的"TrueTIme"方案,能够将不同数据中心的事件偏差控制在10ms知心区间。在不考虑成本的前提下,这种方案简单、有效。然而,计算机系统的时钟误差要大得多,这就造成分布式系统达成一致顺序十分具有挑战性,或者说基本不可能。要实现绝对理想的严格一致性(Strict Consistency)代价很大。除非系统不发生任何故障,而且所有节点之间的通信无需任何时间,此时整个系统其实就等价于一台机器了,因此根据实际需求的可用,人们可能选择不同强度的一致性。

顺序一致性(Sequential Consistency)

虽然强度上 线性一致性 > 顺序一致性,但因为顺序一致性出现的时间比较早(1979年),线性是在顺序的基础上的加强(1990年)。因此先介绍下 顺序一致性。
顺序一致性也算强一致性的一种,它的原理比较晦涩。

举例说明1:下面的图满足了顺序一致,但不满足线性一致

在这里插入图片描述

  • 1.x和y的初始值为0
  • 2.Write(x,4)代表写入x=4,Read(y,2)为读取y=2

从图上看,进程P1,P2的一致性并没有冲突。因为从这两个进程的角度来看,顺序应该是这样的。

Write(y,2), Read(x,0), Write(x,4), Read(y,2)

这个顺序对于两个进程内部的读写顺序都是合理的,只是这个顺序与全局时钟下看到的顺序并不一样。在全局时钟的观点来看,P2进程对变量X的读操作在P1进程对变量X的写操作之后,然而P2读出来的却是就数据0

举例说明2:

假设我们有个分布式KV系统,以下是四个进程对其的操作顺序和结果:
-表示持续的时间,因为一次写入或者读取,客户端从发起到响应是由时间的,发起早的客户端,不一定拿到数据就早,有可能因为网络延迟反而更晚。
情况1:

A:--W(x,1)------------------------
B:  --W(x,2)------------------------
C:                                   -R(x,1)-         --R(x,2)-
D:                     -R(x,1)-              --R(x,2)--

情况2

A:--W(x,1)------------------------
B:  --W(x,2)------------------------
C:                                 -R(x,2)-        --R(x,1)--
D:                          -R(x,2)-          --R(x,1)--

上面情况1和2都是满足顺序一致性的,C和D拿到的顺序都是1-2或2-1,只要CD的顺序一致,就是满足顺序一致性。只是从全局看来,情况1更真实,情况2就显得"错误"了,因为情况2是这样的顺序

B W(x,2) -> A W(x,1) -> C R(x,2) -> D R(x,2) -> C R(x,1) -> D R(x,1)

不过一致性不保证正确性,所以这仍然是一个顺序一致,再加一种情况3

A:--W(x,1)------------------------
B:  --W(x,2)------------------------
C:                            -R(x,2)             --R(x,1)-
D:                      -R(x,1)-            --R(x,2)-- 

情况3就不属于顺序一致了,因为C和D两个进程的读取顺序不同了,回到情况2,C和D拿数据发起的时间是不同的,且有重叠,有可能C拿到1的时候,D已经拿到了2,这就导致了不同的客户端在相同的时间获取了不一样的数据,但其实这种模式在现实中的用的听广泛的:
如,你在Twitter上写了两条推文,你的操作会耗费一定的时间渗透进一层层的缓存系统,不同的朋友将在不同的时间看到你的信息,但每个朋友都会以相同顺序看到了你的两条推文,不会是乱序。只是一个朋友已经看到了第二条,一个朋友才刚看到第一条,不过没关系,它总会看到两条,顺序没错就行,无伤大雅。但有些时候,顺序一致性是不满足要求的

举例说明3:

在这里插入图片描述

从时间轴上可以看到,B0发生在A0之前,读取到的x值为0.B2发生A0之后,读取到的x值为1.而读操作B1,C0,C1与写操作A0在时间轴上有重叠,因此它们可能读取到旧的值0,也可能读取到新的值1,注意,C1发生在B1之后(二者在时间轴上没有重叠),但是B1看到x的新值,C1反而看到的是旧值。对于用户来说,x的值发生了回调。即要求任何一次读都能读取到最新数据,和全局时钟一致,对比例1,既满足顺序一致又满足线性一致应该是这样的。如图所示。在这里插入图片描述

每个读操作都读到了该变量的最新写的结果,同时两个进程看到的操作顺序与全局时钟的顺序一样,都是Write(y,2),Read(x,4),Write(x,4),Read(y,2)

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

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

相关文章

Docker常用镜像安装

1. mysql 1.1 安装 获取镜像 docker pull mysql:8.0.30创建文件挂载目录 创建容器并运行 docker run -p 3306:3306 --name mysql8 \ -v /home/docker/mysql8/log:/var/log/mysql \ -v /home/docker/mysql8/data:/var/lib/mysql \ -v /home/docker/mysql8/mysql-files:/va…

<网络安全>《83 微课堂<国家数据要素总体框架>》

1 总体框架 国家数据要素化总体框架由“六横两纵”共八个关键环节构成。 2 国家数据基础设施(NDI) 最底部第一层是国家数据基础设施(NDI)。国家数据基础设施(NDI)是经济社会进入数据要素化发展新阶段后新…

ASP.NET银行大厅自助信息系统的开发与实现

摘 要 本毕业设计在基于银行业务大厅现有业务的基础上,针对自助银行的概念和其独有特点,通过.NETSQL技术,开发一个简单的银行大厅自助信息系统,完成一些自助银行的业务需求如帐户信息查询、帐户挂失、自助交费、留言、新闻查询…

0510Goods的Maven项目

0510Goods的Maven项目包-CSDN博客 数据库字段 商品主页 修改页面 点击商品主页更改信息, 跳转到修改页面, 并保留初始信息。 商品类别最多选取三项,最少选取一项 添加界面 商品类别最多选取三项,最少选取一项

java 并发线程应用

java 并发线程相关 线程状态 新建(NEW): 创建后尚未启动。可运行(RUNABLE): 正在 Java 虚拟机中运行。但是在操作系统层面,它可能处于运行状态,也可能等待资源调度(例如处理器资源),资源调度完成就进入运行状态。所以该状态的可运行是指可以被运行,具体有没有运行要看底层…

刷题之找到字符串所有字母异位词

找到字符串所有字母异位词 滑动窗口。滑动窗口大小为待比较数组的大小。 class Solution { public:vector<int> findAnagrams(string s, string p) {//滑动窗口vector<int>result;if(s.size()<p.size())return result;vector<int>pnum(26,0);//记录p的字…

steam商店打不开、steam商店错误代码-118的解决方法

现在steam已经开始了&#xff0c;有很多好玩的游戏都在这段时间相继打折&#xff0c;虽然游戏众多&#xff0c;但是不是所有人都能把这些游戏都买下来&#xff0c;有一些小伙伴喜欢的游戏苦于没有足够的资本去购买&#xff0c;steam会以各种名义举办特惠活动吸引玩家们&#xf…

2024 年中国大学生程序设计竞赛全国邀请赛(郑州)暨第六届CCPC河南省大学生程序 设计竞赛Problem A. Once In My Life

//构造 #include<bits/stdc.h> using namespace std; #define int long long int a,b,c ; signed main() {ios::sync_with_stdio(false);cin.tie(0),cout.tie(0);cin>>a;while(a--){cin>>b>>c;int mb,k0;while(m){m/10;k;}int v0;for(int i1;i<9;…

MySQL表的基本操作

表 创建表 comment是添加一个注释 语法&#xff1a; 说明&#xff1a; field 表示列名 datatype 表示列的类型 character set 字符集&#xff0c;如果没有指定字符集&#xff0c;则以所在数据库的字符集为准 collate 校验规则&#xff0c;如果没有指定校验规则&#xff0c;则…

景源畅信:抖音小店比较冷门的品类分享?

在抖音小店的世界里&#xff0c;热门品类总是吸引着众多商家和消费者的目光。然而&#xff0c;就像星空中的繁星&#xff0c;虽不那么耀眼却依然存在的冷门品类同样值得我们关注。它们或许不似服装、美妆那样日进斗金&#xff0c;但正是这些小众市场的存在&#xff0c;为平台带…

(四十二)第 6 章 树和二叉树(树的二叉链表(孩子-兄弟)存储)

1. 背景说明 2. 示例代码 1) errorRecord.h // 记录错误宏定义头文件#ifndef ERROR_RECORD_H #define ERROR_RECORD_H#include <stdio.h> #include <string.h> #include <stdint.h>// 从文件路径中提取文件名 #define FILE_NAME(X) strrchr(X, \\) ? strrch…

Keil编程不同驱动文件引用同一个常量的处理方法

基础不牢&#xff0c;地动山摇&#xff0c;最近单片机编程又遇到一个基础问题。 我在头文件中定义了一个常量同时给两个驱动文件使用&#xff0c;封装的时候编译没问题&#xff0c;但是在main函数中引用驱动函数的时候就出现了重定义的问题&#xff0c;如下如所示。 解决方法很…