8、架构-分布式的共识

     概述

   在正式探讨分布式环境中面临的各种技术问题和解决方案前,我 们先把目光从工业界转到学术界,学习几种具有代表性的分布式共识 算法,为后续在分布式环境中操作共享数据准备好理论基础。下面笔 者从一个最浅显的场景开始,引出本章的主题:

如果你有一份很重要的数据,要确保它长期存储在电脑上不会丢 失,你会怎么做?

         这不是什么脑筋急转弯的古怪问题,答案就是去买几块硬盘,在 不同硬盘上多备份几个副本。假设一块硬盘每年损坏的概率是5%,把 文件复制到另一块备份盘上,两块硬盘同时损坏而丢失数据的概率就 只有0.25%,如果使用三块硬盘存储则丢失数据的概率是0.00125%,四 块是0.0000625%,换言之,四块硬盘就可以保证数据在一年内有超过 99.9999%的概率是安全可靠的。
        在软件系统里,要保障系统的可靠性,采用的办法与上面用几个 备份硬盘来保障的方法并没有什么区别。单个节点的系统宕机导致数 据无法访问的原因可能有很多,譬如程序出错、硬件损坏、网络分 区、电源故障,等等,一年中出现系统宕机的概率也许还要高于5%, 这决定了软件系统也必须有多台机器,并且它们拥有一致的数据副 本,才有可能对外提供可靠的服务。

        在软件系统里,要保障系统的可用性,面临的困难与硬盘备份面 临的困难又有着本质的区别。硬盘之间是孤立的,不需要互相通信, 备份数据是静态的,初始化后状态就不会发生改变,由人工进行的文 件复制操作,很容易就保障了数据在各个备份盘中的一致性。然而在 分布式系统中,我们必须考虑动态的数据如何在不可靠的网络通信条 件下,依然能在各个节点之间正确复制的问题。将我们要讨论的场景 做如下修改:

        如果你有一份会随时变动的数据,要确保它正确地存储于网络中 的几台不同机器之上,你会怎么做?

         相信最容易想到的答案一定是“数据同步”:每当数据发生变 化,把变化情况在各个节点间的复制视作一种事务性的操作,只有系 统里每一台机器都反馈成功、完成磁盘写入后,数据的变化才宣告成 功。使用2PC/3PC就可以实现这种同步操 作。一种真实的数据同步应用场景是数据库的主从全同步复制(Fully Synchronous Replication),譬如MySQL集群,它在进行全同步复制 时,会等待所有Slave节点的Binlog都完成写入后,才会提交Master节 点的事务。(这个场景中Binlog本身就是要同步的状态数据,不应将 它看作指令日志的集合。)然而这里有一个明显的缺陷,尽管可以确 保Master节点和Slave节点中的数据是绝对一致的,但任何一个Slave 节点因为任何原因未响应均会阻塞整个事务,每增加一个Slave节点, 都会造成整个系统可用性风险增加一分。

        以同步为代表的数据复制方法,被称为状态转移(State Transfer),是较符合人类思维的可靠性保障手段,但通常要以牺牲 可用性为代价。我们在建设分布式系统的时候,往往不能承受这样的 代价,一些关键系统,在必须保障数据正确可靠的前提下,也对可用 性有非常高的要求,譬如系统要保证数据达到99.999999%可靠,同时 系统自身也要达到99.999%可用的程度。这就引出了我们的第三个问 题:

        如果你有一份会随时变动的数据,要确保它正确地存储于网络中 的几台不同机器之上,并且要尽可能保证数据是随时可用的,你会怎 么做?

         可靠性与可用性的矛盾造成了增加机器数量反而带来可用性的降 低。为缓解这个矛盾,在分布式系统里主流的数据复制方法是以操作 转移(Operation Transfer)为基础的。我们想要改变数据的状态, 除了直接将目标状态赋予它之外,还有另一种常用的方法是通过某种 操作,令源状态转换为目标状态。能够使用确定的操作促使状态间产 生确定的转移结果的计算模型,在计算机科学中被称为状态机(State Machine)。

        状态机有一个特性:任何初始状态一样的状态机,如果执行的命 令序列一样,则最终达到的状态也一样。如果将此特性应用在多参与 者的协商共识上,可以理解为系统中存在多个具有完全相同的状态机 (参与者),这些状态机能最终保持一致的关键就是起始状态完全一 致和执行命令序列完全一致。

        根据状态机的特性,要让多台机器的最终状态一致,只要确保它 们的初始状态是一致的,并且接收到的操作指令序列也是一致的即 可,无论这个操作指令是新增、修改、删除抑或是其他任何可能的程 序行为,都可以理解为要将一连串的操作日志正确地广播给各个分布 式节点。在广播指令与指令执行期间,允许系统内部状态存在不一致 的情况,即并不要求所有节点的每一条指令都是同时开始、同步完成 的,只要求在此期间的内部状态不能被外部观察到,且当操作指令序 列执行完毕时,所有节点的最终状态是一致的,则这种模型就被称为 状态机复制(State Machine Replication)

        考虑到分布式环境下网络分区现象是不可能消除的,甚至允许不 再追求系统内所有节点在任何情况下的数据状态都一致,而是采用 “少数服从多数”的原则,一旦系统中过半数的节点完成了状态的转 换,就认为数据的变化已经被正确地存储在了系统中,这样就可以容 忍少数(通常是不超过半数)的节点失联,减弱增加机器数量对系统 整体可用性的影响,这种思想在分布式中被称为“Quorum机制”。

        根据上述讨论,我们需要设计出一种算法,能够让分布式系统内 部暂时容忍不同的状态,但最终保证大多数节点的状态达成一致;同 时,能够让分布式系统在外部看来始终表现出整体一致的结果。这个 让系统各节点不受局部的网络分区、机器崩溃、执行性能或者其他因 素影响,都能最终表现出整体一致的过程,就被称为各个节点的协商 共识(Consensus)。

Paxos

        世界上只有一种共识协议,就是Paxos,其他所有共识算法都是 Paxos的退化版本。

                                                                                        ——Mike Burrows,Google Chubby作者

        Paxos是由Leslie Lamport(就是大名鼎鼎的LaTeX中的“La”) 提出的一种基于消息传递的协商共识算法,是当今分布式系统最重要 的理论基础,几乎就是“共识”二字的代名词。这个极高的评价出自 于提出Raft算法的论文,更显分量十足。虽然笔者认为Mike Burrows所言有些夸张,但是如果没有Paxos,那后续的Raft、ZAB等算 法,ZooKeeper、etcd等分布式协调框架、Hadoop、Consul等在此基础 上的各类分布式应用都很可能会延后好几年面世。

        为了解释清楚Paxos算法,Lamport虚构了一个名为“Paxos”的希 腊城邦,这个城邦按照民主制度制定法律,却没有一个中心化的专职 立法机构,而是靠着“兼职议会”(Part-Time Parliament)来完成 立法,无法保证所有城邦居民都能够及时了解新的法律提案,也无法 保证居民会及时为提案投票。Paxos算法的目标就是让城邦能够在每一 位居民都不承诺一定会及时参与的情况下,依然可以按照少数服从多 数的原则,最终达成一致意见。但是Paxos算法并不考虑拜占庭将军问 题,即假设信息可能丢失也可能延迟,但不会被错误传递。 Lamport在1990年首次发表了Paxos算法,选的论文题目就是“The Part-Time Parliament”。由于算法本身极为复杂,用希腊城邦作为 比喻反而使得描述更晦涩,论文的三个审稿人一致要求他把希腊城邦 的故事删掉。这令Lamport感觉颇为不爽,干脆就撤稿不发了,所以 Paxos刚刚被提出的时候并没有引起什么反响。八年之后(1998年), Lamport将此文章重新整理后投到ACM Transactions on Computer Systems。这次论文成功发表,Lamport的名气也确实吸引了一些人去 研究,但并没有多少人能弄懂他在说什么。时间又过去了三年(2001 年),Lamport认为前两次的论文没有引起反响,是因为同行们无法理 解他以“希腊城邦”来讲故事的幽默感,所以这一次他以“Paxos Made Simple”为题,在SIGACT News杂志上发表文章,放弃了“希腊 城邦”的比喻,尽可能用(他认为)简单直接、(他认为)可读性较 强的方式去介绍Paxos算法。情况虽然比前两次要好上一些,但以 Paxos本应获得的重视程度来说,这次依然只能算是应者寥寥。

        这一段 听起来如同网络段子一般的经历被Lamport以自嘲的形式放到了他的个 人网站上。尽管我们作为后辈应该尊重Lamport老爷子,但当笔者 翻开“Paxos Made Simple”的论文,见到只有“The Paxos algorithm,when presented in plain English,is very simple.”这 一句话的“摘要”时,心里实在是不得不怀疑Lamport这样写论文是不 是在恶搞审稿人和读者,在嘲讽“你们这些愚蠢的人类”。 虽然Lamport本人连发三篇文章都没能让大多数同行理解Paxos, 但2006年,在Google的Chubby、Megastore以及Spanner等分布式系统 都使用Paxos解决了分布式共识的问题,并将其整理成正式的论文发表 之后,得益于Google的行业影响力,辅以Chubby作者Mike Burrows那 略显夸张但足够吸引眼球的评价推波助澜,Paxos算法一夜间成为计算 机科学分布式这条分支中最炙手可热的概念,开始被学术界众人争相 研究。Lamport本人因其对分布式系统的杰出理论贡献获得了2013年的 图灵奖,随后才有了Paxos在区块链、分布式系统、云计算等多个领域 大放异彩的故事。

算法流程

下面,我们来正式学习Paxos算法(在本节中Paxos均特指最早的 Basic Paxos算法)。Paxos算法将分布式系统中的节点分为三类。

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

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

相关文章

金钱的认知,你如何理解呢?

金钱的认知 建立在金钱之上的爱情是纯真的爱,朋友关系也才够纯粹,才是单纯的世界,反之没了钱的条件爱情和友情的美好关系极易破碎,也极易反目成仇。 心若美好钱就美好,心有欲望狰狞钱就是只咬人的老虎,钱…

python练习五

Title1:请实现一个装饰器,每次调用函数时,将函数名字以及调用此函数的时间点写入文件中 代码: import time time time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) # 获取当前的时间戳 # 定义一个有参装饰器来实…

Linux 僵尸进程和孤儿进程

一.Z(zombie)-僵尸进程 1.僵死状态(Zombies)是一个比较特殊的状态。当进程退出并且父进程(使用wait()系统调用后)没有读取到子进程退出的返回代码时就会产生僵死(尸)进程 2.僵死进程会以终止状态保持在进程表中,并且会…

【代码随想录37期】Day24 回溯 组合

理论基础 回溯是一种搜索方式,通常通过穷举来解决问题,核心思想是从一个初始状态出发、暴力搜索所有可能的方案,遇到正确的解法则记录下来,直到结束,这是一个典型的深度优先搜索思想:不撞南墙不回头 回溯…

Java17 --- SpringCloud之seate

目录 一、创建seata需要的mysql数据库表 二、修改seata的配置文件 三、启动nacos及seata 四、创建需要的数据库及表 一、创建seata需要的mysql数据库表 CREATE DATABASE seata;CREATE TABLE IF NOT EXISTS global_table(xid VARCHAR(128) NOT NULL,…

C++ | Leetcode C++题解之第128题最长连续序列

题目&#xff1a; 题解&#xff1a; class Solution { public:int longestConsecutive(vector<int>& nums) {unordered_set<int> num_set;for (const int& num : nums) {num_set.insert(num);}int longestStreak 0;for (const int& num : num_set) {…

隐马尔可夫链

1 马尔可夫链 马尔科夫链&#xff08;Markov Chain&#xff09;是一种数学模型&#xff0c;它描述了一系列可能事件的概率&#xff0c;其中每个事件的发生仅依赖于前一个事件的状态。这一特性称为“无记忆性”或“马尔可夫性质”。我将用一个简单的天气预测模型作为例子来解释马…

【组合数学 隔板法 容斥原理】放球问题

本文所属分类 组合数学汇总 8类放球问题 放球问题是一类很有意思的排列组合问题。通俗来说&#xff0c;就是把n个小球放到m个盒子里&#xff0c;问有几种放法。具体可以从3个维度&#xff0c;每个维度2种情况&#xff0c;共8种情况&#xff1a; 维度一&#xff1a;小球是否相…

对象业务的追加写接口

类似文件的追加写操作&#xff0c;在对象的末尾增加新的数据内容。 本文有如下假定&#xff1a; 对象存储服务基于文件语义实现。使用PUT方式上传的对象&#xff0c;内部使用一个文件和对应的元数据来承载。使用多段方式上传的对象&#xff0c;内部使用多个段文件、元数据来承…

【面试题-012】什么是Spring 它有哪些优势

文章目录 Spring有哪些优势有哪些优势Spring和Springboot区别在 Spring 框架中&#xff0c;什么是AOP核心概念应用场景 Spring有哪些通知类型 Spring 是一个开源的 Java 平台&#xff0c;由 Rod Johnson 创建&#xff0c;用于简化企业级 Java 应用程序的开发。它于 2003 年首次…

T-Pot多功能蜜罐实践@debian12@FreeBSD

T-Pot介绍 T-Pot是一个集所有功能于一身的、可选择分布式的多构架&#xff08;amd64&#xff0c;arm64&#xff09;蜜罐平台&#xff0c;支持20多个蜜罐和很多可视化选项&#xff0c;使用弹性堆栈、动画实时攻击地图和许多安全工具来进一步改善欺骗体验。GitHub - telekom-sec…

15.FreeRTOS数据结构:StreamBuffer,MessageBuffer和Queue的区别

FreeRTOS数据结构&#xff1a;StreamBuffer&#xff0c;MessageBuffer和Queue的区别 介绍 在嵌入式系统开发中&#xff0c;任务间的通信是非常重要的一部分。FreeRTOS提供了多种数据结构来实现任务间的通信&#xff0c;包括StreamBuffer&#xff0c;MessageBuffer和Queue。这…

SpringBootWeb登录认证

JWT令牌 JSON Web Token JSON Web Tokens - jwt.ioJSON Web Token (JWT) is a compact URL-safe means of representing claims to be transferred between two parties. The claims in a JWT are encoded as a JSON object that is digitally signed using JSON Web Signatur…

MogDBopenGauss查询重写规则uniquecheck

在MogDB&openGauss中&#xff0c;参数rewrite_rule用于控制查询重写&#xff0c;本文介绍查询重写规则uniquecheck uniquecheck表示提升无agg的where子查询 现在有如下例子 orcl> explain analyze select count(*)from test01 t1where t1.data_object_id (select data…

文件系统和日志分析

文件系统 概述 文件是存储在硬盘上的。硬盘上的最小存储单位是扇区&#xff0c;每个扇区的大小是512字节。 inode号&#xff1a;又叫索引号&#xff0c;保存的是元信息&#xff08;主要有文件的属性 &#xff1a;包括权限&#xff0c;创建者&#xff0c;创建日期等&#xff…

Nodejs 调用langchain的实验

langchain 支持js/ts 语言&#xff0c;可以在nodeJs 中调用langchain 。这有利于在网站后台软件中使用&#xff0c;本博文记录做的小实验。 安装与升级 升级node 直接在官网下载&#xff0c;重新安装就可以了。 安装大模型模块 npm install openai 安装langchain npm insta…

Renesas MCU之使用e² studio搭建开发环境

目录 概述 1 e studio介绍 2 搭建Renesas MUC开发环境 2.1 软件版本信息 2.2 安装软件 3 创建工程 3.1 板卡硬件接口 3.2 FSP配置IO 4 Generate Project 4.1 项目目录介绍 4.2 LED接口相关驱动 5 调试 5.1 测试代码 5.2 J-Link调试代码 5.3 硬件结构 概述 本文主…

ES6-01-简介

一、什么是ES6&#xff1f; 每年一个版本o(╥﹏╥)o。 二、javaScript新特性的特点 1、语法简洁&#xff0c;功能丰富&#xff1b; 2、框架开发应用。 3、岗位需求&#xff01; 三、let关键字 3-1、声明变量 let a;let a,b;let e100;let f521, gmilk-love, h[]; 3-2、声明的…

python采集汽车价格数据

python采集汽车价格数据 一、项目简介二、完整代码一、项目简介 本次数据采集的目标是车主之家汽车价格数据,采集的流程包括寻找数据接口、发送请求获取响应、解析数据和持久化存储,先来看一下数据情况,完整代码附后: 二、完整代码 #输入请求页面url #返回html文档 imp…

Linux C/C++目录操作

获取当前目录 #include <unistd.h>char *getcwd(char *buf,size_t size); char *get_current_dir_name(void);//注意释放内存 malloc() free()切换工作目录 #include <unistd.h>int chdir(const char *path);//0成功&#xff0c;其他失败&#xff08;目录不存在…