FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

更新分布式 · pascalcpp/PassJava-Learning@8d35556 · GitHub

Commit 8d35556

Browse files
committed
更新分布式
1 parent f09ece9 commit 8d35556

2 files changed

Lines changed: 320 additions & 0 deletions

File tree

Lines changed: 251 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,251 @@
1+
# 用三国杀讲分布式算法,舒适了吧?
2+
3+
## 前言
4+
5+
> 《三国杀》是一款热门的卡牌游戏,结合中国三国时期背景,以身份为线索,以卡牌为形式,益智休闲,老少皆宜。
6+
7+
东汉末年,袁绍作为盟主,汇合了十八路诸侯一起攻打董卓。
8+
9+
在讲解之前,我们先聊下分布式协议和算法整体脉络。
10+
11+
现在很多开发同学对分布式的组件怎么使用都有一定经验,也知道 `CAP` 理论和 `BASE` 理论的大致含义。但认真去看分布式算法的真的很少,原因有三:
12+
13+
- 担心算法过于复杂,所以花的时间很少。
14+
- 网上的资料能用大白话将分布式算法讲清楚的比较少。
15+
- 学习分布式算法没有一条清晰的路线。
16+
17+
我会在后续的文章中用`故事、大白话`的方式来讲解分布式算法的原理,以及学习路线到底是怎么样的?
18+
19+
## 学习路线
20+
21+
学习分布式协议和算法的路线可以是先学习四大基础理论,作为地基,再学习分布式协议和算法,就像是在地基上建房子。地基打好了,才能建更稳固的高楼大厦。
22+
23+
### 四大基础理论
24+
25+
- 拜占庭将军问题
26+
- CAP 理论
27+
- ACID 理论
28+
- BASE 理论
29+
30+
### 八大分布式协议和算法
31+
32+
- Paxos 算法
33+
- Raft 算法
34+
- 一致性 Hash 算法
35+
- Gossip 协议算法
36+
- Quorum NWR 算法
37+
- FBFT 算法
38+
- POW 算法
39+
- ZAB 协议
40+
41+
因篇幅原因,本篇只涉及拜占庭将军问题。
42+
43+
## 拜占庭将军问题
44+
45+
大家可能听过拜占庭将军问题。它是由莱斯利·兰伯特提出的点对点通信中的基本问题,
46+
47+
`拜占庭`位于如今的土耳其的`伊斯坦布尔`,是`东罗马帝国`的首都。由于当时拜占庭罗马帝国国土辽阔,为了达到防御目的,每个军队都分隔很远,将军与将军之间只能靠信差传消息。在战争的时候,拜占庭军队内所有将军和副官必须达成一致的共识,决定是否有赢的机会才去攻打敌人的阵营。但是,在军队内有可能存有叛徒和敌军的间谍,这个就是拜占庭容错问题。
48+
49+
实际上拜占庭问题是分布式领域最复杂的一个容错模型,一旦理解它,就能掌握分布式共识问题的解决思路,还能帮助大家理解常用的共识算法,也可以帮助我们在工作中选择合适的算法,或者设计合适的算法。
50+
51+
为什么第一个基础理论是拜占庭将军问题?
52+
53+
**因为它很好地抽象出了分布式系统面临的共识问题。** 上面提到的 8 种分布式算法中有 5 种跟拜占庭问题相关,可以说弄懂拜占庭问题对后面学习其他算法就会容易很多。
54+
55+
下面我用三国杀游戏中的身份牌来讲解拜占庭将军问题。
56+
57+
## 三国杀身份牌
58+
59+
三国杀中主要有四种身份:主公、忠臣、反贼、内奸。每个游戏玩家都会获得一个身份牌。主公只有 1 个。忠臣 最多 2 个,反贼最多 4个,内奸最多一个。
60+
61+
### 主公
62+
63+
![主公身份牌](https://img-blog.csdnimg.cn/img_convert/f0242dc56b7a416d5a827cddb68179b7.png)
64+
65+
**获胜条件:** 消灭所有反贼和内奸
66+
67+
**技巧:** 以自己生存为首要目标,分散反贼注意力。配合忠内剿灭反贼并判断谁是忠谁是内。
68+
69+
### 忠臣
70+
71+
![忠臣身份牌](https://img-blog.csdnimg.cn/img_convert/d689eb9e5c08bea023cac687ed2116f3.png)
72+
73+
**获胜条件:** 保护主公存活的前提下消灭所有反贼和内奸。
74+
75+
**技巧:** 忠臣是主公的屏障,威慑反贼和内奸的天平。
76+
77+
### 反贼
78+
79+
![反贼身份牌](https://img-blog.csdnimg.cn/img_convert/79d1c38f60f6199be81b22732493b400.png)
80+
81+
**获胜条件:** 消灭主公即可获胜。
82+
83+
**技巧:** 反贼作为数量最多的身份,需要集中火力猛攻敌人弱点。正确的思路是获胜的关键。
84+
85+
### 内奸
86+
87+
![内奸身份牌](https://img-blog.csdnimg.cn/img_convert/dc4da4a316f6a6b85fcc688b27682ad6.png)
88+
89+
**获胜条件:** 先消灭反贼和忠臣,最后与主公单挑成为最后唯一生还者。
90+
91+
**技巧:** 正确的战术+ 冷静的头脑+ 运气。
92+
93+
## 还原拜占庭问题
94+
95+
东汉末年,袁绍作为盟主,汇合了十八路诸侯一起攻打董卓。把董卓定为反贼,袁绍定为主公,另外有两个忠诚和一个内奸,就选这三个风云人物:曹操,刘备,孙坚(孙权的爸比),内奸扮演的角色是忠臣,主公和两个忠臣不知道内奸的身份,都当作忠臣对待了。
96+
97+
![战局 3 vs 2]![mark](https://img-blog.csdnimg.cn/img_convert/9ed7f98b44e6cebe9d4b51d97fe14057.png)
98+
99+
董卓是非常强大的,拥有精良的西凉兵,麾下还有战神吕布。大家都知道三英站吕布的故事,吕布以一已之力对阵刘备、张飞、关羽三人。
100+
101+
要想干掉董卓,袁绍必须统一忠臣的作战计划,三位忠臣还不知道有什么其他花花肠子,有一个还是内奸。如果内奸暗通反贼董卓,给忠臣发送误导性的作战信息,该怎么办?另外假定这几个忠臣都是通过书信交流作战信息,如果书信被拦截了或书信里面的信息被替换了咋办?这些场景都可能扰乱作战计划,最后出现有的忠臣在进攻,有的忠臣撤退了。那么反贼就可以乘此机会发起进攻,逐一攻破。
102+
103+
袁绍本来就没有曹操的机智,那他**如何让忠臣们达成共识,制定统一的作战计划呢?**
104+
105+
上面的映射关系就是一个拜占庭将军问题的一个简化表述,袁绍现在面临的就是典型的**共识问题**。也就是在可能有误导信息的情况下,采用合适的通讯机制,让多个将军**达成共识**,制定一致性的作战计划。
106+
107+
## 一方选择撤退
108+
109+
刘备、曹操、孙坚通过**信使**传递进攻或撤退的信息,然后进行协商,到底是进攻还是撤退。遵循少数服从多数,不允许弃权。
110+
111+
曹操疑心比较重,侦查了反贼的地形后,决定撤退。而刘备和孙坚决定进攻。
112+
113+
- 刘备决定**进攻**,通过信使告诉曹操和孙坚**进攻**
114+
115+
- 曹操决定**撤退**,通过信使告诉刘备和孙坚**撤退**
116+
117+
- 孙坚决定**进攻**,通过信使告诉曹操和刘备**进攻**
118+
119+
![一方选择撤退](https://img-blog.csdnimg.cn/img_convert/fc80c133d47fffa8a4038cfecbde942f.png)
120+
121+
曹操收到的信息:进攻 2 票,自己的一张撤退票,票数一比,进攻票:撤退票 = 2 : 1,按照上面的少数服从多数原则进行投票表决,曹操还是会进攻。那么三方的作战方案都是进攻,所以是一个**一致性**的作战方案。最后战胜了董卓。
122+
123+
## 内奸登场-撤退
124+
125+
因为我们前期的设定,孙坚作为内奸,早已与反贼董卓私下沟通好了,不攻打董卓。
126+
127+
- 刘备决定**进攻**,通过信使告诉曹操和孙坚**进攻**
128+
129+
- 曹操决定**撤退**,通过信使告诉曹操和孙坚**撤退**
130+
131+
- 孙坚决定**撤退**,通过信使告诉曹操和刘备**撤退**
132+
133+
![内奸登场-撤退](https://img-blog.csdnimg.cn/img_convert/e24687be2f6d13e7704aaec5980f820a.png)
134+
135+
刘备收到进攻和撤退各一票,而自己又选择撤退,所以刘备得到的票数是:进攻 : 撤退 = 1 : 2,遵从少数服从多数的原则,刘备选择最后选择撤退,那么三方的作战方案都是撤退,所以也是一个**一致性**的作战方案。
136+
137+
## 内奸使诈-一进一退
138+
139+
内奸看了上述计划,发现忠臣都撤退了,并没有被消灭,就想通过使诈的方式来消灭其中一个忠臣。
140+
141+
- 刘备决定进攻,通过信使告诉曹操和孙坚**进攻**
142+
143+
- 曹操决定撤退,通过信使告诉曹操和孙坚**撤退**
144+
145+
- 孙坚作为内奸使诈,通过信使告诉刘备**进攻**,告诉曹操**撤退**
146+
147+
![内奸使诈-一进一退](https://img-blog.csdnimg.cn/img_convert/17075ef632469e3413dd88f37705750c.png)
148+
149+
那么结果是什么呢?
150+
151+
刘备的票数为**进攻** 2 票,**撤退** 1 票,曹操的票数为**进攻** 1 票,**撤退** 2 票。按照少数服从多数的原则,刘备最后会选择进攻,而曹操会选择撤退,孙坚作为内奸肯定不会进攻,刘备单独进攻反贼董卓,势单力薄,被董卓干掉了。
152+
153+
从这个场景中,我们看到内奸孙坚通过发送误导信息,非常容易地就干扰了刘备和曹操的作战计划,导致两位忠臣被逐一击破。这个现象就是**二忠一判**难题。那么主公袁绍该怎么解决这个问题?
154+
155+
## 拜占庭问题解法
156+
157+
### 解法原理
158+
159+
就是讲袁绍也参与进来进行投票,这样就增加了一位忠臣的数量。三个忠臣一个叛贼。然后 4 位将军做了一个约定,如果没有收到命令,则执行默认命令,比如撤退。另外约定流程来发送作战信息和如何执行作战指令。这个解法的关键点就是执行两轮作战信息协商。
160+
161+
我们来看下**第一轮**是怎么做的。
162+
163+
- 第一步:先发送作战信息的将军我们把他称为**指挥官**(袁绍),另外的将军我们称作**副官**(刘备,曹操,孙坚)。
164+
- 第二步:**指挥官**将他的作战信息发送给所有的副官。
165+
- 第三步:每一位**副官**将从**指挥官**处收到的作战信息,作为自己的作战指令;假如没有收到**指挥官**的作战信息,将把默认的撤退作为作战指令。
166+
167+
我们用图来演示:袁绍作为主公先发送作战信息,作战指令为**进攻**。然后曹操、刘备、孙坚收到**进攻**的作战指令。
168+
169+
![第一轮](https://img-blog.csdnimg.cn/img_convert/850d32a692465c6790b4e3054d0731e0.png)
170+
171+
再来看下**第二轮**是怎么做的。
172+
173+
- 第一轮**指挥官**(袁绍)已经发送指令了,现在就需要刘备、曹操、孙坚依次作为**指挥官**给其他两位**副将**发送作战信息。
174+
- 然后这三位副将按照少数服从多数的原则,执行收到的作战指令。
175+
176+
### 孙坚使诈 - 两撤退
177+
178+
如果孙坚使诈,比如给曹操和刘备都发送撤退信息,如下图所示。那么刘备和曹操收到的作战信息为 进攻 2票,撤退 1 票,按照少数服从多数的原则,最后刘备和曹操执行进攻,实现了作战计划的一致性,曹操和刘备联合作战击败了反贼董卓(即使孙坚没有参加作战。)
179+
180+
![孙坚使诈 - 两撤退](https://img-blog.csdnimg.cn/img_convert/6020c04be49be627dd03a5815a109c43.png)
181+
182+
### 孙坚使诈 - 一进一退
183+
184+
假如孙坚使诈,给曹操发送撤退指令,给刘备发送进攻指令,那么刘备收到的作战信息是进攻 3票,肯定会发起进攻了,而曹操收到的作战信息是进攻 2 票,撤退 1 票,最后曹操还是会进攻,所以刘备和曹操还是联合作战击败了反贼董卓。
185+
186+
如此看来,引入了一位指挥官后,确实可以避免孙坚使诈,但如果是孙坚在第一轮作为指挥官,其他人作为副官呢?
187+
188+
![孙坚使诈 - 一进一退](https://img-blog.csdnimg.cn/img_convert/ea7c8eabeff3393737b9c6fff7455672.png)
189+
190+
### 孙坚作为指挥官
191+
192+
第一轮孙坚向其中一个副官袁绍发送**撤退**指令,向另外两个副官曹操、刘备发送**进攻**指令。那么第一轮的结果如下图:
193+
194+
![第一轮](https://img-blog.csdnimg.cn/img_convert/cf2fd825f33a2f3d687bf6c9368ca5be.png)
195+
196+
197+
198+
第二轮孙坚休息,其他副官按照孙坚发送的指令开始向另外的副官发送指令。
199+
200+
- 曹操向刘备和袁绍发送**进攻**指令。
201+
- 刘备向曹操和袁绍发送**进攻**指令。
202+
- 袁绍向曹操和刘备发送**撤退**指令。
203+
204+
如下图所示,最后曹操、刘备、袁绍收到的指令为进攻 2 票,撤退 1 票,按照少数服从多数原则,三个人都是发起进攻。执行了一致的作战计划,保证作战的胜利。
205+
206+
![第二轮](https://img-blog.csdnimg.cn/img_convert/4ee85cd73ebdcf8f13b5abf938d6d13e.png)
207+
208+
### 小结
209+
210+
通过上面的演示,我们知道了如何解决拜占庭将军问题。其实兰伯特在他的论文中也提到过如何解决。
211+
212+
> 如果叛将人数为 m,将军数 n >= 3m + 1,那么就可以解决拜占庭将军问题。
213+
>
214+
> 前提条件:叛将数 m 一致,需要进行 m + 1 轮的作战协商。
215+
216+
这个公式,大家只需要记住就可以了,推到过程可以参考论文。
217+
218+
比如上述的攻打董卓问题,曹操、刘备、孙坚三个人当中,孙坚是叛将,它可以使诈,使作战计划不统一。必须增加一位忠臣袁绍来协商共识,才能达成一致性作战计划。
219+
220+
## 拜占庭解法二-签名
221+
222+
那可以在不增加忠臣的情况下,解决拜占庭的二忠一判问题呢?
223+
224+
解法二就是通过签名消息。比如将军之间通过印章、虎符等信物进行通信。来保证这几个特征:
225+
226+
- 签名无法伪造,对签名消息的内容进行任何更改都会被发现。
227+
- 任何人都能验证将军签名的真伪。
228+
229+
限于篇幅原因,签名的演示这里就不做展开了,感兴趣的@我,后续会加上。
230+
231+
## 总结
232+
233+
通过三国杀角色来讲解分布式中共识场景。那他们和分布式系统的映射关系是怎么样的呢?
234+
235+
- 将军对应计算机节点。
236+
- 忠臣的将军对应正常运行的计算机节点。
237+
- 叛变的将军对应出现故障并会发送误导信息的计算机节点。
238+
- 信使被杀对应通讯故障、信息丢失。
239+
- 信使被间谍替换对应为通讯被恶意攻击、伪造信息或劫持通讯。
240+
241+
可不要小瞧拜占庭问题,它可是分布式场景最复杂的的故障场景。比如在数字货币的区块链技术中就有用到这些知识点。而且必须使用**拜占庭容错**算法(也就是 Byzantine Fault Tolerance,`BFT`)。
242+
243+
拜占庭容错算法还有 `FBFT` 算法,`PoW` 算法,当然不会在这篇中去讲这些算法,后续再讲解。一口吃不了大胖子~
244+
245+
有了拜占庭容错算法,肯定有**非拜占庭容错**算法,顾名思义,就是没有发送误导信息的节点。`CFT` 算法就是解决分布式系统中存在故障,但不存在恶意节点的场景下的共识问题。简单来说就是可能因系统故障造成丢失消息或消息重复,但不存在错误消息、伪造消息。对应的算法有 `Paxos` 算法、`Raft` 算法、`ZAB` 协议。后续讲解~
246+
247+
上面提到了 5 种算法,居然都是跟拜占庭问题有关,你说今天讲的拜占庭问题重要不重要?
248+
249+
**这么多算法该如何选择?**
250+
251+
节点可信,选非拜占庭容错算法。否则就用拜占庭容错算法,如区块链中用到的 PoW 算法。
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
张三丰教我的分布式太极拳,我全忘了
2+
3+
> 背景:元朝赵敏郡主携带一帮高手围攻武当,武当派掌门张三丰被暗算,传了一套武功给张无忌用来对付赵敏。这套武功就是太极拳。
4+
>
5+
> 张三丰:无忌,你可记得多少招式?
6+
>
7+
> 张无忌:我全忘了!
8+
>
9+
> 张三丰:很好,你只要记住把玄冥二老打趴下就可以了。
10+
11+
上篇用三国杀讲分布式中的拜占庭将军问题,还挺有意思的,这次我们用太极拳来聊下剩下的三大理论:
12+
13+
- CAP 理论
14+
- ACID 理论
15+
- BASE 理论
16+
17+
太极拳的精髓:以柔克刚,刚柔并进,四两拨千斤,无招胜有招。
18+
19+
我把 CAP 理论称作`太极`,ACID 理论成为````,BASE 理论称为````。ACID 理论追求一致性,BASE 理论本来就叫做柔性事务,追求的是可用性。那张无忌为什么会全忘了还打败了玄冥二老呢?因为太极拳的精髓拳意,无招胜有招。
20+
21+
## 刚或柔是个问题
22+
23+
CAP 理论是对分布式系统的特性做了一个高度的抽象,变成了三大指标:
24+
25+
- 一致性(Consistency)
26+
- 可用性(Availability)
27+
- 分区容错性(Partition Tolerance)
28+
29+
分布式中的一致性,我们可以理解为客户端的每次`读操作`,不管访问的是哪个几点,要么督导的都是同一份最新写入的数据,要么读取失败。这就很刚了,不能说这种``不好,在很多场景中,也确实需要保证高度的一致性。
30+
31+
为了帮助大家理解一致性,我举个`三国`的故事:
32+
33+
刘备作为主公,带领关羽和张飞攻打曹操,最开始的进攻策略是从北边进攻。刘备发现从北边进攻不妙,于是先给关羽军队下达进从南边进攻的命令,但是关羽和刘备没有告诉张飞的军队,要从南边进攻,刘备次日看到关羽从北边进攻,张飞从南边进攻,这不就乱套了吗?如下图所示:
34+
35+
![刘关张攻打曹操](http://cdn.jayh.club/blog/20201227/3cRbQVF2gFjW.png?imageslim)
36+
37+
那放到分布式系统中该如何理解呢?
38+
39+
- 初始环境:客户端查询或更新节点 1 和 节点 2,两个节点存的值 A = 1。
40+
41+
![初始环境](http://cdn.jayh.club/blog/20201227/qjcfzRA61Jne.png?imageslim)
42+
43+
- 客户端更新节点 1 中 A 的值,设置 A = 5。
44+
45+
![客户端更新节点 1](http://cdn.jayh.club/blog/20201227/Vtb8YElS3Yhr.png?imageslim)
46+
47+
- 节点 1 将 A 的值更新为 5 后,返回更新成功给客户端。
48+
49+
![节点 1 返回更新成功](http://cdn.jayh.club/blog/20201227/ajCr3gVEcJWy.png?imageslim)
50+
51+
- 客户端访问到了节点 2 ,请求获取 A 的值,结果返回 A = 1。这和节点 1 中存储的 A 的值就不一致了。
52+
53+
![客户端访问到节点 2 ](http://cdn.jayh.club/blog/20201227/cdBBEgbCpWE3.png?imageslim)
54+
55+
- 那么怎么保证两个节点中的值都是 A = 5 呢?客户端将节点 1 更新后,节点 2 也需要更新,才能告诉客户端更新成功了。
56+
57+
![mark](http://cdn.jayh.club/blog/20201227/i9VOHtWYwlNx.png?imageslim)
58+
59+
- 两个节点都更新成功后,客户端访问其中任意一个节点获取到的都是 A = 5。这个就叫做一致性。
60+
61+
![两个节点都更新后](http://cdn.jayh.club/blog/20201227/zmRI0Q5D3u9D.png?imageslim)
62+
63+
一致性强调的是数据正确,每次读取节点中的数据都是最新写入的数据。但是
64+
65+
## 刚柔并进
66+
67+
68+
69+
## 无招胜有招

0 commit comments

Comments
 (0)

Back | FazBrowse Home | New Git URL