Processing read-only queries more efficiently
前言:
raft 的論文也看了很多遍, 其中輕描淡寫的說了leased-base的讀。 etcd的raft源碼實現(xiàn)也看了幾次, 有幾個點特別不理解, 直到去看readme.md的時候,才注意到這個https://ramcloud.stanford.edu/~ongaro/thesis.pdf(哎, 不讀文檔害死人呀,以后看什么一定要先讀文檔), 這不是論文, 更像一本書, 涉及到了raft方方面面.
整體步驟
如果leader還沒有提交entry, 他必須等待直到有entry提交. leader完整性規(guī)則保證了該leader擁有提交過的entry, 但是在當他被選擇為leader的時候, 他并不知道那些那些是已經(jīng)提交的entry, 所以他會在成為leader之后, 首先提交一個空entry作為自己item的開始, 一旦該空entry提及提交成功,該leader的commmited idx 至少和其他server上的commit idx一樣大(也就是說:剛成為leader的時候, leader的commitidx 不一定是最大的)
leader 把最新的commit idx保存在本地變量readindex里
leader必須保證自己不被其他new leader替代(并且自己還沒有意識到自己被替代)。 leader向其他server發(fā)送一輪hb,并且檢驗自己能不能被過半server回復, 一旦被集群過半server回復,該leader就能至少保證在他發(fā)送hb的那一刻,集群中沒有其他leader, 因此,自己本地保存的readindex仍然是最大.
leader等state machine至少applied和readindex一樣大, 這種情況下, 就能滿足強一致。
最后,leader把用戶查詢賦給狀態(tài)機, 并且給客戶端回復。
alternative(一)
為了提高集群的吞吐量,分擔leader的壓力, 可以讓follower承擔讀的請求。 但若沒有一些措施,可能讀到過期數(shù)據(jù),比如L:分區(qū)follower可能一段時間內并沒有接受到任何新的entry, 甚至該follower確實接受到了leader的hb, 但是該leader其實并不是當前集群的leader, 只是該leader自己還沒意識到自己已經(jīng)被取代而已。 為了保證安全的讀, follower需要向leader(該leader將會執(zhí)行上面的1-3 step)請求當前最新的readindex, 然后該follower在自己本機器執(zhí)行以上的4-5 step。
alternative(二)

一旦leader的hb被集群的大多數(shù)server確定, 該leader就能假設沒有其他任何server在最小election timeout能成為leader, 這樣leader就可以延長自己的lease(這個spanner的長leader有點相似)。因此leader在這段時間內就可以回復client的讀請求而不需要和其他server交互。