在 corfu 模型上的幾點擴展
前文提要
CORFU: A Shared Log Design for Flash Clusters
https://zhuanlan.zhihu.com/p/32091622
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。
推薦閱讀: