当eventSourceing遇到并发和事务将变得复杂

11-11-04 gamex
据个例子:有个 仓库 共享对象

仓库『

events

addEvent

A 线程 处理一个事务(里面会用到仓库对象)如果失败需要回滚 如果成功store event to disk

b 线程 处理一个事务(里面也会用到仓库对象)如果失败需要回滚 如果成功store event to disk

这时候如果操作event是顺序存入共享对象的events队列里,那问题将更加的复杂,例如:假设存入在event队列里面的顺序如下

A线程的 event1

B线程的 event3

A线程的 event4

B线程的 event5

这时候A 线程的事务是成功的他需要commint 并 store event 到磁盘

可B线程事务这个时候失败了,这时候事情将变的复杂话。

所以你就会发现这种设计最理想的是single-write规则,假如想多加入处理器的话,共享事件队列将会让问题变得很复杂。

              

10
SpeedVan
2011-11-04 17:44
A做A的,B做B的,哪里复杂了?

1、事件本身就是相互独立的。

2、使用事务不是很适合逻辑的,因为逻辑是不讲究过程的,而回滚正是针对过程而存在。

3、多处理器不是问题,关键是处理的设计,可以看看下面的对比(event2在event1之后处理):

1)event1进入队列后,把event2放入队列;(计划任务)

2)event1进入队列后,待event1执行后才放入event2;(一件事完了才会有第二件事)

这里可以看出,不是队列很复杂,而是我们想得太简单了,发散一下思维,不要被原来理所当然的队列约束。

gamex
2011-11-04 22:04
2011年11月04日 17:44 "@SpeedVan"的内容
A做A的,B做B的,哪里复杂了?

1、事件本身就是相互独立的。

2、使用事务不是很适合逻辑的,因为逻辑是不讲究过程的,而回滚正是针对过程而存在。

3、多处理器不是问题,关键是处理的设计,可以看看下面的对比(event2在event1之后处 ...

还是不是很明白 ,event1处理完了,event2才开始处理这个是肯定毋庸置疑的(这是针对单对象),但是我们的事务不是只针对一个对象做一件事,扣完仓库还要去做别的也许是根据当前库存去做校验公式计算,在把计算结果保存到另一个对象(但是如果在计算另一个对象的时候出错,扣掉的库存该如何处理?)。

gamex
2011-11-04 22:11
2011年11月04日 22:04 "@gamex"的内容
1)event1进入队列后,把event2放入队列;(计划任务)

2)event1进入队列后,待event1执行后才放入event2;(一件事完了才会有第二件事)

...

你说的是不是大事件,例如:转账就是个大事件,然后排队处理?

banq
2011-11-05 07:50
2011年11月04日 22:11 "@gamex"的内容
A 线程 处理一个事务(里面会用到仓库对象)如果失败需要回滚 如果成功store event to disk ...

这里假设前提需要事务,然后再用Event Sourcing,这实际是矛盾的,因为事务是串行,事件是并行的,两者本质上是矛盾的,水和火。

在实际上,我们是缩小需要使用事务的范围,绝不将事务和并发混合。这样才能提供整体性能。

如果实际中有这种极端的实例,可以通过避免在一个内存中的这种线程Queue模式,转化为JMS的分布式事务来实现。也就是说,如果有楼主这个需求,又要求使用事件,又要求事务安全,那么不要使用线程来做,而是利用Disruptor这样Queue机制转发到JMS中,使用JMS这种异步的分布式事务来实现即可。

见这个讨论:事件与事务

[该贴被banq于2011-11-05 08:04修改过]

猜你喜欢
8Go 1 2 3 4 ... 8 下一页