区块链设计模式系列(二)本地优先

本地优先 (Local First),指的是类似 google doc 这样一种应用,网络连接正常的时候可以多人协同编辑一份文档;而网络中断的情况下,每个参与者还是可以正常的编辑文档,软件的功能基本不受影响,只是期间看不到其他协作者的修改;等到网络连接恢复,会自动同步并合并多个参与者期间对文档的修改。

当然对于开发者来说,还有一个更加熟悉的例子,那就是 git

Local First 有很多优势:可用性高,离线状态也可以继续使用;安全,本地保存数据;隐私,只传递必要的交互数据。

更详细的描述可以参见: 不要在云上保存你的数据(一):本地优先的七个理念不要在云上保存你的数据(二):未来软件发展途径

区块链系统的节点之间也是一种本地优先的关系。

  1. 区块链设计模式系列(一)对等网络里提到,区块链的每个节点地位是对等的,每个节点都可以处理用户的请求,也都可以出块。因此,节点需要处理的内容,不管是交易,还是区块,都有两个来源:本地的,来自其他节点的。
  2. 对于来自其他节点的内容,出于安全的考虑需要做严格的合法性检查。但是检查通过之后,后续处理过程,跟本地的数据处理是一样的。这里的检查可能是依赖本地状态的,跟本地状态有冲突的数据都会被抛弃。整体上有点merge操作的味道。
  3. 节点间似断似连。在共识阶段之前,比如交易池和未确认的链,节点都是以本地状态为基础来操作的,可以说各个节点在不停的分叉。然后通过merge来自其他节点的内容,在一定的时间延迟之后,趋于一致。

架构示意图:

实现上的主要难点在于交易和区块链管理系统需要进行类似merge的操作,来合并源自本地和源自其他节点的操作。因此要实现成一种类似版本控制软件的架构。
调研了现有的版本控制软件,但是其实现层次都比较低,无法感知到比较高层的应用语义,也无法简单的定制自动合并策略。参见 https://rink1969.github.io/darcs-vs-git

这里的话题稍微延展一下就可以关联到一个经常被问的问题:区块链和分布式数据库的区别,区块链是不是就是拜占庭容错的分布式数据库?
其实两者的差异还是比较大的。
对于分布式系统来说,根据CAP定律,一致性,可用性和网络分区,三者只能取其二。网络分区是不可控因素,因此是必选的。系统跟通常只能在一致性和可用性两者之间进行权衡。
分布式数据库选择了强一致性,但是牺牲了可用性。像前面 google doc的例子,如果是分布式数据库的化,网络链接一断,文章就编辑不了了。
区块链则是选择了高可用,而牺牲了一致性(只能做到弱一致性)。网络链接断了之后,文章还可以本地编辑,但是别人的修改就看不到了,可能存在冲突。

造成这样的区别,关键其实不在共识算法上,Fabric虽然用的是raft共识算法,但是还是属于区块链范畴的,跟分布式数据库还是不同的。
关键在于交易池。用户往区块链上发送交易,只是本地节点做验证,然后进入交易池,就给用户响应结果了。后续交易能否上链,以什么顺序上链,是由出块节点决定的。整个上链过程,以交易池为分界点,分成了异步的两个阶段。
而分布式数据库的写入操作是同步的,必须得到多数节点的响应,才会给用户响应结果。如果系统出了问题,那么用户就会阻塞在那里,直至超时,因此是牺牲了可用性的。但是正因为如此,系统写入的顺序一定跟用户发起写入操作的顺序是一致的,而不会打乱顺序。

因此,从技术角度倒推,真正适合区块链的场景,至少能跟分布式数据库形成差异的,应该是需要高可用性,不要求强一致性,从操作到最终结果是异步的场景。

另外一个相关的点是CRDT技术-- Conflict-free Replicated Data Type
它是一种跟Local First场景完美契合的技术。详细信息看上面的链接。
因此,区块链也可以应用这种技术。在共识阶段之前,比如交易池,分叉树,本身就是CRDT类型的数据结构,多个节点同时修改,最终把这些修改都merge到一起。
在这个视角下,共识算法是用来解决merge时的冲突的。当然什么算冲突,这个是可以自己定义的。假如是DAG类型的区块链系统,那就不会有冲突,因为这种系统本身就容忍同一个高度有多个并列的区块。当然也可以像某些项目一样,在发现有实质的冲突的时候,再发起共识。或者通过限制系统支持的操作的类型,规避实质的冲突。
这样我们就会发现,共识算法不是必需的。可以一直做全局共识,也可以需要的时候叫出来做局部共识,甚至可以完全不需要共识。
区块链的形态也可以灵活的改变,可以是链式的,也可以是DAG的,甚至是退化成传统的协作系统。