大多数系统在数据库存的都是系统的状态数据,好比一个用户表可能会存用户的姓名、头像、个性签名等信息。若是只存状态数据的传统模式会有什么问题呢?sql
假设你公司作了一个系统,并正式上线了。通过一周的推广,老板问你要一些用户的行为数据。老板想知道全部用户平均修改个性签名的次数。数据库
对于传统的数据库设计,当用户修改个性签名,会执行相似以下的 SQL 语句:设计模式
UPDATE Users SET Sign='Talk is cheap, show me the code.' WHERE Id=123
问题是目前数据库没有记录用户修改密码次数的字段。因而,为了更快的实现老板的需求,你须要给数据库的用户表增长这样一个字段。用户每次修改个性签名的时候,这个字段值加一。数据库设计
这样虽然很好的解决了问题,但若是这种需求愈来愈多,好比老板又问你要全部用户平均修改密码的次数,就会有一些明显的问题:学习
上面用户的个性签名、密码修改次数的例子算是简单的需求,增长字段、修改代码还能够应付。但需求稍微变换一下,复杂一点,好比要分析某商品在用户购物车中变化的状况,如什么时间点添加这个商品到购物车的用户最多、当用户从购物车移除该商品的同时购物车中有哪些竞品等。这种需求带来的修改,会使数据库设计和系统变得无比复杂,产生的工做量也是巨大的。测试
可见,随着系统不断扩大,业务需求愈来愈多样化,这种数据库存储状态数据的传统模式就会愈加捉襟见肘了。设计
面对这种“痛”,事件溯源多是一剂良方。日志
事件溯源(ES,Event Sourcing),字面上理解就是使任何对数据的修改均可追溯。code
事件溯源是一种设计模式。相对于传统的在数据库中存储系统的状态,事件溯源在数据库中存储的是系统发生的事件。blog
举个例子,当用户在系统中注册后,一个UserCreated
的事件就被存储了。而后,当用户修改了密码,一个UserChangedPassword
的事件就被存储了。对于这个用户而言,经过事件溯源设计模式,系统能够知道该用户的一举一动。好比按照时间线,某个用户的事件多是这样的:
这样对于前文用户平均修改个性签名次数的需求,就能够轻松应对了。只须要查询事件为UserChangedPassword
的数量再除以用户总数便可。
事件溯源在现实世界中更接近人们的思惟习惯,好比当有人问你今天过得怎么样时,你不会告诉他们今天你的体重是多少、吃了几顿饭(状态数据),而会告诉他们发生了什么有趣的事情(事件)。因此对系统来讲,也更容易建模。
事件溯源适用于数据分析,能够生成各类维度的报表,帮助你更深刻地了解数据;能够提供审计日志,帮助你准确地知道系统是如何从一个状态变成另外一个状态的。好比你在银行存了一千万,隔了一年后发现帐户余额只有一百块。事件溯源就能够告诉你,你是如何一步一步从一个千万富翁变成穷光蛋的。
听上去不错,但事件溯源也不是包治百病的万能药。
事件溯源会给系统增长额外的复杂性。每每用传统方式能够简单快速完成的增、删、改功能,使用事件溯源就会多绕几步。它一般须要与 CQRS (Command Query Responsibility Segregation,命令查询职责分离) 结合使用,这对开发人员而言,学习成本更高。
若是是不须要审计日志的小规模系统,使用事件溯源就会得不偿失。若是团队中没有在这方面有足够的经验的开发者,也不要轻易在生产环境中使用它。没有精钢钻,不揽瓷器活。