主頁 > 後端開發 > 用三國殺講分布式演算法,舒適了吧?

用三國殺講分布式演算法,舒適了吧?

2020-12-16 15:40:20 後端開發

前言

《三國殺》是一款熱門的卡牌游戲,結合中國三國時期背景,以身份為線索,以卡牌為形式,益智休閑,老少皆宜,
東漢末年,袁紹作為盟主,匯合了十八路諸侯一起攻打董卓,

在講解之前,我們先聊下分布式協議和演算法整體脈絡,

現在很多開發同學對分布式的組件怎么使用都有一定經驗,也知道 CAP 理論和 BASE 理論的大致含義,但認真去看分布式演算法的真的很少,原因有三:

擔心演算法過于復雜,所以花的時間很少,
網上的資料能用大白話將分布式演算法講清楚的比較少,
學習分布式演算法沒有一條清晰的路線,
我會在后續的文章中用故事、大白話的方式來講解分布式演算法的原理,以及學習路線到底是怎么樣的,

學習路線

學習分布式協議和演算法的路線可以是先學習四大基礎理論,作為地基,再學習分布式協議和演算法,就像是在地基上建房子,地基打好了,才能建更穩固的高樓大廈,

四大基礎理論
拜占庭將軍問題
CAP 理論
ACID 理論
BASE 理論
八大分布式協議和演算法
Paxos 演算法
Raft 演算法
一致性 Hash 演算法
Gossip 協議演算法
Quorum NWR 演算法
FBFT 演算法
POW 演算法
ZAB 協議
因篇幅原因,本篇只涉及拜占庭將軍問題,

拜占庭將軍問題

大家可能聽過拜占庭將軍問題,它是由萊斯利·蘭伯特提出的點對點通信中的基本問題,

拜占庭位于如今的土耳其的伊斯坦布爾,是東羅馬帝國的首都,由于當時拜占庭羅馬帝國國土遼闊,為了達到防御目的,每個軍隊都分隔很遠,將軍與將軍之間只能靠信差傳訊息,在戰爭的時候,拜占庭軍隊內所有將軍和副官必須達成一致的共識,決定是否有贏的機會才去攻打敵人的陣營,但是,在軍隊內有可能存有叛徒和敵軍的間諜,這個就是拜占庭容錯問題,

實際上拜占庭問題是分布式領域最復雜的一個容錯模型,一旦理解它,就能掌握分布式共識問題的解決思路,還能幫助大家理解常用的共識演算法,也可以幫助我們在作業中選擇合適的演算法,或者設計合適的演算法,

為什么第一個基礎理論是拜占庭將軍問題?

因為它很好地抽象出了分布式系統面臨的共識問題, 上面提到的 8 種分布式演算法中有 5 種跟拜占庭問題相關,可以說弄懂拜占庭問題對后面學習其他演算法就會容易很多,

下面我用三國殺游戲中的身份牌來講解拜占庭將軍問題,

三國殺身份牌

三國殺中主要有四種身份:主公、忠臣、反賊、內奸,每個游戲玩家都會獲得一個身份牌,主公只有 1 個,忠臣 最多 2 個,反賊最多 4個,內奸最多一個,

主公

主公身份牌
獲勝條件: 消滅所有反賊和內奸

技巧: 以自己生存為首要目標,分散反賊注意力,配合忠內剿滅反賊并判斷誰是忠誰是內,

忠臣

忠臣身份牌
獲勝條件:保護主公存活的前提下消滅所有反賊和內奸,

技巧:忠臣是主公的屏障,威懾反賊和內奸的天平,

反賊

反賊身份牌
獲勝條件:消滅主公即可獲勝,

技巧: 反賊作為數量最多的身份,需要集中火力猛攻敵人弱點,正確的思路是獲勝的關鍵,

內奸

內奸身份牌
獲勝條件: 先消滅反賊和忠臣,最后與主公單挑成為最后唯一生還者,

技巧:正確的戰術+ 冷靜的頭腦+ 運氣,

還原拜占庭問題

東漢末年,袁紹作為盟主,匯合了十八路諸侯一起攻打董卓,把董卓定為反賊,袁紹定為主公,另外有兩個忠臣和一個內奸,就選這三個風云人物:曹操,劉備,孫堅(孫權的爸比),內奸扮演的角色是忠臣,主公和兩個忠臣不知道內奸的身份,都當作忠臣對待了,

董卓是非常強大的,擁有精良的西涼兵,麾下還有戰神呂布,大家都知道三英戰呂布的故事,呂布以一已之力對陣劉備、張飛、關羽三人,

要想干掉董卓,袁紹必須統一忠臣的作戰計劃,三位忠臣還不知道有什么其他花花腸子,有一個還是內奸,如果內奸暗通反賊董卓,給忠臣發送誤導性的作戰資訊,該怎么辦?另外假定這幾個忠臣都是通過書信交流作戰資訊,如果書信被攔截了或書信里面的資訊被替換了咋辦?這些場景都可能擾亂作戰計劃,最后出現有的忠臣在進攻,有的忠臣撤退了,那么反賊就可以乘此機會發起進攻,逐一攻破,

袁紹本來就沒有曹操的機智,那他如何讓忠臣們達成共識,制定統一的作戰計劃呢?

上面的映射關系就是一個拜占庭將軍問題的一個簡化表述,袁紹現在面臨的就是典型的共識問題,也就是在可能有誤導資訊的情況下,采用合適的通訊機制,讓多個將軍達成共識,制定一致性的作戰計劃,

一方選擇撤退

劉備、曹操、孫堅通過信使傳遞進攻或撤退的資訊,然后進行協商,到底是進攻還是撤退,遵循少數服從多數,不允許棄權,

曹操疑心比較重,偵查了反賊的地形后,決定撤退,而劉備和孫堅決定進攻,

劉備決定進攻,通過信使告訴曹操和孫堅進攻,

曹操決定撤退,通過信使告訴劉備和孫堅撤退,

孫堅決定進攻,通過信使告訴曹操和劉備進攻,

一方選擇撤退
曹操收到的資訊:進攻 2 票,自己的一張撤退票,票數一比,進攻票:撤退票 = 2 : 1,按照上面的少數服從多數原則進行投票表決,曹操還是會進攻,那么三方的作戰方案都是進攻,所以是一個一致性的作戰方案,最后戰勝了董卓,

內奸登場-撤退

因為我們前期的設定,孫堅作為內奸,早已與反賊董卓私下溝通好了,不攻打董卓,

劉備決定進攻,通過信使告訴曹操和孫堅進攻,

曹操決定撤退,通過信使告訴曹操和孫堅撤退,

孫堅決定撤退,通過信使告訴曹操和劉備撤退,

內奸登場-撤退
劉備收到進攻和撤退各一票,而自己又選擇撤退,所以劉備得到的票數是:進攻 : 撤退 = 1 : 2,遵從少數服從多數的原則,劉備選擇最后選擇撤退,那么三方的作戰方案都是撤退,所以也是一個一致性的作戰方案,

內奸使詐-一進一退

內奸看了上述計劃,發現忠臣都撤退了,并沒有被消滅,就想通過使詐的方式來消滅其中一個忠臣,

劉備決定進攻,通過信使告訴曹操和孫堅進攻,

曹操決定撤退,通過信使告訴劉備和孫堅撤退,

孫堅作為內奸使詐,通過信使告訴劉備進攻,告訴曹操撤退,

內奸使詐-一進一退
那么結果是什么呢?

劉備的票數為進攻 2 票,撤退 1 票,曹操的票數為進攻 1 票,撤退 2 票,按照少數服從多數的原則,劉備最后會選擇進攻,而曹操會選擇撤退,孫堅作為內奸肯定不會進攻,劉備單獨進攻反賊董卓,勢單力薄,被董卓干掉了,

從這個場景中,我們看到內奸孫堅通過發送誤導資訊,非常容易地就干擾了劉備和曹操的作戰計劃,導致兩位忠臣被逐一擊破,這個現象就是二忠一判難題,那么主公袁紹該怎么解決這個問題?

拜占庭問題解法

解法原理
就是將袁紹也參與進來進行投票,這樣就增加了一位忠臣的數量,三個忠臣一個叛賊,然后 4 位將軍做了一個約定,如果沒有收到命令,則執行默認命令,比如撤退,另外約定流程來發送作戰資訊和如何執行作戰指令,這個解法的關鍵點就是執行兩輪作戰資訊協商,

我們來看下第一輪是怎么做的,

第一步:先發送作戰資訊的將軍我們把他稱為指揮官(袁紹),另外的將軍我們稱作副官(劉備,曹操,孫堅),
第二步:指揮官將他的作戰資訊發送給所有的副官,
第三步:每一位副官將從指揮官處收到的作戰資訊,作為自己的作戰指令;假如沒有收到指揮官的作戰資訊,將把默認的撤退作為作戰指令,
我們用圖來演示:袁紹作為主公先發送作戰資訊,作戰指令為進攻,然后曹操、劉備、孫堅收到進攻的作戰指令,

第一輪
再來看下第二輪是怎么做的,

第一輪指揮官(袁紹)已經發送指令了,現在就需要劉備、曹操、孫堅依次作為指揮官給其他兩位副將發送作戰資訊,
然后這三位副將按照少數服從多數的原則,執行收到的作戰指令,
孫堅使詐 - 兩撤退
如果孫堅使詐,比如給曹操和劉備都發送撤退資訊,如下圖所示,那么劉備和曹操收到的作戰資訊為 進攻 2票,撤退 1 票,按照少數服從多數的原則,最后劉備和曹操執行進攻,實作了作戰計劃的一致性,曹操和劉備聯合作戰擊敗了反賊董卓(即使孫堅沒有參加作戰,)

孫堅使詐 - 兩撤退
孫堅使詐 - 一進一退
假如孫堅使詐,給曹操發送撤退指令,給劉備發送進攻指令,那么劉備收到的作戰資訊是進攻 3票,肯定會發起進攻了,而曹操收到的作戰資訊是進攻 2 票,撤退 1 票,最后曹操還是會進攻,所以劉備和曹操還是聯合作戰擊敗了反賊董卓,

如此看來,引入了一位指揮官后,確實可以避免孫堅使詐,但如果是孫堅在第一輪作為指揮官,其他人作為副官呢?

孫堅使詐 - 一進一退
孫堅作為指揮官
第一輪孫堅向其中一個副官袁紹發送撤退指令,向另外兩個副官曹操、劉備發送進攻指令,那么第一輪的結果如下圖:

第一輪
第二輪孫堅休息,其他副官按照孫堅發送的指令開始向另外的副官發送指令,

曹操向劉備和袁紹發送進攻指令,
劉備向曹操和袁紹發送進攻指令,
袁紹向曹操和劉備發送撤退指令,
如下圖所示,最后曹操、劉備、袁紹收到的指令為進攻 2 票,撤退 1 票,按照少數服從多數原則,三個人都是發起進攻,執行了一致的作戰計劃,保證作戰的勝利,

第二輪
小結
通過上面的演示,我們知道了如何解決拜占庭將軍問題,其實蘭伯特在他的論文中也提到過如何解決,

如果叛將人數為 m,將軍數 n >= 3m + 1,那么就可以解決拜占庭將軍問題,
前提條件:叛將數 m 已知,需要進行 m + 1 輪的作戰協商,
這個公式,大家只需要記住就可以了,推到程序可以參考論文,

比如上述的攻打董卓問題,曹操、劉備、孫堅三個人當中,孫堅是叛將,他可以使詐,使作戰計劃不統一,必須增加一位忠臣袁紹來協商共識,才能達成一致性作戰計劃,

拜占庭解法二-簽名

那可以在不增加忠臣的情況下,解決拜占庭的二忠一判問題呢?

解法二就是通過簽名訊息,比如將軍之間通過印章、虎符等信物進行通信,來保證這幾個特征:

簽名無法偽造,對簽名訊息的內容進行任何更改都會被發現,
任何人都能驗證將軍簽名的真偽,
限于篇幅原因,簽名的演示這里就不做展開了,感興趣的@我,后續會加上,

總結

通過三國殺角色來講解分布式中共識場景,那他們和分布式系統的映射關系是怎么樣的呢?

將軍對應計算機節點,
忠臣的將軍對應正常運行的計算機節點,
叛變的將軍對應出現故障并會發送誤導資訊的計算機節點,
信使被殺對應通訊故障、資訊丟失,
信使被間諜替換對應為通訊被惡意攻擊、偽造資訊或劫持通訊,
可不要小瞧拜占庭問題,它可是分布式場景最復雜的的故障場景,比如在數字貨幣的區塊鏈技術中就有用到這些知識點,而且必須使用拜占庭容錯演算法(也就是 Byzantine Fault Tolerance,BFT),

拜占庭容錯演算法還有 FBFT 演算法,PoW 演算法,當然不會在這篇中去講這些演算法,后續再講解,一口吃不了大胖子~

有了拜占庭容錯演算法,肯定有非拜占庭容錯演算法,顧名思義,就是沒有發送誤導資訊的節點,CFT 演算法就是解決分布式系統中存在故障,但不存在惡意節點的場景下的共識問題,簡單來說就是可能因系統故障造成丟失訊息或訊息重復,但不存在錯誤訊息、偽造訊息,對應的演算法有 Paxos 演算法、Raft 演算法、ZAB 協議,后續講解~

上面提到了 5 種演算法,居然都是跟拜占庭問題有關,你說今天講的拜占庭問題重要不重要?
這么多演算法該如何選擇?
節點可信,選非拜占庭容錯演算法,否則就用拜占庭容錯演算法,如區塊鏈中用到的 PoW 演算法,

https://mp.weixin.qq.com/s/2slIJxMmLSoJkj-k5dFTmg

總結了一些2020年的面試題,這份面試題的包含的模塊分為19個模塊,分別是: Java 基礎、容器、多執行緒、反射、物件拷貝、Java Web 、例外、網路、設計模式、Spring/Spring MVC、Spring Boot/Spring Cloud、Hibernate、MyBatis、RabbitMQ、Kafka、Zookeeper、MySQL、Redis、JVM ,
獲取資料以上資料:關注公眾號:有故事的程式員,獲取學習資料,
記得點個關注+評論哦~

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/235664.html

標籤:其他

上一篇:都說?python中的串列很好用,但是在謀定情況下不要使用串列!

下一篇:大廠高頻面試題:如何實作 MySQL 洗掉重復記錄并且只保留一條?

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more