当前只读状态:是_Raft 只读(read-only)优化
Raft 只讀操作優化
為什么需要優化只讀操作
raft是一個為分布式集群達成一致性的協議。對于集群需要保證一致性的數據,每次一操作其實都要確認此操作是否在集群中達成了一致。從是否會改變數據的角度,操作就分兩個只讀操作與寫操作。只讀操作顧名思義就是不會對數據做任何的改動。寫操作包含了增刪改等需要修改數據的操作,通俗說就是這次操作處理完后,數據有可能跟操作前不一樣。
正是因為只讀操作不對數據進行修改,所以raft可以優化只讀操作。
如何優化
優化只讀操作的核心就是保證此時請求到該集群leader確實是能夠向集群中法定人數的節點commit log成功。否則用戶可能會讀到陳舊的數據信息,無法保證線性一致。
用論文[1]中的話說就是
圍繞這一核心目標,raft的作者在他PhD論文[2]中提到了兩種優化的方法。
一. 使用readIndex
readIndex這種方法,雖然避免不了網絡請求的開銷,但是減少了raft的log,也避免了讀操作落磁盤的開銷。
此方法實現以后,用戶可以向follower請求只讀操作,以保證負載均衡,增強系統讀的吞吐率。這里需要注意,follower的數據可能落后當前leader很多,或者網絡分區后跟隨了錯誤的leader。所以,leader必須提供一個接口以返回當前的readIndex。follower請求這個接口,拿到當前的readIndex,然后leader執行1-2,被請求的follower在自己的狀態機中執行3-4步。
但是我覺得這種負載均衡的方法并不是很巧妙。第一,增加了系統復雜度,第二,有了讀放大,多了請求leader的網絡操作。第三,這種方法并不能保證用戶的寫操作負載均衡。
現在系統一般使用對集群分組,對數據分片的方法來做負載均衡。這樣既不會增加raft協議的復雜度,同時對讀寫操作都做了負載均衡。
二. 使用時鐘(lease read)
方法二就是使用租期(lease)時間。在租期未過期時,在不進行任何網絡請求下,保證用戶只讀請求。
首先還是要記錄leader的commitIndex作為readIndex。但是不會專門發起一次心跳(一.中的2)。在租期不過期的情況下,保證leader的狀態機至少執行到readIndex,給用戶返回只讀操作。
租期其實就是選舉的時間差。當leader收到法定人數的心跳后,那么在raft系統設置超時選舉(election timeout)這段時間內,自己的數據肯定是正確的。因為在這段時間里,肯定不會有新的leader產生。
這里使用論文[2]中的一副圖來說明情況
因為要考慮到進程調度,垃圾回收,虛擬機遷移,時鐘頻率不同等種種原因,需要設置一個bound(bound是大于1的)。其中start為leader向集群follower發送心跳的時間點。那么租期為:
當收到法定人數的心跳點后,延長一個租期(lease_time)。雖然使用lease這種方法減少了時鐘開銷,但是如果這里的bound設置與現實不符,或者出現時鐘嚴重漂移等問題。仍會導致舊leader可能給客戶返回陳舊數據。
作者在文章[2]中最后又提出了一種方法來避免這種情況。
服務器在返回apply日志時,把這個日志對應的index也一并返回給用戶,用戶把這個日志的index保存起來,客戶將跟蹤與他們所看到的結果相對應的最新索引,并在每次請求時將這些信息提供給服務端。如果服務端收到的客戶端請求的index大于服務器最新的applied的日志的index,則服務器不會為該請求提供服務。
不過這個描述我沒太看懂。。因為要保證所有客戶端都能知道最新的applied 的index,感覺這種情況才能避免。
TiKV中提供了一種解決方案[3],有點像一和二的結合體。不同的是在每次寫操作時,進行租期的續約。如果長時間沒有寫操作,租期過期時,使用方法一(readIndex)進行。
[1] Ongaro D, Ousterhout J. In search of an understandable consensus algorithm (extended version)[J]. 2013.
[2] Ongaro D. Consensus: Bridging theory and practice[D]. Stanford University, 2014.
[3] https://pingcap.com/blog-cn/lease-read/
總結
以上是生活随笔為你收集整理的当前只读状态:是_Raft 只读(read-only)优化的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: angular 字符串转换成数字_一文看
- 下一篇: python画图颜色表示大小变化_pyt