DDD 缓存何时持久化

持久化选用SqlServer
我所知的三种持久化方式
1:定时:内存模型在某个时间点回写到数据库文件中(弱一致性-最终一致性)
2:异步:每次模型状态改变后,提交持久化操作到工作队列中去异步执行(弱一致性)
3:即时:每次模型状态改变后,立刻以阻塞的方式进行持久化

我在实践第一种方法,但以此而来产生了一些问题,请各位道友赐教
A1:选用第一种方法后,模型在某个时间点才回与数据库文件一致。那此时需要按照几个条件查询一个列表,排序后选取某一页返回。此时因为内存与数据库并未同步,如何实现这个查询呢?

如果换做第二个方法来实现,因为不同步产生的精确度还在可以容忍的范围内。
但这里也有一个问题
A2:
假设一个模型,有三个业务方法 A、B和C
因为某个命令,模型需要执行方法 A ,再执行方法 B,之后保存
模型在执行方法A时,是通过的。但之后执行B的时候,模型验证报错。
此时,另外一个线程在执行方法C,之后也提交保存了。
由于内存中,模型是同一个,就导致了数据库里保存下了一份错误的数据。

对于A2,我觉得是自己某个地方弄错了,但不知道错在哪里

希望 @banq 和道友们严厉的指出批评我
[该贴被tbyes于2013-03-04 19:09修改过]
[该贴被tbyes于2013-03-04 19:09修改过]

QA1 : 既然是最终一致,瞬时一致肯定做不到的。

QA2 : 在操作Aggre时,如果有特殊需要,可以lock this object. 或使用单进程运行 Domain ,采用内存缓存进行Domain内部使用,可保证Domain的运行一致。

@brighthas

利奥,好久不见

是的,我是在找寻一种方法,在查询的时候,是否可以把内存中的数据结合起来。

好久不见,这里还有个事儿,domain内部的那个cache是“内存真实体”,也就是说,领域不依赖DB本身进行运行,当然这是题外话,具体我和道友探讨了一些,具体看这里

至于解决domain和 UI query的一致性,也有办法,就是监听domain内部状态,举例来说。


var domain = require(‘jsdm’)();
// asycCallback 回调函数就是监听这个命令DB整体完成后再调用,也就是数据已被修改。
domain.exec(命令, asycCallback);

这只是一个方法,其实解决方法不只一个,一起探讨吧。

有个疑问,不是立即持久化的时候,中间当机了怎么办?

2013-03-04 20:00 "@brighthas
"的内容
既然是最终一致,瞬时一致肯定做不到的 ...

是这样,只能追求最终一致性,缓存如何持久化可以参考一些NoSQL内部持久机制,比如好像是MongoDB,其是将数据库操作事件append到日志文件,然后在其他机器上执行这些操作事件。

缓存的数据一般是代表实体的状态,除了状态持久化,如果要追求数据高一致性和事务性,可以持久化改变状态的事件,也就是Event Sourcing, Event Store,将事件根据其发生时间前后放入一个Queue排队,然后依次保存到数据库,需要时进行事件回放,通过事件改变状态。可以参考本站:LMAX架构。

有人问:不是立即持久化的时候,中间当机了怎么办?
使用Disruptor之类多线程框架,虽然是异步,但是执行时间非常迅速,不用担心当机,如果对失败担心到线程执行级别,采取分布式failover策略,比如EJB等等技术。

关于中间当机的问题,对于没有办法玩分布和EJB的项目是否就没有100%的保障呢

也不是一点办法都没有,具体办法如下:

内存 , 最快(领域对象的真实体就在这里)

瞬态数据库,要求写的快,容量可以很小,这个数据库写一定要快,然后就是在特定时刻清空这个数据库。这个数据库可以只保存 “一瞬间那个点的数据”

最终数据库 ,可以不是很快。

具体操作如下:

Repository.create 时,内部先要写入临时数据库,然后在构建成“内存真实体”,然后会异步更新最终数据库。

当机之后,可以启动机器时用缓冲数据库更新最终数据库。

简单的说就是 , 在创建、更改领域对象时,先更改瞬态数据库,然后在更改领域对象的数据库,最后再更改最终数据库。

关键点:就是这个瞬态数据库,要足够足够快,我觉得应该是单独的服务器,并且是与domain层主机放在一起局域内的。挑选写的最快的数据库,具体根据自己需求来。


[该贴被brighthas于2013-03-05 11:46修改过]

2013-03-05 11:28 "@jongh
"的内容
关于中间当机的问题,对于没有办法玩分布和EJB的项目是否就没有100%的保障呢 ...

Event Sourcing,刚接受到用户按界面按钮的事件,立即持久化,见下面这张图,事件通过Event Bus保存到数据库,需要时,进行事件回放

推荐看看LMAX架构,这是一个类似股票交易的高频交易系统,不但要性能快,还要可靠性,万一当机,一笔交易丢了怎么办呢?

多谢指教

@banq

这里引入溯源,还有一个问题

面对大批量“事件”的时候,又如何进行一次多条件并排序的查询呢

2013-03-06 08:57 "@tbyes
"的内容
面对大批量“事件”的时候,又如何进行一次多条件并排序的查询呢 ...

事件不同于一般数据,事件作为数据存储,只是用来追溯,实现事务,所有数据查询分析还都是针对事件改变的状态。

2013-03-06 09:06 "@banq
"的内容
所有数据查询分析还都是针对事件改变的状态。 ...

您是说,像数据查询分析,另外还有一个数据库么?

见CQRS:

谢了,banq老师,我看的懂了