fabric 1.1中共识算法只有两种,一种是 kafka,一种是solo,solo是单个机器的,很少用于开发环境中。所以有段时间一直在困惑: 到底kafka能不能作为一种共识算法?
有疑惑的最好办法就是去看阅读源码,理清实现机制。于是我根据fabric 1.1的源码整理了下面的内容。希望通过具体的实现来回答这个问题。
Kafka共识的组成部分
fabric 1.1中的共识包括三个部分:
1. Chain。 这里的chain跟我们说的区块链中的链不是同一个概念,这里的Chain是在排序中,注入消息的一种方法。是一个接口。为了在实现上更方便,Chain负责排序消息,通过blockcutter把消息分块,之后发送消息,最后写入账本。Chain支持两种处理流程:
消息排序后放入数据流中,然后把数据流切成块,提交块到账本。solo和kafka是基于这种方式
把消息新切成块,排序块,之后把块提交。sbft用的是这种方式。
2. Consenter。可以理解为kafka的broker。包括了:broker的配置,重试机制,tls配置以及kafka的版本信息。Consenter通过生成Chain来定义整个排序机制。
3. ConsenterSupport。对Consenter操作的一个封装。包括了如:blockCutter,创建下一个block,把block写入账本,写配置信息块到账本等操作。
Kafka共识的流程
kafka的运行过程如下:
1. 会通过Chain Start方法启动Chain,这个方法主要是首先初始化 生成者,消费者和kafka中的Connect。之后等待消费者队列中的消息。
2. 有消息过来要求排序
先序列化这个消息中带签名的payload
把序列化后的数据封装成一个kafka消息格式的数据包
对kafkfa消息格式的数据包再次序列化
生成要发送的生产者数据包,这个包是指定的channel下的生成者的包
生产者(异步)发送这个消息
3. 消费者从生产者队列中获取到消息后,这个时候,Chain的Start方法拿到了要处理的消费者数据。
反序化消费者消息
根据消息的类型进行处理,消息有KafkaMessage_Connect,KafkaMessage_TimeToCut,KafkaMessage_Regular消息。
4. 处理KafkaMessage_Regular消息
根据配置序列号,查看当前是否还有未处理的消息,如果有,根据当前是系统管道还是应用管道,进行消息的有效性验证。
把这个消息根据 2 的处理步骤进行排序
所有消息都已经重新验证了,这个时候需要进行提交块操作
5. 提交块操作
分包操作。把当前消息的大小和还未处理,处于pending的消息包根据配置的块大小进行分包
把第一个包封装成块
使用blockwriter 把块,连同签名信息一起写入账本
写在最后
上面是从fabric角度来分析,可以看出kafka在fabric中起的很大一部分作用都是在保证数据的队列化和顺序性。而从kafka角度来说,kafka 在架构层面上给出了如下的保证:
由生产者发送到一个指定topic分区中是有序的。比如,记录M1和M2都是同一个生产者发送,M1比M2先发送,那么M1在日志中的偏移值就比M2更小(在M2的前面)
消费者实照存储在日志中的顺序查看记录。类似于队列的先进先出
对于一个topic的N个备份,可以容忍n-1的服务失败而不会导致数据丢失
从上面可以看出:分区,有序,容错是kafka的三个特性。这里的有序是说在一个分区中的消息被某一个消费者消费时,消息是有序的。换句话说,也就是说对于一个消费者来说,在一个分区内的所有消息是有序的。但是不保证不同分区的数据是有序的。
也正由于这三个特性,可以使用kafka来作为一种“简单粗暴”的共识算法。这里再次强调下共识的定义,所谓的共识是指:在一个时间段内对事物的前后顺序达成共识的一种算法。
kafka的分区有序就保证了kafka可以作为一种共识算法。从工程角度,这种共识算法的安全性较低。但是由于Fabric引入了比较强的身份管理机制,在一定程度上加强了整个系统的安全等级。
赶快来分享关注吖
蜗牛讲技术,满满的都是干货,你值得关注。
领取专属 10元无门槛券
私享最新 技术干货