分布式系统


摩尔定律如果一直能实现,不管是涉及或者实现一个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. XML解析中的namespace初探

    原文:XML解析中的namespace初探 初学者在解析XML文件的时候最容易遇到的问题恐怕就是XML的namespace了,本文旨在对namespace做一个简要的介绍. namespace的意义无 ...

  2. jconsole线程面板中的阻塞总数和等待总数(转)

    阻塞总数 Blocked count is the total number of times that the thread blocked to enter or reenter a monito ...

  3. windows phone 三种数据共享的方式(8)

    原文:windows phone 三种数据共享的方式(8) 本节实现的内容是数据共享,实现的效果描述:首先是建立两个页面,当页面MainPage通过事件导航到页面SecondPage是,我们需要将Ma ...

  4. NYOJ 45 棋盘覆盖 模拟+高精度

    题意就不说了,中文题... 小白上讲了棋盘覆盖,于是我就挖了这题来做. 棋盘覆盖的推导不是很难理解,就是分治的思想,具体可以去谷歌下. 公式就是f(k) = f(k - 1) * 4 + 1,再化解下 ...

  5. 每天一点儿JAVA-向量的操作

    package java_prac2; import java.util.*; /** * <p>Title: 矢量操作</p> * <p>Description: ...

  6. kb3035583

    dism /online /Get-Packages /Format:Table|findstr 3035583 升级到w10补丁

  7. 基础知识(1)- Java程序设计概述

    1.1 Java程序设计平台 1.2 Java“白皮书”的关键术语  1.2.1 简单性  1.2.2 面向对象  1.2.3 网络技能  1.2.4 健壮性  1.2.5 安全性  1.2.6 体系 ...

  8. Java Drp项目实战——Drp知多少

    是什么 Drp是Distribution Resource Planning的缩写,意思是分销资源计划.它是用来管理企业的执行于Internet上的分销网络的系统,是以商业流程优化为基础,它的核心是销 ...

  9. log4j 日志大小限制 分成30一个 不按日期分日志 按大小分成 按生产日期

    首先说说生成按日期.不解释,大家都懂的,这种方法的缺点是很吃硬盘空间 log4j.rootLogger=INFO,logfile,stdout log4j.logger.java.sql=DEBUG, ...

  10. Xamarin.Android 入门实例(2)之实现WCF 寄宿于IIS 的Web服务提供

    1.WCF 契约 ICalculator.cs using System.ServiceModel; namespace Contracts { [ServiceContract] public in ...