分布式系統里排他性的資源訪問方式,叫作分布式互斥,而這種被互斥訪問的共享資源就叫作臨界資源。
一.集中式算法
引入一個協調者程序便得到一個分布式互斥算法。每個程序在需要訪問臨界資源時,先給協調者發送一個請求。如果當前沒有程序使用這個資源,協調者直接授權請求程序訪問;否則,按照先來后到的順序為請求程序排隊。如果有程序使用完資源,則通知協調者,協調者從請求程序的隊列里取出排在最前面的請求,並給它發送授權消息。拿到授權消息的程序,可以直接去訪問臨界資源。
這個互斥算法就是集中式算法,也可以叫做中央服務器算法。之所以這么稱呼,是因為協調者代表着集中程序或中央服務器。
集中式算法的優點在於直觀、簡單、信息交互量少、易於實現,並且所有程序只需和協調者通信,程序之間無需通信。
缺點在於一方面,協調者會成為系統的性能瓶頸。想象一下,如果有 100 個程序要訪問臨界資源,那么協調者要處理 100*3=300 條消息。(
向協調者發送請求授權信息,1 次消息交互;協調者向程序發放授權信息,1 次消息交互;程序使用完臨界資源后,向協調者發送釋放授權,1 次消息交互。共三條信息
)也就是說,協調者處理的消息數量會隨着需要訪問臨界資源的程序數量線性增加。另一方面,容易引發單點故障問題。協調者故障,會導致所有的程序均無法訪問臨界資源,導致整個系統不可用。
二.分布式算法
當一個程序要訪問臨界資源時,先向系統中的其他程序發送一條請求消息,在接收到所有程序返回的同意消息后,才可以訪問臨界資源。其中,請求消息需要包含所請求的資源、請求者的 ID,以及發起請求的時間。
比如程序 1、2、3 需要訪問共享資源 A。在時間戳為 8 的時刻,程序 1 想要使用資源 A,於是向程序 2 和 3 發起使用資源 A 的申請,希望得到它們的同意。在時間戳為 12 的時刻,程序 3 想要使用資源 A,於是向程序 1 和 2 發起訪問資源 A 的請求。此時程序 2 暫時不訪問資源 A,因此同意了程序 1 和 3 的資源訪問請求。對於程序 3 來說,由於程序 1 提出請求的時間更早,因此同意程序 1 先使用資源,並等待程序 1 返回同意消息。程序 1 接收到其他所有程序的同意消息之后,開始使用資源 A。當程序 1 使用完資源 A 后,釋放使用權限,向請求隊列中需要使用資源 A 的程序 3 發送同意使用資源的消息,並將程序 3 從請求隊列中刪除。此時,程序 3 收到了其他所有程序的同意消息,獲得了使用資源 A 的權限。
一個程序完成一次臨界資源的訪問,需要進行如下的信息交互:
- 向其他 n-1 個程序發送訪問臨界資源的請求,總共需要 n-1 次消息交互;
- 需要接收到其他 n-1 個程序回復的同意消息,方可訪問資源,總共需要 n-1 次消息交互。
所以一個程序要成功訪問臨界資源,至少需要 2*(n-1) 次消息交互。假設,現在系統中的 n 個程序都要訪問臨界資源,則會同時產生 2n(n-1) 條消息。總結來說,在大型系統中使用分布式算法,消息數量會隨着需要訪問臨界資源的程序數量呈指數級增加,容易導致高昂的資源使用成本。
這種算法的缺點是
- 當系統內需要訪問臨界資源的程序增多時,容易產生“信令風暴”,也就是程序收到的請求完全超過了自己的處理能力,而導致自己正常的業務無法開展。
- 一旦某一程序發生故障,無法發送同意消息,那么其他程序均處在等待回復的狀態中,使得整個系統處於停滯狀態,導致整個系統不可用。所以,相對於集中式算法的協調者故障,分布式算法的可用性更低。
針對可用性低的一種改進辦法是,如果檢測到一個程序故障,則直接忽略這個程序,無需再等待它的同意消息。因此,分布式算法適合節點數目少且變動不頻繁的系統,且由於每個程序均需通信交互,因此適合 P2P 結構的系統。比如,運行在局域網中的分布式文件系統,具有 P2P 結構的系統等。
在Hadoop 中,其中的分布式文件系統 HDFS 的文件修改就是一個典型的應用分布式算法的場景。
處於同一個局域網內的計算機 1、2、3 中都有同一份文件的備份信息,且它們可以相互通信。這個共享文件,就是臨界資源。當計算機 1 想要修改共享的文件時,需要進行如下操作:
- 計算機 1 向計算機 2、3 發送文件修改請求;
- 計算機 2、3 發現自己不需要使用資源,因此同意計算機 1 的請求;
- 計算機 1 收到其他所有計算機的同意消息后,開始修改該文件;
- 計算機 1 修改完成后,向計算機 2、3 發送文件修改完成的消息,並發送修改后的文件數據;
- 計算機 2 和 3 收到計算機 1 的新文件數據后,更新本地的備份文件。
三.令牌環算法
主要思想是所有程序構成一個環結構,令牌按照順時針(或逆時針)方向在程序之間傳遞,收到令牌的程序有權訪問臨界資源,訪問完成后將令牌傳送到下一個程序;若該程序不需要訪問臨界資源,則直接把令牌傳送給下一個程序。因為在使用臨界資源前,不需要像分布式算法那樣挨個征求其他程序的意見了,所以相對而言,在令牌環算法里單個程序具有更高的通信效率。同時,在一個周期內,每個程序都能訪問到臨界資源,因此令牌環算法的公平性很好。
但是,不管環中的程序是否想要訪問資源,都需要接收並傳遞令牌,所以也會帶來一些無效通信。假設系統中有 100 個程序,那么程序 1 訪問完資源后,即使其它 99 個程序不需要訪問,也必須要等令牌在其他 99 個程序傳遞完后,才能重新訪問資源,這就降低了系統的實時性。
優點是所有的程序輪流通信並傳輸數據,從而消除了多個程序對資源的爭奪,使得每個程序都能接收到其他程序的信息,降低了碰撞導致的丟包率,保證了網絡通信的穩定性,提高了多個程序之間的協作效率。
令牌環算法是一種更加公平的算法,通常會與通信令牌結合,從而取得很好的效果。特別是當系統支持廣播或組播通信模式時,該算法更加高效、可行。
對於集中式和分布式算法都存在的單點故障問題,在令牌環中,若某一個程序出現故障,則直接將令牌傳遞給故障程序的下一個程序,從而很好地解決單點故障問題,提高系統的健壯性,帶來更好的可用性。但這就要求每個程序都要記住環中的參與者信息,這樣才能知道在跳過一個參與者后令牌應該傳遞給誰。
令牌環算法的公平性高,在改進單點故障后,穩定性也很高,適用於系統規模較小,並且系統中每個程序使用臨界資源的頻率高且使用時間比較短的場景。
上面提到的集中式、分布式和令牌環 3 個互斥算法,都不適用於規模過大、節點數量過多的系統。而最近流行的互斥算法是兩層結構的分布式令牌環算法,把整個廣域網系統中的節點組織成兩層結構,可以用於節點數量較多的系統,或者是廣域網系統。廣域網由多個局域網組成,因此在該算法中,局域網是較低的層次,廣域網是較高的層次。每個局域網中包含若干個局部進程和一個協調進程。局部進程在邏輯上組成一個環形結構,在每個環形結構上有一個局部令牌 T 在局部進程間傳遞。局域網與局域網之間通過各自的協調進程進行通信,這些協調進程同樣組成一個環結構,這個環就是廣域網中的全局環。在這個全局環上,有一個全局令牌在多個協調進程間傳遞。