为什么要用Event Sourcing?

为什么要用事件采购Why Event Sourcing? - Blog - CQRS and Cloud Computing

这是来自研究CQRS和云计算博客的一篇文章,大意如下:

Event Sourcing(事件采购 事件源驱动)已经越来越被大家熟悉,Event Sourcing本质上是一种持久数据的方式,这种方式能够保留信息详细到bit字节,它将事件的顺序作为对象,这些事件一直在发生并导致当前状态的变化(banq注:传统持久化数据是持久化状态,状态是事实的结果,而不是事实本身,我们在保存结果的同时,实际失去导致这些结果的可能原因,我把这个结果数据比喻成拉屎,我们要经常根据拉的屎推导今天吃了什么,很显然逻辑上不严密)。

打个比喻:持久化数据持久的是当前状态,比如我的零用钱是100EUR,后来变化到新值67EUR,很显然丢弃到前面的状态,将67EUR保存到数据库。

好像简单优雅,但是如果我们在执行大量逻辑,那么很显然会丢失信息,如果我们保留所有改变将是如下:

从ATM机取: 100 EUR
买了地铁票: -12 EUR
吃了一次午餐: -8 EUR
找到一个硬币: 1 EUR
出租车花费: -14 EUR

如果我们有这样一个事件顺序,我们能够得到当前零花钱结果:

Balance: 100 - 12 - 8 + 1 - 14 = 67 EUR

最后状态是是先前状态的左侧left-fold 功能,类似于 .NET的IEnumerable.Aggregate。C++的std::accumulate和JS的array.reduce。

你现在可能会问自己一个问题,如何保存这些中间过程呢?一种方式就是event sourcing 。

如何将这些事件作为数据保存呢?只要定义成对象即可,然后序列化成其他格式,如JSON XML等,如下:
GotMoneyFromAtm! (amount, transaction, time)
BoughtMetroTickets! (count, amount, machine, time)
GrabbedALunch! (amount, cost, time, menu, place)
FoundACoin! (amount, gps, time)
TookTaxi! (amount, rideDuration, taxiCompany, route, time)


通过给出的事件顺序,我们可以预测他们到任何需要的结构示意图。这是一个非常重要的功能。例如,我们可以写一个总结项目:总结我们的所有费用和生产的最新平衡。

我们还可以做更多的:

输出那些最经常可以发现硬币的城市的清单
获取的是最便宜的或最快的出租车公司,。
前5日个最喜爱的星期一午餐地方。


更有趣的,为了做到这一点,我们并不需要任何真正复杂的查询,。如果你只有当前零用钱状态单一的字段,即使你有一个变化清单(信用卡/借记),尝试这样做编写事件的预测(至少在C#)是枯燥的。

只要你有一个事件流,你可以以任何形式保存它,即使是传统的SQL数据库。举例来说,我最喜欢的方法是将事件流以JSON文本方式存储到云存储中。详情这里

事件代表一种可序列化的数据结构,能够进入追加式流中,如:
发布事件给多个订阅者。
实现冗余和可靠性
支持增量同步

基于事件的架构可以得到几乎无限的可扩展性,非常高的吞吐量和无死锁读取,这是因为如下事实:
事件可以在发生时尽快发布,
从事件模型中获取一些模型非常简单。
事件可以发布给多个用户,每个订阅者拥有自己一份可读取的模型。

因为这些我们几乎可以达到LMAX速度
1.将读取模型(可预先计算的查询结果)直接存储在MemCached内存中,如果某个服务器当机,我们可以直接从事件历史重新导出到缓存中。

2.多个并行读取进程。

3.实时严格要求的系统将得到好处。

其他好处还有:
1.简化部署和维护 很少的SQL
2.减少了对硬件和软件(不需要有非常强大的和冗余的服务器或商业数据库)的费用。
3.系统之间的整合更简单(这里直接适用于所有的企业集成模式)。
4.由于没有数据丢失,我们获得了全面的审计(特别能力是在任何时间点)和优秀的调试功能。
5.事件采购是一个为软件开发人员想捕捉的业务领域的精髓(尤其是最复杂的),同时保持平台的复杂性或硬性能问题脱钩的天作之合。
6.ES的方法,帮助提供市场和技术给我们带来一些新的挑战的明确的答案:云计算,数据处理,移动和偶尔连接的系统,实时的商业智能。

当然,Event Sourcing事件采购不是银弹,只是一种不同的数据思考方式罢了,如果你是C程序员,感觉回到了汇编时代...

下面是一些困难:
1.定义事件是一件艺术,需要熟悉的领域建模,DDD领域驱动设计是关键。
2.需要软件和硬件支持事件采购,在以后几年,你会看到这个领域的很多解决方案。(banq注:jdonFramework是一个支持DDD DCI 事件采购 的开源框架)
3.这方面是新生事物,可指导的经验太少。
4.限制与真正成熟的DDD/ES技能。

其他带来的问题还有:
1.需要超级大的存储消耗。云存储解决。
2.比较慢也不是问题,因为我们优化优化IO来实现快照和持久。并利用基于事件的天然“推”性质,我们可以得到立即失效缓存。简而言之,能够过后有多个插入,需要这种多个的技术解决方案。
3.脆弱(丢失失过去的一个事件将导致整个流腐败)不是一个问题,因为你可以决定自己的SLA水平去(通过复制和冗余)。使用Git的方法,可以可靠地检测在任何一个副本的腐败事件包括SHA1签名针对它的内容和以前的事件签名计算。

CQRS and Event Sourcing

Domain Events – 救世主
使用CQRS重新考虑架构

[该贴被admin于2011-10-30 11:06修改过]

该文作者关于CQRS Starting Page文章:

CQRS 是分离命令 (改变数据的命令)和查询 (读取数据).读写分离。

并给出了CQRS DDD和云计算的路线图:

高清晰的图片按这里

路线图文档下载地址:CQRS路线图.PDF

软件架构变迁大概经过这么一个过程:
数据库 -- > 状态 --->事件

而实际项目中是这样一个过程:
事件 --> 函数方法 ---> 状态 --- >数据库

过去,我们通常在函数方法中使用SQL语句的CRUD(insert update delete)等,SQL操作结果存在数据库中,基本忽视事件 函数方法和状态这样几个环节。

随着面向函数范式编程以及EDA事件驱动架构演进,大家越来越重视导致数据库状态发生变化的原因了。特别是复杂软件系统中。事件已经不只是停留在界面层,处理键盘鼠标按钮等事件了,Javascript这个从界面层诞生的语言衍生出Node.js,占据服务器后端市场,关键也是得益于其事件驱动模式。

Event Sourcing CQRS或EDA 或Domain Events等等都是从事件角度看待软件架构,如果说云计算解决了计算和存储分离及各自的可扩展性,那么事件无疑是触发计算的源动力,事件本身也是一种大数据,需要云存储支持(如NOSQL)。

我在SNS Webgame 社区类页面网游开发帖子中就建议楼主在这样一个游戏系统中大胆采取事件架构,特别是一些实时系统,如LMAX的股票交易系统,使用Disruptor并行框架,能够达到每秒处理600万订单,每微秒延迟获得100T的吞吐量。

该文从设计角度认为事件模型能够解决业务领域复杂性和技术平台复杂性的脱钩。

事件模型可以说是位于领域和技术之间接壤一个边界,在技术上,事件模型代表一种无锁的并发模型。

过去我们都是在一个线程下的同步顺序编程,JavaEE虽然没有让我们直接接触到线程,但是我们的Servlet或Jsp等都是以线程方式解释运行的。

这种下一步依赖上一步,上一步完成后才能运行下一步的顺序编程模型已经完全不能适应现代多核CPU的并行并发硬件结构了。

JDK5或6推出了很多所谓并发包如java.concurrent.*,但是这些并发包都是堵塞Block的,是一种伪并发,最后整个系统性能都集中在这些并发锁上,而CPU效率一直无法真正利用。

后来Actor模型如Scala或Disruptor开始推出无锁无堵塞并发,无堵塞,所以快,Node.js也因为号称无锁,No Lock, No Block, 但是最近却被爆出Node.js是有CPU堵塞的:Node.js是癌症

由此可见,通往真正并发编程模型的编程之路并不一帆风顺,只有去伪存真以后,我们才能发现真正的并发编程模型。

相关帖子:
无堵塞的并发编程
[该贴被banq于2011-10-06 17:27修改过]