HyperLedger - 序列3 - 分布式一致性理论与Order Service解析

从比特币,到以太坊,再到HyperLedger,我们一直没有专门来讲1个问题,也就是分布式一致性。

分布式一致性,也就是通常所说的共识算法,作为分布式系统的一个核心理论问题,它很重要,但往往也离上层的应用开发人员比较远,不是那么好理解,也因此在前面没有仔细来阐释这个。

在经过足够多的铺垫,足够多的知识积累之后,本篇将对这个问题,做一个通俗,而又深入的讨论。

2大类一致性问题
一致性问题,在计算机中场景比比皆是,大致说来可以分为2大类:
事务一致性
案例1:你数据库同时操作多张表,如何保证多张表,要么同时成功?要么同时失败?(我们知道要用数据库提供的事务机制。事务是数据库的一个非常核心的特性,其实现原理也充满了各种巧妙的地方,以后有机会会专门来分析一下Mysql的事务到底怎么玩的)

案例2:你的系统有缓存,有DB。现在你要同时修改缓存,和DB,如何保证2者同时修改成功? 缓存又没有回滚机制,缓存和DB数据不一致了,咋处理?

案例3:现在都讲微服务架构。如果你的1个请求,调用2个微服务,都要update数据。1个update成功了,1个update失败了,数据不一致了,咋处理?

。。。这样的场景还有很多,很多

多备份一致性
所谓多备份一致性,就是你的数据有多个副本的时候,怎么保证这多个副本的数据完全一样呢?
如果多个副本的数据不能完全保持一致,那不同客户端从不同副本读取数据,结果不是会不一样?

为什么要搞多个备份呢? 1种是为了高可用。
比如Kafka,每个partiton都多个备份;
比如Zookeeper,要搞多个备份;
比如数据库,要搞多个备份。。。

还有1种呢,就是像比特币,以太坊这种P2P的网络,天生就是多副本的。每个节点都是1个副本,所有节点对等的,每个节点都存储了区块链的所有数据,怎么保证每个节点的数据完全一样?

在此处,我们探讨的分布式一致性,就是专门针对第2类,多备份一致性。
关于第1类,事务一致性,我在另外一篇文章中有系统的探讨,参见:
分布式事务 – 最佳实践方案汇总 – 看这1篇就够了

比特币/以太坊 怎么解决分布式一致性问题的? – 经济学的办法
前面讲过,比特币/以太坊 在挖矿过程中,都会出现分叉,也就是节点之间数据不一致。

从计算机技术的角度讲,你可以说,比特币/以太坊其实并没有解决这个问题,而是接受这个问题的存在!!

中本聪的天才之处在于,他用经济学的办法,变相解决了这个问题:你可以在侧链上挖,你可以让整个网络的数据不一致,但这对你没啥好处。你在侧链上挖出的块,别人都不认,这会迫使你放弃在侧链上挖矿,而是不断同步主链,保持在主链上挖。

用句通俗的话来讲:大家都不要闹分歧嘛,团结一致,才最符合每个人的利益!! 通过这种经济学的办法,让所有人的数据往一致性上收敛。

但也正因为这是个经济学的解决办法,不是计算机技术的办法,因此一旦遇到重大的利益分歧点,整个网络也就不可能一致了。

所以我们看到,比特币/以太坊今天都出现了硬分叉,可以说,永久的数据不一致了。

Paxos/Raft – 内网多节点数据一致性

比特币/以太坊的这种场景,的确可以用经济学来解决问题。

但考虑另外一个场景:1个企业的内部,在局域网里面,我有多台机器,多个备份(比如数据库),这多个数据库都同时提供读写服务,那我怎么保证这多个备份的数据完全一致??

这里不可能再用经济学的办法,你必须从技术的角度去保证,这多个节点的数据完全一致。

而这就要用到Paxos/Raft算法。这2个算法呢,都很复杂,尤其Paxos,晦涩难懂,我在另外一个序列,有专门讨论,参见。
https://blog.csdn.net/chunlongyu/article/details/72834274

后面有机会,会对这2个算法,进行更全面的介绍。

HyperLedger Fabric如何解决分布式一致性问题的? – Order Service
Fabric作为1个联盟链,既不同于企业内部的节点之间的数据一致性(需要技术上严格保证),也不同于比特币/以太坊这种(公网上,上万个节点,通过经济学解决)。

Fabric的这种场景呢,其实是被简化了:首先,它的节点数不会很多;同时,交易处理是异步的、批量的,并不是客户端发送交易了,同步的要立即结果。

Fabric的处理分布式一致性问题,就是用了3个典型技巧:
请求排序(交易排序) – Order Service
考虑下面的场景:3个client同时分别向3个Peer发送了请求T1, T2, T3
Peer1处理T1,同时要把T1转发给Peer2, 3;
Peer2处理T2,同时要把T2转发给Peer1,3;
Peer3处理T3,同时要把T3转发给Peer1, 2。

那结果每个Peer收到的Transaction的顺序都不一样:
Peer1接收到的可能是T1, T2, T3;
Peer2接收到的可能是T2, T3, T3;
Peer3接收到的可能是T3, T1, T2;

3个节点接收到的Transaction的顺序不一样,怎么保证3个Transaction处理完毕之后,3个节点数据一样????

那怎么处理呢? Fabric用了一个很简单的办法,如下:
3个Peer收到请求之后,并不立即处理,只是模拟执行(此时Peer充当的角色就是Endoser); 把请求都转发给Order Service,Order Service对所有的请求排个顺序,再发回给Peer1, 2, 3。这样Peer 1, 2, 3看到的请求的顺序就是完全一样的了。

比如Order Service接受到3个peer的3个请求,顺序是T1, T3, T2。 那它就按这个顺序,打包成Block,发给3个peer执行(此时peer充当的就是Commiter角色)。

3个Transaction怎么排序并不重要!重要的是3个Peer看到的顺序是完全一样的!!!

日志流水 + 状态机模型
在Paxos/Raft序列中,我们分析了日志流水 + 状态机的模型;在以太坊中,也有类似的模型。

到了Fabric里面,具体到上面的图,也类似: Order Service就相当于日志流水,每个peer都是1个状态机。日志流水只有1份,那每个peer(每个状态机)对这个流水进行回放,得到的状态机肯定也一样。

乐观锁(基于版本的并发控制) – 读写集

当出现多个Transaction并行修改同1个状态(同1个账号的记录)时,就会面临并发的锁的问题。

在Fabric中,引入了一个读写集的概念,其实就类似于Mysql中的乐观锁的机制,这个在下1篇中,将详细来讲这个问题。

相关链接:
《HyperLedger - 序列2 - Fabric 1.0 架构解析与Transaction处理全流程》
《HyperLedger - 序列1 - 公有链 vs 联盟链》

有兴趣朋友也可以进一步关注公众号“架构之道与术”, 获取原文。 或扫描如下二维码: 这里写图片描述

猜你喜欢

转载自blog.csdn.net/chunlongyu/article/details/80759034