Thinking Above Code:TLA+思維概述

{"type":"doc","content":[{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"本文是《Thinking Above Code:TLA+從入門到實踐》系列文章第一篇。"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https:\/\/lamport.azurewebsites.net\/tla\/tla.html","title":"xxx","type":null},"content":[{"type":"text","text":"TLA+"}]},{"type":"text","text":"是Paxos算法發明者Leslie Lamport的大作。它是一套數學建模工具箱,用於給分佈式系統建模。這個工具箱主要包括形式化建模語言TLA+和形式化驗證工具TLC model checker。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如今Paxos算法幾乎成了分佈式系統一致性算法的事實標準。市面上流行的大多數分佈式系統都直接使用了Paxos算法或其某個變種。但相信搞過分佈式系統的朋友們都會對Paxos算法坎坷的問世過程有所瞭解。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"曾經Lamport爲了能生動形象的表述算法,假借考古學家的口吻講述了古希臘Paxos島上兼職議會(The Part-Time Parliament)的運作過程。論文投出去後,審稿者覺得這種口吻過於隨意,不符合技術文章的風格,沒有給出積極的迴應。Lamport自己甚至還假扮考古學家做了幾次演講,講述Paxos算法,均收效甚微。大家覺得Paxos這個東西太複雜,沒有人知道他到底在說什麼。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"之後Lamport自己又寫了一篇文章"},{"type":"link","attrs":{"href":"https:\/\/www.microsoft.com\/en-us\/research\/publication\/paxos-made-simple\/","title":null,"type":null},"content":[{"type":"text","text":"《Paxos Made Simple》"}]},{"type":"text","text":"進一步介紹Paxos,通篇幾乎沒有任何數學符號。可這時人們又覺得Paxos算法不夠嚴謹,缺少嚴格的數學證明。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"直到新世紀之後,互聯網浪潮風起雲湧,席捲全球。Google作爲互聯網時代的領軍者,聲稱在自家的分佈式鎖服務"},{"type":"link","attrs":{"href":"https:\/\/static.googleusercontent.com\/media\/research.google.com\/zh-CN\/\/archive\/chubby-osdi06.pdf","title":null,"type":null},"content":[{"type":"text","text":"Chubby"}]},{"type":"text","text":"中引入了Paxos算法。此後,Paxos算法一戰成名,成爲分佈式系統一致性算法的事實標準。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"2013年,Lamport也因爲對分佈式系統的重大貢獻,成爲當年的圖靈獎得主。曾經有不少人質疑Paxos算法的數學嚴謹性。殊不知,Lamport本人曾就讀於麻省理工的數學專業,對於數學和物理學都有着極高的造詣。Paxos算法也是他多年使用數學思維爲分佈式系統建模,進而設計出來的。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"多年後,他又把自己的數學思維形式化成爲一套具體的數學語言,也就是TLA+。同時,也開發出了一套可用的形式化驗證工具軟件,也就是TLC model checker。Lamport曾經穿着一件印有“You Want Proof? I'll Give You Proof!”的T恤衫演講,不知是否是對這些人的回擊。看來這老爺子是個老頑童。^_^"}]},{"type":"image","attrs":{"src":"https:\/\/static001.infoq.cn\/resource\/image\/1c\/23\/1c549d11cf8cdf5141fdef228c2eec23.png","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"1. TLA+簡介"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"相信開發過分佈式系統的朋友們都遇到過這種場景:系統開發完成後,通過了所有的測試用例,於是我們信心滿滿的將其上線了。可是線上系統跑着跑着,不知哪一天突然莫名其妙地出現了一些bug。當我們打開日誌,打開GDB,準備追蹤定位這些問題時,它們又無法復現了。可如果放任不管,不知什麼時候,它們又會詭異地冒出來。這種bug非常棘手,甚至讓開發者很崩潰。這個問題本質上是因爲分佈式系統過於複雜,測試case很難覆蓋所有可能的運行場景所導致的。再怎麼細心,總會存在某些corner case。當系統運行到這些場景時,bug就出現了。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"怎麼系統地解決這種問題呢?答案就是本文的主角——TLA+。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"讀者朋友應該對數學建模的過程非常熟悉:我們使用某種數學語言給現實世界中要研究的問題建立數學模型,然後從數學上推導論證模型的某些性質,進而預測在現實世界中未來的趨勢。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.infoq.cn\/resource\/image\/f7\/dc\/f75b9077d81fef4cfb375d47066b19dc.png","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"TLA+就是爲分佈式系統建模的數學語言(主要用到了數理邏輯、集合論和圖論三個數學工具)。我們使用TLA+爲我們的分佈式算法建模,同時針對實際系統的運行場景給出若干約束條件,然後再使用TLC model checker去驗證模型是否滿足這些約束條件。如果驗證通過,我們再用具體的編程語言(比如C\/C++)把算法編程實現出來。這樣系統開發完成後,即使再遇到某些bug,也都是編程過程中本身的bug,都比較好處理。分佈式算法上不會再有問題。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https:\/\/github.com\/taosdata\/TDengine","title":null,"type":null},"content":[{"type":"text","text":"TDengine"}]},{"type":"text","text":"作爲一款開源的分佈式時序數據庫軟件,主要面對的是物聯網這個複雜的運行環境。在物聯網場景下,怎麼保證數據的一致性,同時兼顧讀寫性能,是一個非常大的挑戰。我們對TLA+做了一些探索,用TLA+爲TDengine的分佈式算法建模(基於物聯網場景下改進的Raft算法),以保證其性能和正確性。後續我們會通過一系列文章,講述探索和實踐的過程,供大家參考。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.infoq.cn\/resource\/image\/4f\/c6\/4fcc72ce5acb3faee325495724d86ec6.png","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"2. 狀態機模型(state machine)"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"2.1 狀態(state)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"可以用狀態(state)來描述某個系統在某一時刻的性質。狀態是什麼呢?就是一堆變量。比如用長寬高描述一個箱子,用速度與加速度描述一個運動中的物體。在計算機世界中,同樣可以用一堆變量描述系統當下的狀態。比如用msgs、maxBal、maxVBal和maxVal 4個變量描述一個Paxos節點,用currentTerm、state等9個狀態描述一個Raft節點。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.infoq.cn\/resource\/image\/04\/6f\/043f274255c179e65a31b0ac2889db6f.png","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"2.2 狀態轉變"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在自然界中,物體的狀態是可以隨時間發生改變的,通常用時間t的函數f(t)來描述物體的當下狀態。比如位移 = 速度 x 時間,s=f(t) = vt。這裏的時間t是一個連續的變量。大部分的物理學定律都是這樣,將某些物理量定義爲時間t的函數。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在計算機世界中,同樣也可以把系統狀態描述爲時間t的函數,只是這裏的時間是一個離散量,具體來說,就是CPU中的時鐘滴答。系統隨時間的改變,就可以看成一系列離散的狀態變化。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.infoq.cn\/resource\/image\/3d\/da\/3d6a7a892452deeec0e35187bf88fbda.png","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"3. 分佈式系統"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"分佈式系統包括多個節點,我們把所有節點狀態的集合看成一個統一的全局狀態,用這個統一的全局狀態來描述一個分佈式系統。下面是一個Raft系統的全局狀態。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"通過對比可以看到,原來Raft單節點變量變成了數組,包括currentTerm、state、votedFor和commitIndex。而原來的數組變量變成了二維數組,包括log、votesResponded、votesGranted、nextIndex和matchIndex。另外增加了一個msg變量,用來描述系統節點發出的網絡消息。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"看到這裏,大家可能會有點暈。不過沒關係,這裏只是概要地介紹一下,讓大家對TLA+的思維方式先有個印象。後續這些變量究竟是什麼意思、怎麼使用,我們還會詳細介紹。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.infoq.cn\/resource\/image\/f5\/07\/f549d89572329c39b096464106cc9407.png","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"怎樣定義全局狀態的轉換呢?直觀上我們可以想到:如果某個節點自身的狀態發生了改變,那麼全局狀態自然也會發生改變。另外,如果某個節點發送了一條網絡消息,或者某個節點接收了一條網絡消息,全局狀態也會發生改變。所以,引起系統全局狀態改變的原因包括分佈式系統中任一節點自身的狀態改變和系統中消息的發送。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.infoq.cn\/resource\/image\/55\/2c\/556767b0b248eecb9e14ba8778bfcc2c.png","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當我們能定義分佈式系統全局狀態改變之後,就可以進一步描述分佈式系統的運行。分佈式系統的運行可以看成是全局狀態從某個初始狀態Init起,一系列可能的改變過程。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.infoq.cn\/resource\/image\/a4\/de\/a4f18d3b3583472aac3feee6a7a19ede.png","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"具體系統的一次運行,只能從衆多可能路徑中選取一條,就像歷史有無數種可能,但最終只有一次真實的演變路徑一樣。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.infoq.cn\/resource\/image\/96\/ae\/96f4c1a7763e0d101fdd54fbbe5ef7ae.png","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"4.使用數學語言精準刻畫狀態改變"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這種狀態圖的思路很常見,也很好理解。比如,我們在下棋時,通常會在頭腦中構造出一個全局狀態轉換圖,然後選擇最優的一條路徑。如果可能的路徑太多,還需要做剪枝優化。計算機博弈程序通常是這麼設計的。這裏的狀態轉換也可以叫“走法”,是固定的、簡單的規則。比如對於中國象棋來講,就是“馬走日”“象走田”之類的規則。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.infoq.cn\/resource\/image\/95\/f8\/950665fc754581ea49be3854f9ddabf8.png","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"而分佈式系統的全局狀態轉換很難精確刻畫,因爲它太複雜了,需要使用具有極強描述能力的語言纔行。是什麼語言呢?對了,就是數學。因爲數學是上帝用來描述宇宙的語言(這句話似乎是伽利略說的,無從考證)。數理邏輯和集合論是數學大廈的兩座基石,這兩大工具幾乎是萬能的,所以全局狀態的改變也能用這兩大工具來刻畫。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Lamport天才地提出了這種思想,而且重要的是,他精確定義了語法,同時實現了“數學編譯器”,也就是TLA+。於是我們就可以通過TLA+語言來描述系統狀態的轉換了。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.infoq.cn\/resource\/image\/ef\/22\/ef25f4035cc5250dfec06f49424bf822.png","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"下面的例子是用TLA+語言描述在Paxos協議中,Proposer接收到Accept消息後做出的反應。"}]},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"Phase2a(b) ==\n \/\\ ~ \\E m \\in msgs : (m.type = \"2a\") \/\\ (m.bal = b)\n \/\\ \\E v \\in Values :\n \/\\ \\E Q \\in Quorums :\n \\E S \\in SUBSET {m \\in msgs : (m.type = \"1b\") \/\\ (m.bal = b)} :\n \/\\ \\A a \\in Q : \\E m \\in S : m.acc = a\n \/\\ \\\/ \\A m \\in S : m.maxVBal = -1\n \\\/ \\E c \\in 0..(b-1) :\n \/\\ \\A m \\in S : m.maxVBal =< c\n \/\\ \\E m \\in S : \/\\ m.maxVBal = c\n \/\\ m.maxVal = v\n \/\\ Send([type |-> \"2a\", bal |-> b, val |-> v])\n \/\\ UNCHANGED <>"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"下面的例子是TLA+語言描述的在Raft協議中,節點更新commit_index時做出的反應。"}]},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"AdvanceCommitIndex(i) ==\n \/\\ state[i] = Leader\n \/\\ LET \\* The set of servers that agree up through index.\n Agree(index) == {i} \\cup {k \\in Server :\n matchIndex[i][k] >= index}\n \\* The maximum indexes for which a quorum agrees\n agreeIndexes == {index \\in 1..Len(log[i]) :\n Agree(index) \\in Quorum}\n \\* New value for commitIndex'[i]\n newCommitIndex ==\n IF \/\\ agreeIndexes \/= {}\n \/\\ log[i][Max(agreeIndexes)].term = currentTerm[i]\n THEN\n Max(agreeIndexes)\n ELSE\n commitIndex[i]\n IN commitIndex' = [commitIndex EXCEPT ![i] = newCommitIndex]\n \/\\ UNCHANGED <>"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"5.屬性判斷"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"只描述系統狀態轉換用途不大。關鍵的是,我們想知道系統在各種可能發生的狀態轉換中,具備什麼樣的屬性。同樣,通過TLA+可以描述某一時刻系統的狀態。下面的例子就是TLA+描述Paxos節點value chosen的語句。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"VotedForIn(a, v, b) == \\E m \\in msgs : \/\\ m.type = \"2b\"\n \/\\ m.val = v\n \/\\ m.bal = b\n \/\\ m.acc = a\n \nChosenIn(v, b) == \\E Q \\in Quorums :\n \\A a \\in Q : VotedForIn(a, v, b)\n \nChosen(v) == \\E b \\in Ballots : ChosenIn(v, b)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"系統在每條可能的演化路徑上,無非有如下幾種情況:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"1. 某種屬性從未發生"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"2. 某種屬性一直在發生"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"3. 某種屬性開始時發生了,某一時刻起又永遠地消失了"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"4. 某種屬性一旦發生後,永遠不會消失"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"5. 某種屬性時有時無"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"6. 當屬性1發生後,屬性2就一直髮生"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"下圖用帶顏色的小球表示系統運行中的某個狀態滿足某種屬性,大家稍微仔細看一下,應該不難理解其中的含義。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.infoq.cn\/resource\/image\/94\/43\/94b345e63eb0a1f6caf4f83411856743.png","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"5.1 不變式(Invariance)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"系統在每條可能的演化路徑上,都具備的某種性質,稱爲不變式(Invariance)。比如Paxos的single value chosen不變式如下:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"Consistency == \\A v1, v2 \\in Values : Chosen(v1) \/\\ Chosen(v2) => (v1 = v2)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"也就是說,無論系統怎麼運行,在任意時刻,系統的全局狀態都會滿足Consistency屬性。"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"5.2 時序邏輯(Temporal Logic)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"系統在某條路徑的演化過程裏,可以通過時序邏輯判斷前後狀態的關係。比如某一時刻某個value被chosen,那麼後續時刻,永遠只有這一個value被chosen。TLA+中的TL,就是Temporal Logic。時序邏輯比較複雜,這裏就不展開了。後續用到時會詳細介紹。"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"5.3 safety與liveness"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"safety與liveness這兩個名詞經常出現在分佈式理論的論文中,但卻從來沒有被精確定義過。通過TLA+,可以很顯然地看出它們的含義。同樣,這裏也不展開,後續用到時再詳細介紹。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"6. 系統設計與驗證"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"有了TLA+,我們就可以大膽地設計分佈式系統了。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們可以先用TLA+精確定義出系統,比如Paxos、Raft,或者自己改造後的一些分佈式算法。然後我們根據實際的運行場景和自己的要求,定義出若干檢驗條件,比如數據是否永遠一致,系統中是否會出現雙主等。最後,將定義好的模型和待檢驗條件扔進TLC model checker。TLC model checker會窮舉系統每個可能的演化路徑(內部會生成一張圖,進行廣度優先搜索),同時使用邏輯計算來判斷狀態的屬性與狀態之間的關係。如果某個屬性不滿足,系統就會報錯,而且會給出這種錯誤在怎樣的演化路徑下會出現。如果模型通過了所有的檢驗,我們再用合適的編程語言把模型編程實現就可以了。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這時,開發者就可以非常自信地面對自己做出的系統了。就這樣,分佈式系統corner case這種幾乎無解的難題,被Lamport老爺子使用數學工具給解決了。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"TLA+ Tools截圖如下:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.infoq.cn\/resource\/image\/80\/74\/80f118211c930255831694ce0ca79874.png","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這是一篇概述性的文章,讓大家先對TLA+有一個大概的瞭解。後續會詳細介紹TLA+的技術細節,以及TLA+在TDengine中的實踐過程。歡迎大家一起交流,共同提高。也歡迎大家擁抱開源技術,關注TDengine,一個爲物聯網而生的時序大數據引擎。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"參考資料:"}]},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"http:\/\/lamport.org\/","title":null,"type":null},"content":[{"type":"text","text":"http:\/\/lamport.org"}]}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"《Specifying Systems》by Leslie Lamport"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"作者介紹:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"李明昊,濤思數據工程師。曾就職於百度、360的基礎架構部門,負責大規模分佈式存儲系統的研發工作。"}]}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章