A Kafka-based Ordering Service for Fabric这篇文章是HyperLedger Fabric orderer的kafka设计文档,详细介绍orderer应用kafka的设计思想演进过程,从基本点逐步深入,由问题到解决方案,值得阅读。这里列举学习过程中的笔记。
- Solution 0(S0) : 单个tx(transaction)构成block。
- Problem 1(P1) : 单个block的size很小,当网络有大量tx时会产生大量的block。而OSN(ordering service node)需要对block进行打包,签名,client需要解包,验证签名。overhead太大,效率太低。
- S1 :多个tx打包成一个block。
- P2 : 但是需要缓存到指定数量的tx,如果网络tx太少,可能需要等很长时间才产生一个block,tx需要等待很久才得以确认。
- S2 : 增加时钟,如果指定时间内没有达到数量要求,时钟到时切分block。
- P3 : 各个OSN时钟不同步,可能导致block间切分的位置差异。
- S3 : OSN加入TTC-X(Time to Cut block-X),时钟到时发送该message到kafka,各个OSN收到改消息后切分block。
-
P4 : Deliver服务需要读取指定block。
-
S4a : block头部加上metadata,从block X-1可以知道block X的开始的kafka offset。OSN从该offset开始重读kafka,replay重新构建block。
-
P4a : 如果client缺少block X-1,就无法得知block X的开始offset。
-
S4b : OSN保存table,block number <-> offset number。
-
P5 : 读取block X需要从kafka重读消息,重新打包,签名。
-
P6 : 网络中存在重复的消息,例如re-order的消息
-
S5a : kafka partition 0 保存tx,partition 1保存打包后的block,简历partition 1的table,block number <-> offset number。如果需要读取blcok X,则查表,从partition 1读取相应offset的block。但是,需要每次查表,而且无法解决P6。partiton 1中的每个block会被每个OSN都发送一次,大量重复的block。
-
S6a :OSN发送前判断partition 1中是否有重复的block number,如果已存在则不在发送。但是所有的OSN之间无法做到严格同步,可能有多个block副本(来自不同的OSN的同一个block同时发送)处在in-flight状态,仍然没有解决重复的问题。
-
S6b : 选举OSN leader,只有leader才能发送到partition 1。但是,如果就leader发送block X后crash,选举的新leader重发block X,导致重复(旧leader发的block X处在in flight状态)。无法使得block number = offset number,仍然需要存表查表。
-
S6c : 使用kafka的log压缩特性,保留key相同(可以使用block number X作为key)只有一个offset,删除冗余的。但是,OSN要保留table,block number <-> offset number,并且log压缩后删除旧值,表里如果更新不及时会读取到旧offset(实际上已经被删除)。而且压缩后的block与offset间是乱序的。
-
S5b,S6d : OSN把block存储本地账本。无需使用table,从tx构建账本链可以保证顺序性,而且deliver也可以复用orderer broadcast代码。
The OSN will need to keep track of the last offset number it read though, just so that it knows where to seek to when consuming from Kafka upon reconnection.
A downside of serving Deliver requests from the local ledger could be that it would be slower than serving them straight from Kafka. But we never serve straight from Kafka; there’s always some processing happening on the OSNs. (其他的方案在OSN也会引入开销)
Overall an ordering service that uses a single partition (per chain) for incoming client transactions and TTC-X messages (as shown in Solution 3), and which stores the resulting blocks in a local ledger (again, per chain) strikes a nice balance between performance and complexity.