在 corfu 模型上的幾點擴展

前文提要

CORFU: A Shared Log Design for Flash Clusters

zhuanlan.zhihu.com/p/32

Corfu要求連續的offset

擴展1:減少replication的數量

corfu的要求是chain replication。好處是讀取比較快,只要讀尾部。缺點是寫入比較慢,需要按順序寫入所有的chain block。多數派的讀寫是可以的:CorfuDB/CorfuDB

複製不一定要串列,也可以並行。多數派的定義參考flexible paxos。

擴展2:不連續offset

因為corfu的假設是存儲是沒有邏輯的flash unit。所以只能用連續的offset來fill 沒一個hole的junk。如果承載的存儲是有邏輯的服務,可以只寫一個max offset,就可以把小於這個offset的之前的位置都標記為junk了。類似與paxos的proposal number。

擴展3:基於邏輯時間的租約

有了log的offset,就是有了邏輯時間。有了時間就可以有租約。所謂租約就是提前一次性獲得將來n次寫入所需要的讀鎖。比如之前是要獲得offset5這個位置的讀鎖,把offset5標記為當前的max offset。那麼加上租約就是可以是把105設為max offset,從5到105這100個位置就都被我佔了。

擴展4:集群變更

集群變更消息作為log的一條寫入到log里。這樣所有的寫入者都會發現過去的歷史上發生了集群變更,自然就follow到新的集群設置里了。

擴展5:非獨佔寫入

發現歷史上有空洞。一種辦法是非協作的,就是把別人正在的寫的offset標記為作廢。另外一種是協作式的,註冊一個回調,等offset寫如了通知我(比如long polling)。協作式的寫入聽起來沒有什麼用,因為一個變數的版本應該是連續遞增的。當有人在寫版本4,版本5必須基於版本4嘛。既然你沒有辦法提前做什麼,幹嘛要等,讓一個人(leader)獨佔來寫就好了。

這個假設未必成立。因為單值變數是這樣的。但是如果這個變數是一個多key的變數,假設read key1/write key1,和read key2/write key2,這兩個read/write set並不衝突的。這樣就可以把自己的提交拆成寫入read/write set和commit兩個過程。另外還可以speculate(投機),猜還沒有寫入的空洞不會影響我,提前算。如果最後發現猜錯了,就放棄好了。

對於單key來說,基於租約實現單leader串列寫入,效率最高。對於read/write set的commit(類似hyperledger的order service)來說,非獨佔寫入可以提高並發。

擴展6:歷史是有用的

corfu保存了一個變數的所有變更歷史。這個歷史本身除了控制並發,本身也有業務上的價值。且不說有一些業務需求需要讀歷史版本。就是RPC的基石,冪等性也要求一個command產生的副作用只有一次。這個可以通過暴露歷史版本,查看歷史版本上是否有這個command來實現。

把corfu的模型改吧改吧,可以變成一個很有用的通用 shared log。

推薦閱讀:

Indexed Shared Log

TAG:Paxos | Raft | 数据库 |