目錄(?)[-]緩存
- 背景和介紹
- 租約屬性和管理
- 互聯網的一致性問題
- 卷租約
- 租約的其餘應用
- 到底租約是什麼
背景和介紹
緩存是計算機裏普遍使用的一種技術,對下降讀取延遲、網絡流量和服務器負載都很是有效,但也帶來了一致性(Consistency)的問題。所謂一致就是客戶端總能讀到最新的數據,使用緩存後有可能服務器端的數據已經被修改,但客戶端仍然從緩存中讀取陳舊的數據。爲了保證一致性,有兩種常見的解決辦法,第一種是輪詢(Polling),即每次讀取數據時都先詢問服務器數據是否是最新的,若是不是就從服務器傳輸新數據,這種方法須要每次讀取數據時都與服務器通訊。另外一種方法就是回調(Callback)或者無效化(Invalidation),就是由服務器記住有哪些客戶端讀取了數據,對數據作修改時首先通知全部這些客戶端數據已經失效,這種方法的問題在於服務器須要記住全部讀取過數據的客戶端,這是很大的負擔,更嚴重的是,一旦有客戶端聯繫不上或者丟失了客戶端的信息,修改操做就沒法繼續。安全
1989年斯坦福大學的Cary G. Gray和David R. Cheriton提出了利用
租約來維護緩存一致性的方法。所謂租約,其實就是一個合同,即服務器給予客戶端在
必定期限內能夠
控制修改操做的 權力。若是服務器要修改數據,首先要徵求擁有這塊數據的租約的客戶端的贊成,以後才能夠修改。客戶端從服務器讀取數據時每每就同時獲取租約,在租約期限 內,若是沒有收到服務器的修改請求,就能夠保證當前緩存中的內容就是最新的。若是在租約期限內收到了修改數據的請求而且贊成了,就須要清空緩存。在租約過 期之後,客戶端若是還要從緩存讀取數據,就必須從新獲取租約,咱們稱這個操做爲「
續約」。
在租約期限內,客戶端能夠保證其緩存中的數據是最新的。同時,租約能夠容忍各類非拜占庭式失效(機器崩潰、網絡分割等)。若是客戶端崩潰或者網絡中斷,服務器只須要等待其租約過時就能夠進行修改操做。若是服務器出錯丟失了全部客戶端的信息,它只須要知道租約的最長期限,就能夠在這個期限以後安全的修改數據。與回調方式相比,服務器只需記住還擁有租約的客戶端便可。服務器
租約與帶期限的鎖很是類似,但更加靈活,由於租約還提供了「尋求贊成」的機制(我以爲能夠稱爲「帶期限可妥協的鎖」)。服務器還能夠實現多種租約,好比「寫租約」和「讀租約」,並保證一個時間段內只有一個寫租約或者多個讀租約,這就至關因而單寫者多讀者的鎖協議。
因 爲租約是基於時間的,所以其有效性須要系統時間來保證。若是服務器的時鐘快而客戶端時鐘慢,那麼有可能服務器認爲一個租約已通過期而客戶端仍然認爲其有 效,就可能致使錯誤。對這種狀況就必須經過時鐘同步協議來解決了,不過這種狀況不多見。通常狀況下,咱們能夠認爲一個分佈式系統的時間是同步在一個很小的 時間差e以內,只需把這個e考慮到租約期限內便可。
租約屬性和管理
租約的屬性和管理有多種選擇,首先要考慮的就是租約期限的長短。網絡
通常狀況下,應當選擇較短的租約期限。與長租約相比,短租約有三個優勢。首先,在失效狀況下修改操做每每須要等待租約過時,所以短租約就意味着更短的
失效延遲。其次,就算一個客戶端已經再也不須要讀取數據,但在其租約過時前,任何的修改操做仍然須要徵求它的贊成,這種狀況叫作「
假共享」,顯然租約期限越長,這個問題就越嚴重。最後,短租約也使得服務器要維護的客戶端信息更少。然而短租約也意味着更大的
續約開銷, 所以對於要反覆讀取卻不多修改的數據,長租約會更有效。所以,對租約期的選擇要權衡失效延遲、假共享開銷和續約開銷等多個因素,服務器能夠根據數據訪問特 性和客戶端的性質靈活設置期限。事實上,若是咱們把租約期限設爲零,就至關與輪詢,此時修改操做隨時能夠進行,而讀取數據老是要聯繫服務器。若是把租約期 限設爲無限長,就至關於回調。
除了期限的選擇,還有不少管理選項。對客戶端來講,能夠選擇 是否續約、什麼時候續約以及是否贊成修改等。好比爲了減小讀取延遲,客戶端能夠在租約過時前就續約,不過這樣可能加劇服務器的負擔。對服務器來講,能夠選擇是 否發放租約、租約覆蓋粒度以及對如何進行修改操做。好比在收到修改請求後,服務器能夠不徵求客戶端贊成,而是簡單的等待全部租約過時(等待時再也不發放新租 約以免無限期的延遲)。對於「
安裝文件」,也就是修改極少的文件(好比頭文件、庫文件),服務器能夠用一個租約來覆蓋一批文件,同時按期廣播續約通知來節省開銷,若是須要修改數據,就中止廣播並等待租約過時便可。
互聯網的一致性問題
在互聯網環境下,一致性問題更加複雜,由於網絡延遲比局域網要大的多,客戶端失效和網絡分割都很常見。所以不少狀況下,咱們都只保證緩存的弱一致性,也就是不保證客戶端總能讀到最新的數據,只是儘可能保證其讀到的數據還不是很是滯後。相應的,咱們把前面使用的一致性稱爲強一致性。目前最經常使用的保證弱一致性的方法就是生存期(TTL), 即讀取數據的時候會指定生存期,在生存期內客戶端直接從緩存中讀取數據,以後必須與服務器通訊驗證緩存有效性或者獲取最新數據。很顯然,咱們能夠給變化較 多的數據分配較短的生存期來儘可能減小客戶端讀取過時數據的概率,而給變化較少的數據分配較長的生存期來減小讀取延遲和服務器負載。分佈式
1992年CMU的Vincent Gate在Alex項目中實現了可變生存期(Adaptive TTL),這個技術基於這樣的觀察,就是新數據比舊數據更容易被修改。 在Alex中採用了更新閾值(update threshold)的概念,把生存期設定爲其緩存時間的一個百分比。假設一個剛剛向服務器驗證過的數據已經在緩存中存在了10個鐘頭,其更新閾值爲 20%,那麼其生存期就是2個鐘頭。採用可變生存期技術並不能減小網絡流量,可是能夠比普通的生存期技術減小服務器負荷。工具
雖然弱一致性模型已經知足咱們平常瀏覽網頁的需求,但仍是有一些應用會要求強一致性。局域網狀況下的方法很難直接擴展到互聯網環境。輪詢方法的讀取延遲太 大。回調方法不但記錄全部客戶會使得服務器難以承受,常常出現的網絡分割更使得修改操做沒法繼續。短租約致使的網絡通訊和服務器負荷都太大,並且若是租約 期限小於網絡延遲的話,那麼除了增長服務器負荷外沒有任何做用。長租約又相應的使得失效延遲和假共享的問題更加嚴重,並且服務器要記錄大量客戶端數據。既 然有可變生存期,那天然的也有了
可變租約(variable leases)的想法。1998年威斯康辛大學麥迪遜分校的Pei Cao和Chengjue Liu就提出了一種叫
two-tier的方案,就是區分只是偶然讀取數據的客戶端和真正須要強一致性的客戶端,只對後者才發放租約(由客戶端顯示的提出請求)。更進一步的,他們分析瞭如何根據不一樣狀況調整租約屬性,例如數據修改減小時增長租約期限,存儲空間不夠時則縮短租約期限甚至要求客戶端放棄租約。
卷租約
在1999年的論文中,德克薩斯大學奧斯汀分校的Jian Yin等提出了互聯網環境下保證強一致性的卷租約機制。
所謂
卷租約(volume leases), 與上面提到的針對「安裝文件」的租約有點相似,即由一個租約會覆蓋多個相關文件,其期限較短,通常是數十秒,通常要在過時前續約。卷租約由於期限短,續約 操做就比較頻繁,但用戶每每會同時讀取一個卷下的多個文件,所以這個開銷分攤到了多個文件上,依然是能夠接受的。若是光采用卷租約,會帶來很是嚴重的假共 享問題,由於擁有卷租約的客戶端各自關注的數據可能很不相同。所以服務器還另外提供了
對象租約(object leases),就是隻覆蓋一個文件的普通租約,期限通常較長,能夠是數小時甚至數天,以取得較小的續約開銷。客戶端要保證緩存有效,就必須
同時擁有對象租約和卷租約。修改操做須要徵求同時擁有卷租約和對象租約的客戶端的贊成,若是出現客戶端機器失效或者網絡分割的狀況,最多隻需等待卷租約過時,就能夠安全的修改數據。
一旦卷租約過時,服務器就認爲相應的對象租約也都過時,客戶端從新獲取卷租約時,會檢查相應的對象租約的有效性,若是數據沒有修改就續約,不然清空緩存。事實上,卷租約和對象租約相似於
心跳和回調,前者主要用來肯定客戶端的狀態,後者用來定位對數據有興趣的客戶端。經過兩種租約的結合,能夠較好的平衡失效延遲和通訊開銷。實驗數據代表,要取得一樣的
失效延遲時間,卷租約機制能夠比普通租約機制減小三成到四成的消息數。粗一想或許還會奇怪,加了一個租約怎麼可以減小通訊呢?這是由於要取得一樣的失效延遲,普通租約就必須把租約期限設定在延遲期限內(好比20秒),而若是使用卷租約,只需把卷租約的期限設定在延遲期限內,而對象租約的時間能夠設的很長。由於卷租約的通訊開銷有好幾個對象分攤,而對象租約的開銷由於期限很長事實上很是小,因此總的開銷會小於只使用普通租約的狀況。
租約的其餘應用
以上咱們只討論瞭如何用租約來維護緩存一致性,其實租約的應用範圍很是普遍。
在 Frangipani分佈式文件系統中實現了一個分佈式的鎖,客戶端在獲取鎖以前,首先要獲取一個租約,而且必須在租約過時前續約。這個客戶端得到的鎖都 與這個租約相關聯,若是租約過時了,鎖服務器就會自動的釋放這些鎖。這裏的租約就是對鎖有效性的一個保證,經過維護客戶端租約,避免了爲每一個鎖維護期限的 開銷。這裏的租約就至關於心跳。
在gfs中,每一個文件塊都有多個副本分佈在多個chunkserver上,在 並行追加時必須有一個全局統一的追加順序。固然這個順序能夠由master來肯定,可是這樣會大大增長master的負荷。另外一種方法能夠由多個 chunkserver經過一致性協議(好比Paxos)來達成一個一致,但這樣開銷太大。gfs使用了租約機制,就是對每一個文件塊,由master向一 個chunkserver發放租約,在租約期限內就由它來負責並行追加操做的順序。chunkserver正常運行時能夠一直續約,若是出現了機器失效或 者網絡分割的狀況,master就在租約過時之後把租約交給另一個chunkserver。在某些狀況下,master也會聯繫擁有租約的 chunkserver,請它們提早釋放租約。
不少狀況下,系統中已經有一個保證一致性的中心服務,如某個
單一服務器或者是
實現了Paxos協議的一組服務器,但若是全部的功能都須要經過這個中心服務,很容易形成性能瓶頸。爲了提升效率和擴展性,能夠經過租約把
一致性擴展到更多服務上。事實上用租約來維護緩存一致性也是至關於把服務器上的數據一致性擴展到了客戶端。
到底租約是什麼?
在不少時候,租約的定義彷佛很模糊,有的時候租約相似心跳,有的時候又相似於鎖。到底租約的本質是什麼呢?
回到租約最原始的定義:租約就是在
必定期限內給予持有者
特定權力的 協議。我以爲這裏的期限就是租約的根本特性,正是這一特性使得租約能夠容忍機器失效和網絡分割。在期限以內,租約其實就是服務器和客戶端之間的協議,而這 個協議的內容能夠五花八門。若是協議內容是服務器確認客戶端還存活,那麼這個租約的功能就至關於心跳;若是協議內容是服務器保證內容不會被修改,那麼這個 租約就至關於讀鎖;若是協議內容是服務器保證內容只能被這個客戶端修改,那麼這個租約就至關於寫鎖。租約這種靈活性和容錯性,使其成爲了維護分佈式系統一致性的有效工具。