共识机制一直是区块链领域最值得争议的话题之一。从最初的PoW到近期的PoS,到未来的DPoS,每种架构和理论所带来性能、特点与优劣势各自非常明显。而近一段时间IOTA提出的DAG理论及其各种变型也充斥在社区上被大家讨论。在这里笔者阐述一下自己的看法,片面之处也请业界专家指正。
区块链即分布式多活数据库,这是笔者一直以来对区块链本质的理解。抛开账本即事务日志的存储模块,其所谓的“共识”机制从本质上来说与分布式数据库中“一致性算法”有异曲同工之处。
纵观数据库历史的发展,IBM DB2 for z/OS与Oracle RAC是Share Disk架构中的鼻祖,其核心理念在于多个服务实例共享存储,而在服务之间通过高速网络连接以实现共享锁与共享内存(RDMA等)。这种架构一般被用来实现高可用(HA),但是对于异地灾备环境来说,业界的普遍做法是采用主从日志复制(Log Shipping)的方式进行。
在传统Log Shipping机制中,集群中存在一个可读写的主数据节点,与一个或多个只读的从节点(开始时从节点只是冷备,后来2008年前后业界才提出在业务层面牺牲强一致的理念,做到备节点只读)。因此可以看出,数据库发展到今天,其灾备架构中一般来说存在一个相对持久的主节点进行交易日志生成,之后通过网络将该节点生成的交易日志发送给其他备节点进行回访,从而达到主备节点之间数据最终一致的目标。
而这种机制与区块链的“出块”何其相似。可以说区块链数据同步的本质就是Log Shipping,唯一不同的地方在于每次出块的过程中需要进行多节点间竞争,只有获胜的节点才获得记账权(也就是发送事务日志的权利)。这部分与传统数据库永远由主节点发送日志不同,区块链的第一个开源实现比特币,其十分钟出块的设计思路使得集群中的主节点每十分钟改变一次,从而避免了任何“主从”概念,做到全节点对等。
而另一个与数据库事务日志不同之处则在于,区块链的节点间数据同步采用定时检查点的理念,而非以事务提交回滚为检查点。这里定义,检查点即数据从内存真实落入磁盘的过程。只有数据从非永久存储的内存写入永久存储介质后,才认为该数据被永久保存。数据库一般在提交回滚操作时会触发一个日志缓存刷盘的过程,通过DIO的方式将日志写入磁盘。而比特币则只有每次出块时,才会将数据块作为日志永久结构写入链条并发送给其他节点进行持久化存储。从本质上讲,两者之间没有任何区别。
因此可以看到,区块链的出块、同步、以及回放机制都是一种检查点同步的过程,而该过程不论从PoW、PoS、甚至DPoS来看都是一种同步操作。因此,我们可以认为,区块链的链式结构中,使用账本同步机制实现的共识算法为检查点式同步持久化策略。
而IOTA则提出DAG模式,以及近期依据DAG思路所提出的一系列变种,则采用异步持久化策略。
从数据结构体系来看,DAG模式是一种典型的谣言传播算法,其核心机制即在于异步通讯。
异步通讯所带来最大的问题在于一致性不可控。就好像微服务架构中最让开发者头痛的在于各个微服务之间一致性与先后顺序控制的逻辑,远比传统开发模式复杂许多。
具体来说,在DAG模型中所带来的第一个问题在于交易确认时间完全未知。在链式结构中,只要一个区块出块后基本其交易的确认时间是相对可控的。但是DAG由于每个节点各自为政,因此没有非常强有效的机制保证交易的确认时间。在IOTA当前的实现中可以通过重试的机制来重新激活长期未确认的交易。
而DAG算法的另一个更重要的潜在问题则是排序。对于仅支持加减运算的简单交易类业务,在最终一致性的前提下只要两个业务均被执行,一般来说先后顺序并不是非常关键。但是,在图灵完备的场景需求中,一般来说加减乘除等四则运算是至少需要保障的。这样一来,对于一条记录的操作顺序则至关重要。
举例来说,针对同一个账户的当计息操作(乘法)与转账操作(减法)在两个不同节点同时发起时,节点A首先对100元本金执行5%利息的乘法操作,得到105元;之后节点A接收到节点B传来的转账10元的请求,最终结果为95元。但是,对于节点B来说,其首先得到对账户转账10元的请求,即账户变为90元,之后进行计息5%,结果为94.5元。这种情况在一个复杂系统中,如果没有一种类似全局“账本”的机制保障每个节点最终所确认的操作顺序保持一致的话,很有可能出现节点间所记录的数据在运行一段时间后出现较大的偏差。这是DAG算法急需从理论上解决的问题。
因此,DAG所带来的两个潜在问题(1)交易时长不可控,当前通过请求重发的机制需要在客户端进行一些较为复杂的超时机制设计,希望能够存在更简单的一次性确认机制;(2)不存在全局排序机制,导致系统支持的操作类型受限。
因此,笔者认为,DAG与链式结构相比有创新有不足,其优势在于将异步通讯理念替换传统的同步检查点机制,以期望提升设备的响应速度。但是其几个核心问题使其在通用化业务场景中是否能够得到大规模应用,提出了不小的挑战。