Event Sourcing - ENode(一)
分布式系统
摩尔定律如果一直能实现,不管是涉及或者实现一个OLTP的系统,我们是不是都会轻松点,用硬件堆就可以了。但是现在硬件已经在求变了,那么我们也得求变,云的概念如此之火,本质就是设施虚拟化,也可以认为是逻辑化,那么我们做软件是不是也要来虚拟化一下呢,当然,软件本身就是虚拟逻辑化。
如果摩尔定律继续支持IO设备性能往上走,那就皆大欢喜,可惜不是这样。于是我们将系统做成多个实例,也许一个系统中还有很多子系统,全部实例化,一股脑扔进一个大的“计算机”里面,这个“计算机”是逻辑的,物理上就有太多组合了,可能在中国有一个服务器是一个系统实例或者子系统实例,在美国也有。从外面看,就是一个完整的系统,从内部看,由多个系统实例组成,因为是逻辑隔离的,所以认为是分布的。
一个系统的多实例,也许是部署在不同机器上,或者容器,或者单台机器,但是他们都是独立的运行单元了,假如将他们理解为在一个机器上运行的多个程序,要协调他们正常运作,那么我们是不是需要模拟操作系统呢,这就是分布式系统的基础设施,基本上与操作系统的各个基础设施所对应,甚至实现方式都类似,不过在现实当中连接他们的是网线而不是总线。
关系数据库
ACID特性,实质上ACID只是一种指导思维,其实现有各种各样,不管是ORACLE、MSSQLSERVER、MYSQL以及其他关系数据库,大多实现了ACID,我们的系统有各种需求,有时特别需要数据一致性,例如账号存钱取钱之类的场景,所以在关系数据库上我们是基本放心的。在把系统设计成分布式之后,无论我们怎么拆系统,都会因为系统与关系数据库这个短板耦合而无法适应,于是后来的CAP,BASE理论就相继出现了。关系数据库是一个成熟的集成好的软件,我们无法控制,所以干脆我们抛弃ACID中不适应我们系统的需要特性,于是我们将关系数据库给拆了,将存储拆成一个基础设施,其他的我们按需来设计,比如需要一致性的我们用最终一致性来代替,实质上我们将关系数据库的各种组件都拆出来自己来实现。当然这里严格来说不能认为是实现了关系数据库,只能说借鉴了它的一些特性衍生到现在这样。因为没办法,于是我们只好将各种组件拆成可以分区扩展的组件。拆完了数据库,换种说法是持久化设施,我们就可以拆我们的系统了,不拆也可以,直接使用分区扩展的实例,没有问题,因为我们已经将短板给干掉了。
领域驱动
物理架构差不多了,我们需要考虑考虑真正的业务架构与逻辑架构了,DDD的理论不细说,业务架构从DDD的映射来看,可以认为是上下文,当然在物理视图当中,它也许是多实例的。那么对于每个上下文的逻辑架构呢,目前来说,应用最广泛的是经典的4层架构,也有很多变种,根据实际项目的需要,我更喜欢采用六边形架构,不过在实际项目中,我们的采用的框架所面对的问题更实际,可维护性,可扩展性可能更需要注重,也许一个聚合根的概念就需要沟通很多次,各种概念是因人而异的,不管怎么实现,只要最后有这个功能满足了功能需求与非功能需求即可。所以也许最后又变回了原始的3层架构。如果我们坚持贯彻了DDD的概念,那么未来在可扩展上一定是非常方便的。所以要实现DDD,团队成员的要求是比较高的。
CQRS ES
CQRS典型的借鉴了我们在优化关系数据库架构中常用的方法,读写分离。在写DDD的时候,是不是碰到过模型适应写与读场景的不匹配,各种令人烦躁的ORM的N+1问题,也许已经想办法从框架内实现了只读模型的DTO,用CQRS来形容并形成一个标准更能让大家接受。不同的架构师面对同一个问题有不同的解决方案,但也许只是变种,如果能统一大家的使用方式形成专业的语言,例如领域语言,那么我们就可以集合大家的力量齐头并进了。CQRS就算是一种。
为什么要使用ES呢,我们来想想关系数据库实现数据一致性的方式,假如我们要插入一条数据,数据库先写日志,然后插入表中,这样的描述不够准确,但大致如此,不要纠结,我想说的是关系数据库采用了一种方式称为写屏障,在真实写入之前先记录,在异常情况下,我们就可以保持数据的一致性,现在Linux的很多新型文件系统就是采用了此种方式,那么ES呢,也是一种写屏障,只不过将数据定义为了面向DDD中的领域事件,我们可以通过Event来查询源头重新演绎领域对象的状态。同时,我们也在ES中使用了写屏障,那么这里我们也实现了一致性,不过是最终一致性。但是如果我们从关系数据库来看,其本质也是最终一致性,例如关系数据库在插入数据的某一刻它突然断电,重启之后,查询日志,该插入的数据还是插入(逻辑不是如此简单),那么从内部来看都是最终一致性。
从性能角度来考虑,那就有关于聚合根的粒度了,聚合根的粒度越细,Event必然越多。
ENode
EDA ES框架
前面所讲的都是我在看到ENode框架之后想到的,ENode框架不仅满足了分布式的需求,在DDD以及ES的概念上真正的做成了可以使用的框架,只要对DDD以及CQRS的概念理解的足够深,那么使用它将会是最好的选择。
要想使用ENode的所有特性完成项目,那需要团队成员对DDD有足够多的理解。
因为想采用ENode框架,所以将预研ENode框架的过程和大家分享一下。
在业务的可扩展性我们从DDD上我们就可以保证,所以无需多说。
引用作者的设计图

因为是预研性的项目,所以对于框架的易用性、易理解性、维护性,关注的稍微要少些。更多的是想理解作者的设计思想。
关注框架是否能满足项目的非功能需求、核心功能需求,所以先尝试关注以下几点:
1. 分布式
划分好上下文后,采用ENode框架实现,就可以直接使用分布式的基础设施将上下文的多个实例连接起来。
其实ENode本身就是支持分布式的,内部采用了作者自己编写的消息中间件EQueue,EQueue有点类似于Apache Kafka的设计,也是支持动态扩容的消息框架,从性能上来说整个就满足了分布式的需求。
2. 是否能满足一致性
(1)从写屏障的角度来说,ES可以部分支持一致性,一致性在分布式的环境中实现的方式有多种,涉及到几个概念,对一个操作至少执行一次,绝对只执行一次,当然还可以自己设计,例如不知道执行与否,就是我会执行但不知道执行结果。扯远了,如果要绝对只执行一次,在实现以及性能上都会有一些折扣,作者采用的是至少执行一次,怎么讲呢,至少执行一次所遵从的原则是必须经过了写屏障,如果没经过写屏障,那么我们可以认为这是无效的,经过了写屏障,系统宕机,可以通过ES重新发起事件。这里执行的就是Domain Event。
既然是至少执行一次,那就会有幂等的处理,作者设计非常灵活,允许使用者自己来装配,在作者的Sample中,使用了MSSQLSERVER来持久化Event,通过MSSQLSERVER中的唯一约束做乐观锁来做到幂等。
在聚合根的内部采用乐观锁来消除幂等,可以在很多个地方使用乐观锁,不管是ENode框架本身提供的,例如在Command Store、Event Store处由SQLSERVER来实现,也可以通过ZooKeeper实现,作者也提供了分布式悲观锁的接口以及采用SQLSERVER的实现,乐观锁就像是一个检查点,台湾人喜欢称这种检查点为机关,我们可以设置合适位置设置合适数量的机关来检查并发。
(2)对应关系数据库的隔离性,在作者的设计中,是按照聚合根来隔离并发的。
使用了聚合根的粒度来实现隔离,在聚合根内部采用了乐观锁或者悲观锁,减小了锁的粒度,来换取性能的提升。
在作者的设计图中还未完全标注出一些组件,
CommandHandler,EventHandler,ApplicationMessageHandler,ExceptionMessageHandler,不是很准确,有兴趣的朋友可以自行查看源代码。
Command、Event是DDD的领域语言
ApplicationMessage、Exception是作者在框架设计的框架领域语言
这些都是作为底层的可传递的消息,可以理解为分布式的消息,上面罗列的Handler都是作者默认实现的,采用的是Actor模式,都是有自己的MailBox,那么其实现就是顺序的并且是单线程的。在某一时刻,单个的系统实例中,Command、Event、ApplicationMessage、Exception都是在并行,但他们内部是只有一个在运行实际的逻辑。这也是可以装配的。
Event Sourcing - ENode(一)的更多相关文章
- Event Sourcing - ENode(二)
接上篇文章继续 http://www.cnblogs.com/dopeter/p/4899721.html 分布式系统 前篇谈到了我们为何要使用分布式系统,因为ENode本身就是一个分布式的框架.看了 ...
- Event Sourcing - ENode(三)
接上一篇 http://www.cnblogs.com/dopeter/p/4903328.html 老板昨天在第二篇介绍中回复代码和文字无法一一对应.为了更好的让老板为大家解惑,把第二篇最后的猜测的 ...
- Event Sourcing
Event Sourcing - ENode(二) 接上篇文章继续 http://www.cnblogs.com/dopeter/p/4899721.html 分布式系统 前篇谈到了我们为何要使用分布 ...
- Event Sourcing Pattern 事件源模式
Use an append-only store to record the full series of events that describe actions taken on data in ...
- CQRS, Task Based UIs, Event Sourcing agh!
原文地址:CQRS, Task Based UIs, Event Sourcing agh! Many people have been getting confused over what CQRS ...
- Typed Message模式与Event Sourcing
引言 在<设计模式沉思录>(Pattern Hatching: Design Patterns Applied,[美]JohnVlissides著)一书的第4章中,围绕事件Message传 ...
- DDD创始人Eric Vans:要实现DDD原始意图,必须CQRS+Event Sourcing架构
http://www.infoq.com/interviews/Technology-Influences-DDD# 要实现DDD(domain drive design 领域驱动设计)原始意图,必 ...
- Event Sourcing pattern
Event Sourcing pattern Instead of storing just the current state of the data in a domain, use an app ...
- DDD CQRS和Event Sourcing的案例:足球比赛
在12月11日新的有关DDD CQRS和Event Sourcing演讲:改变心态- 以更加面向对象视角看待业务领域建模中,作者以足球比赛football Match为案例说明传统编程方法和CQRS的 ...
随机推荐
- C++-传值与传引用的差别
//值传递与引用传递的差别 #include <iostream> #include <iomanip> using namespace std; void fiddle(in ...
- hash表、hash算法
概念: 散列表(Hash table.也叫哈希表),是依据关键码值(Key value)而直接进行訪问的数据结构. 也就是说,它通过把关键码值映射到表中一个位置来訪问记录,以加快查找的速度.这个映射函 ...
- kb3035583
dism /online /Get-Packages /Format:Table|findstr 3035583 升级到w10补丁
- 【解决】/usr/bin/ld: cannot find -lc
现象:运行gcc静态编译程序时报错: /usr/bin/ld: cannot find -lc collect2: ld returned 1 exit statusmake: *** [gcc_dr ...
- Git代理服务器设置和访问Github
因为现在工作的网络环境有着非常严格的限制,.可以说,在最近的访问通过代理Github它采取了一些曲折的.也积累了一些相关经验.我们认为有必要注意什么. 符合"不要再发明轮子"宗旨, ...
- Windows 8 应用开发 - 本地数据存储
原文:Windows 8 应用开发 - 本地数据存储 在应用中通常会遇到用户主动或被动存储信息的情况,当应用关闭后这些数据仍然会存储在本地设备上,用户下次重新激活应用时会自动加载这些数据.下 ...
- Swing程序最佳架构设计—以业务对象为中心的MVC模式(转)
前言: 我打算写一系列关于Swing程序开发的文章.这是由于最近我在做一个Swing产品的开发.长期做JavaEE程序,让我有些麻木了.Swing是设计模式的典范,是一件优雅的艺术品,是一件超越时代的 ...
- T-SQL基础(2) - 单表查询
开窗函数over select orderid, custid, val, SUM(val) over() as totalvalue, SUM(val) over(partition by cust ...
- strchr,wcschr 和strrchr, wcsrchr,_tcschr,_tcsrchr功能
strchr,wcschr 和strrchr, wcsrchr,_tcschr,_tcsrchr功能 (1) char *strchr( const char *string, int ...
- nyoj 117 找到的倒数 【树阵】+【分离】
这个问题的解决方案是真的很不错!!! 思路:建立一个结构体包括val和id. val就是输入的数,id表示输入的顺序.然后依照val从小到大排序.假设val相等.那么就依照id排序. 假设没有逆序的话 ...