分布式系统


摩尔定律如果一直能实现,不管是涉及或者实现一个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(一)的更多相关文章

  1. Event Sourcing - ENode(二)

    接上篇文章继续 http://www.cnblogs.com/dopeter/p/4899721.html 分布式系统 前篇谈到了我们为何要使用分布式系统,因为ENode本身就是一个分布式的框架.看了 ...

  2. Event Sourcing - ENode(三)

    接上一篇 http://www.cnblogs.com/dopeter/p/4903328.html 老板昨天在第二篇介绍中回复代码和文字无法一一对应.为了更好的让老板为大家解惑,把第二篇最后的猜测的 ...

  3. Event Sourcing

    Event Sourcing - ENode(二) 接上篇文章继续 http://www.cnblogs.com/dopeter/p/4899721.html 分布式系统 前篇谈到了我们为何要使用分布 ...

  4. Event Sourcing Pattern 事件源模式

    Use an append-only store to record the full series of events that describe actions taken on data in ...

  5. CQRS, Task Based UIs, Event Sourcing agh!

    原文地址:CQRS, Task Based UIs, Event Sourcing agh! Many people have been getting confused over what CQRS ...

  6. Typed Message模式与Event Sourcing

    引言 在<设计模式沉思录>(Pattern Hatching: Design Patterns Applied,[美]JohnVlissides著)一书的第4章中,围绕事件Message传 ...

  7. DDD创始人Eric Vans:要实现DDD原始意图,必须CQRS+Event Sourcing架构

    http://www.infoq.com/interviews/Technology-Influences-DDD# 要实现DDD(domain drive  design 领域驱动设计)原始意图,必 ...

  8. Event Sourcing pattern

    Event Sourcing pattern Instead of storing just the current state of the data in a domain, use an app ...

  9. DDD CQRS和Event Sourcing的案例:足球比赛

    在12月11日新的有关DDD CQRS和Event Sourcing演讲:改变心态- 以更加面向对象视角看待业务领域建模中,作者以足球比赛football Match为案例说明传统编程方法和CQRS的 ...

随机推荐

  1. 用数组array代替CActiveRecord构建CArrayDataProvider

    当需要构建 GridView的时候: 常常用 CArrayDataProvider 或者 CActiveDataProvider 这是就需要一个CActiveRecord 比如:  857       ...

  2. 编译gRPC

    编译gRPC 目录 一.概述 二.编译gRPC 三.C#中使用gRPC 四.C++中使用gRPC 无论通过哪种语言调用gRPC,都必须要编译gRPC,因为生成proto访问类时,除了产生标准的数据定义 ...

  3. uva10635 LCS映射转LIS

    题目给定 2个序列,要我们求LCS,但是序列的长度最长是250*250, LCS的时间复杂度是O(N*N),所以无法解决 我们可以第一个序列的数字,按位置,映射为1.2.3.4.5.6.7.8.9 那 ...

  4. DataTable筛选器

    //datatable筛选器,函数包装模板:传入源table,目标table,db名,多表查询table,列条件数组,where筛选列,selsect筛选列 public DataTable Filt ...

  5. Android DrawerLayout 抽屉

    Android DrawerLayout 抽屉 DrawerLayout 在supportV4 Lib在.类似的开源slidemenu如,DrawerLayout父类ViewGroup,自定义组件基本 ...

  6. Ejb in action(两)——示例入门

    在前面的文章中,,我们推出Ejb相关概念.在此之前展开的阐述,我给大家Ejb示例.加深印象. 开发环境:eclipse 应用server:jboss 1.服务端程序 在Eclipse中创建一个Ejb项 ...

  7. 返璞归真 asp.net mvc (3) - Controller/Action

    原文:返璞归真 asp.net mvc (3) - Controller/Action [索引页] [源码下载] 返璞归真 asp.net mvc (3) - Controller/Action 作者 ...

  8. C++习题 商品销售

    Description 商店销售某一商品,每天公布统一的折扣(discount).同时允许销售人员在销售时灵活掌握售价(price),在此基础上,一次购10件以上者,还可以享受9.8折优惠.现已知当天 ...

  9. Best Time to Buy and Sell Stock I,II,III [leetcode]

    Best Time to Buy and Sell Stock I 你只能一个操作:维修preMin拍摄前最少发生值 代码例如以下: int maxProfit(vector<int> & ...

  10. 在C#主线程和子线程将数据传递给对方如何实现

    在C#中主线程和子线程怎样实现互相传递数据 老帅 在C#中创建线程Thread时,能够有多种方法,而主线程和子线程之间又怎样实现互相传递数据,每种创建方法传递參数的效果是不同的,逐一看一下:  一.不 ...