1. 程式人生 > >辨析三種一致性:快取一致、記憶體一致、資料一致

辨析三種一致性:快取一致、記憶體一致、資料一致

本文由giantpoplar發表於CSDN,轉載請保留本宣告。

“Cache Coherence” V.S. “Memory Consistency” V.S. “Data Consistency”

快取一致性

cache coherence 的coherence這個詞猜測是體系結構圈為了和memory consistency做區分,用了coherence這個詞,但我理解快取一致性和分散式多副本資料的一致性基本接近,只不過cache coherence是一種同步可靠通訊、有全域性時鐘條件下的強一致(linearizability)。cache一致性協議有MSI,MESI等,雖然處理器的整個記憶體系統很複雜,但就cache一致性協議來說,比分散式環境下的資料一致要簡明一些

多核處理器每個核會有私有cache,也就是記憶體裡的一份資料在多個核上可能有了副本,這多個副本,每個核都可能會對一個記憶體地址有讀寫操作,每個核是直接讀寫自己私有的副本,這就要求各個副本上的讀寫操作順序要一致,這和分散式環境下的資料一致性很接近。

具體的MSI,MESI協議暫不展開寫。

記憶體一致性

記憶體一致性說的是共享記憶體多核處理器訪存序的問題,程序對某一個記憶體地址(和分散式的同一資料多副本的一致性有所區別)的訪問序的在多核下暴露出的問題 全部記憶體讀寫順序的正確性問題,單核亂序執行重新排列無關的指令在多核系統中可能出現問題。也就是程式中 Load Store 的(ISA)順序(馮諾依曼架構下看可以看做記憶體操作請求的順序)和Load Store實際執行完成的順序可能相同、可能不同(這取決於微體系結構的實現),在多核情況下,程式的正確性可能出問題。有各種一致性模型來表達各種程度的相同不同,相應的有軟、硬體機制來確保多核處理器上程式的正確執行。

這裡只具體寫順序一致性(sequential consistency)模型,更弱的一致性模型在學習過相關資料論文後再做補充。順序一致性的概念來源於Lamport 1977年的一篇論文How to Make a Multiprocessor Computer That Correctly Executes Multiprocess Program
這裡寫一下論文中給出的闡述
看一個互斥協議,問題是多核處理器下多程序併發/並行會使得兩個程序都進入臨界區麼?

幾點說明寫在前面:

  • 1,2,3,4,5,6只是標號,數字本身帶有的序和問題沒聯絡
  • 程式裡的讀寫操作都是一條指令的粒度,不是高階語言的一句語句
  • P1, P2指處理器
- P1 - P2
a=0 b=0
1 a=1 4 b=1
2 IF(b==0) THEN 5 IF(a==0) THEN
(臨界區) (臨界區)
3 a=0 6 b=0
ELSE ELSE
{…} {…}

考慮這個例子,如下事件依次發生

  • 1 P1 發出a=1的請求,請求的是記憶體模組1,記憶體模組1此時正忙
  • 2 P1 發出取b的請求,請求的是記憶體模組2,記憶體模組2此時可用,取b的指令執行
  • 4 P2 發出b=1的請求,請求的是記憶體模組2,這個請求會在取b執行完成後執行
  • 5 P2 傳送取a得請求,請求的是記憶體模組1,記憶體模組1此時正忙

在這個例子裡,這4條指令對同一記憶體請求順序是1 ->5 ; 2->4
這4條指令執行完成的順序是什麼呢 2->4;
如果是 2->4;5 -> 1 這兩個處理器會同時進入臨界區
如果是 2->4;1 -> 5 則不會
-> 符號不直接對應happen-before

順序一致性有兩個條件:

  • 每個處理器按程式序發射記憶體請求(1->2;4->5)
  • 所有處理器到單個儲存器模組的請求依照FIFO序服務。請求的發射過程包含進入FIFO佇列。

我理解就是說,不管這多個處理器對同一記憶體的請求順序如何交疊,都可以,但是記憶體必須按照請求到達的順序執行(這裡應該隱含著對同一地址先請求(指令發射)的先到達(指令執行)的假設),這樣保證上面的互斥協議正確。這樣的要求稱為順序一致的要求,是很嚴格的,會對硬體效能造成影響,其實可以放寬,不必嚴格按請求順序執行,但是必須有軟體機制來提供正確的互斥協議的實現,上面的護持互斥協議在弱於順序一致的記憶體模型下是不正確的。

也就是說1,2,4,5的請求可以有C(4,2)=6種交疊方式,每一種都符合順序一致只要每種情況的執行也是按照這個順序

現在來看這句很拗口的話

the result of any execution is the same as if the operations of all the processors were executed in some sequential order, and the operations of each individual processor appear in this sequence in the order specified by its program

似乎這個定義裡要求每個核上不同記憶體地址的請求也要安程式序執行,但是在微體系結構層次,提交時要保持,但是執行時程式序是可以打破的,同一處理器不同地址請求序(亂序發射)和程式序(馮諾依曼ISA序)是否一致,請求序和執行序是否一致,這裡似乎沒有明說。分散式環境中的一致性是關於同一資料的多個副本上要達成全域性一致性,某種角度來講,如果把記憶體的請求發射和到達,類比分散式中對一個副本的寫/讀和向各個副本傳播寫/讀操作,這兩者非常類似 //但是感覺還是沒有理解二者的本質

單核處理器下多程序併發會使得兩個程序都進入臨界區麼?此時表裡的P1,P2代指程序。不會有這個問題,記憶體請求是從同一個核過來,到達順序和服務順序一樣(單核天然是順序一致的),不會有多核中多個請求到達,在執行請求時會涉及排程導致服務順序和到達順序不一致的情況。

如果你考慮一個多核處理器的記憶體體系,就會發現這個問題很複雜,cache以及一致性,buffer,pipeline和記憶體一致性的保證,和分散式的一致性相比,雖然分散式下非同步不可靠網路帶來了很大挑戰,但是現在我覺得處理器的記憶體系統可以說比分散式環境下的一致性問題更加複雜

x86的記憶體一致模型是順序一致的TSO,所以在實現一個正確的互斥鎖的時候也沒有考慮太多,比如沒用memory barrier這種東西就對了

資料一致性

分散式系統為了效能、容錯的需要,資料進行多副本冗餘是一項很基本的技術。資料一致性說的是一份資料有多個副本,在多個副本上的讀寫操作的順序要達成一致,這個一致也有很多不同的強弱要求,產生了眾多的強弱一致性模型,這些模型的術語和記憶體一致性的術語有很大的重疊,可能是歷史上並行體系結構和分散式系統兩個領域是一夥人在搞?

由強到弱的資料一致性模型構成了 資料一致性譜

線性一致性和順序一致性

這兩種都是稱為強一致性

  • 線性一致性和順序一致性都是強一致性
  • 都給客戶端提供單副本的假象
  • Linearizability關乎時間,sequential consistency 關乎程式順序

分散式下強一致是個困難問題,著名的paxos演算法挺複雜的,Raft是2014年出的一個可以看作是改良版的演算法。

線性一致性 Linearizability

  • 表現出單副本的行為
  • 讀操作返回最近(most recent)的寫,和client無關
  • 所有後序讀返回相同值,直到下一次寫,和client無關

最近所有後序: 由時間確定
e.g.
這裡寫圖片描述
這裡寫圖片描述
這裡寫圖片描述

順序一致性

  • 表現出單副本的行為
  • 讀操作返回最近(most recent)的寫,和client無關
  • 所有後序讀返回相同值,直到下一次寫,和client無關

最近所有後序
同一個client的操作由時間決定(程式序);
跨client的操作:不由時間決定,我們可以安排某種序,只要保持程式序。

從系統外的觀察者來看:順序一致性需要提供操作的全域性序,1)工作起來像一個副本,2)來自同一個client的操作順序被保持

e.g.

  • 不違背順序一致
- - - - - -
P1: W(x)a
P2: W(x)b
P3: R(x)b R(x)a
P4: R(x)b R(x)a

這個例子裡面,橫軸代表時間,時間上雖然W(x)a在前,W(x)b在後,但是其序不一定也如此,所以這個例子並不違背分散式環境下的順序一致,也再次說明分散式的順序一致是比記憶體的順序一致更弱的一致

  • 違背順序一致
- - - - - -
P1: W(x)a
P2: W(x)b
P3: R(x)b R(x)a
P4: R(x)a R(x)b
  • 不違背順序一致,違背線性一致
- - - -
P1: W(x)a W(x)b
P2: R(x)a
time ——-> ——-> ——->

記憶體的順序一致是順序一致麼?

記憶體的順序一致性和分散式哪一種強一致性是一樣的呢?是順序一致性麼?因為分散式環境下沒有全域性時間,所以分散式資料順序一致性退化成較弱的一種一致性,而Linearizability和記憶體的順序一致性更接近。

因果一致性
放寬順序一致性的要求,有因果關聯的操作保持順序,併發的(相互沒有因果關聯的)寫操作可能在不同機器上順序不同
因果關係可以由vector-clock捕捉
e.g.

  • 違背順序一致,不違背因果一致
- - - - - - -
P1: W(x)a W(x)c
P2: R(x)a W(x)b
P3: R(x)a R(x)c R(x)b
P4: R(x)a R(x)b R(x)c
  • 違背因果一致
- - - - - -
P1: W(x)a
P2: R(x)a W(x)b
P3: R(x)b R(x)a
P4: R(x)a R(x)b
  • 不違背因果一致
- - - - - -
P1: W(x)a
P2: W(x)b
P3: R(x)b R(x)a
P4: R(x)a R(x)b

最終一致性
某些副本的資料已經修改,而另一些副本的資料還沒來得及修改。當修改可靠地傳播到所有副本,並給予足夠的時間,所有副本的資料都將變成新值,取得一致。

happen-before

理解一致性要理解一個併發系統中的“序”的問題,什麼叫先,什麼叫後。在分散式系統中,這個問題困難是因為沒有完美的全域性同步時鐘,多核系統中是因為多核的微體系結構上的原因。

Lamport在1978年的論文中給出了happen-before的定義,這篇論文非常經典,提出了很多分散式系統中十分重要的概念,此處暫不展開,只談happen-before。據說這篇文章受相對論啟發,瞭解happen-before有助於理解時間、順序。

happen-before 關係

基本假設

  • 假設程序的事件(event)形成一個序列(sequence),單個程序定義為 一組事件的全序(total ordering)
  • 假設程序之間訊息(message)的傳送(send)和接受(receive)是事件

happen-before 是滿足以下條件的最小關係(relation)

  • 如果a,b是同一個程序的事件,a在b前面 ,那麼ab
  • 如果a是傳送訊息程序的傳送事件,b是接收該訊息程序的接受事件,那麼ab
  • 如果ab,bc,那麼ac

定義aa
另外,如果兩個不同的事件a,b,有 ab,ba,就稱a,b是併發的(concurrent)

這樣從數學上看,happen-before就是一個定義在所有事件上偏序關係,反自反,反對稱,傳遞性都有了,偏序關係中存在不可比的情況,所以有些事件並無先後是併發的,如果在加上限制條件 break tie,那麼在這個偏序關係上就可以定義一個全序關係。

程序和事件的定義非常general,事件可以是一個子程式的執行、也可以是一條機器指令的執行。

訊息的傳送和接受在分散式系統中很顯然。在體系結構方面也有類似之處,考慮單核處理器、馮諾依曼架構中指令順序執行,其實這些指令並不需要嚴格一條接著一條指令,所以會有亂序執行,在亂序執行裡,如果把同一記憶體地址的寫讀看做訊息傳送接收,其實亂序執行的寫後讀依賴就和happen-before序十分類似。

引用

[1].Gharachorloo, Kourosh, et al. Memory consistency and event ordering in scalable shared-memory multiprocessors. Vol. 18. No. 2SI. ACM, 1990.
[2].Lamport, Leslie. “Time, clocks, and the ordering of events in a distributed system.” Communications of the ACM 21.7 (1978): 558-565.
[3]Lamport, Leslie. “How to make a multiprocessor computer that correctly executes multiprocess progranm.” IEEE transactions on computers 9 (1979): 690-691.
[4].Tanenbaum, Andrew S., and Maarten Van Steen. Distributed systems: principles and paradigms. Prentice-Hall, 2007.
[5].https://homes.cs.washington.edu/~bornholt/post/memory-models.html
[6].https://cse.buffalo.edu/~stevko/courses/cse486/spring15/lectures/23-consistency2.pdf