Eventuate:基于操作CRDT的服务框架

Eventuate是建立高扩展的事件溯源event sourcing和使用因果一致性建立事件协助的开源服务框架。基于事件驱动和事件溯源的服务能够给予因果顺序的事件流通讯,服务可位于单个服务器本地也可以分布到全球规模,使用因果一致性复制,保持网络分区之间的写操作高可用性。

Eventuate有Java和Scala两个API,基于Akka编写。

具体特性如下:
1.提供建立有态事件溯源服务、持久化和内存查询数据库和事件处理管道。
2.激活服务通过一个可靠分区冗余事件总线通讯,该总线基于因果事件顺序,可分布到大型分布式系统。
3.支持使用因果一致性进行有态服务复制,使用自动和互动的冲突解决方案实现当前状态更新。
4.提供基于操作的CRDTs(Conflict-free replicated data types )实现。
5.允许服务跨多个区域分布开发运行
6.支持用于更新查询数据库的分布式服务的事件聚合
7.提供适配第三方流处理框架用于事件流分析。

基于操作的CRDTs
CRDTs是免冲突复制数据类型Conflict-free replicated data types 的简称。是一种可复制的数据类型,在发生更新时,所有数据类型最终会收敛到相同状态。一个CRDT在更新时无需进行复制协调,因此节约了协调成本,提高效率。这使得CRDT对于写操作高可用,CRDT能够被分类成基于状态的CRDTs和基于操作的CRDTs,简称CvRDTs和CmRDTs。基于状态的CRDTs是于传播状态的复制,而基于操作的CRDTs则是传播操作。

如果操作是通过一个可靠的因果(RCB)中间件广播传播就会保证Cmrdt复制最终一致收敛,他们设计用于并行操作交换。

CvRDTs不需要对底层消息中间件有特别要求,但是状态传播需要增加带宽或降低状态大小。

CmRDT操作分为两个阶段:prepare和effect,prepare在本地节点上执行。它着眼于操作和(可选)当前状态,并产生一个代表操作的消息,然后分发给所有的其他节点。effect适用于所有节点上的传播操作。

与事件溯源有关
CmRDT两个更新阶段:prepare和effect和事件溯源实体的更新阶段(命令处理和事件处理)有关:

1.在命令处理中,传入命令(可选)对实体的当前状态进行了验证,如果验证成功,则表示代表该命令效果的事件可被写入事件日志中。这相当于在cmrdt的prepare阶段产生的操作。

2.在事件处理中,写入事件日志中的写入事件被拿出使用,用于更新实体的当前状态。这相当于将产生cmrdt的effect效果。

Eventuate提供 EventsourcedActor实现定制命令和事件处理。

可靠的因果广播
大多数CmRDT需要更新操作的因果传输顺序,因果传输可通过事件日志提供的前后顺序轻松完成,但是,如果事件日志本身被复制(例如在Kafka集群中的一个分区topic),或它一点也不复制的,这样的事件日志的可用性是有限的,因为它必须协调所有复制备份的更新。

因此,让cmrdts共享一个完全有序的事件日志会受限制于底层的事件日志的可用性,这不是我们想要的。

我们需要的是将cmrdt复制跨分布地理位置(或可用性区域)分布,每个本地都有其自己的本地事件日志,仍然保持可以写入,即使与其他地方分区分开来。在一个本地写入的事件通过异步和可靠地复制到其他位置。能够在这样一个网络复制本地事件日志以达到最强的全局秩序才满足的cmrdts规定的因果关系。

在Eventuate 中本地事件日志称为可复制的event log,可复制的event lg中因果跟踪通过向量时钟实现,向量时钟是作为潜在的因果关系代表,是一种部分顺序。

CRDT服务框架
之前介绍了如何将CmRDT继承到Eventuate的事件溯源和事件协调底层设施,为了解放CmRDT开发者,Eventuate提供CmRDT服务开发框架隐藏了这些底层细节。

详细原理见:https://krasserm.github.io/2016/10/19/operation-based-crdt-framework/

Eventuate项目:
GitHub - RBMHTechnology/eventuate: Global-scale ev