banq
2013-03-17 21:15

2013-03-17 18:54 "@abbasky

"的内容

我认为读和写要整合到一个顺序序列中才能解决读写竞争问题 ...

如果读写整到一起,虽然解决了读写竞争,但是也变成性能瓶颈了,锁模式就是这种解决办法,比如数据库锁或ORM的悲观或乐观锁等。

将”客户端提交数据然后返回结果“这种方式可以看成一种函数调用Lambda架构

“query = function(all data)”

或者说,将客户端提交数据看成是一种写操作,在服务器端对写操作进行切分并行化或异步处理,如下图:

客户端提交了数据给领域模型,模型完成业务后立即将结果返回客户端;同时领域模型将其他处理如数据库存储等通过Disruptor这个并发框架立即开启。

打个比喻,快递送物品过来,你就立即处理一下快递想要的结果,比如签字等等活动,等快递走了,你同时打开包裹,检查商品。这样效率是不是很高?如果你在签字之前,要打开包裹,验机等等一系列操作,快递肯定等不及,不耐烦了,但是你认为这样保险,而快递说有问题可和商城联系,和他们无关。

D D D 缓 存何时持久化,领域模型打发完客户端(快递)请求后,要进行持久化(验机),通过Jdonframework基于事件的模型可以并发立即持久化,这是由Disruptor完成的,持久化动作和签字动作几乎是同时并发发生。

实现无锁异步的事件编程的好处,原先有三个操作在一个方法中顺序执行,以jivejdon论坛发帖为例:

A. 插入新贴数据库

B. 加入Lucene搜索

C. 通知关注作者的所有订阅者更新信息

这就容易碰到问题,B动作因为是加入搜索文件还要优化索引,比较费CPU,当发帖作者关注人数很多时,能几百个几千条数据要插入数据库。这些因素合并在一起,致使发一次贴,CPU负载相当高,甚至影响正常功能,比如发完新贴,理应给发贴者显示一下其发帖的新内容,结果因为CPU忙于B和C两个操作,无法显示发帖内容了,有些系统甚至出现Session丢失,连接拒绝等等问题。

而引入事件编程后,我们有两种手段来对付,并发和异步,如下处理:

A.通过无锁并发,让另外一个线程插入数据库。

B.让另外一个线程延时60秒插入搜索索引

C.加入一个队列定时器,两分钟以后每隔5分钟向成百上千订阅者发布通知,包括邮件 微博通知等等。这个队列大小可根据服务器硬件配置设置一定大小,硬件弱的,队列小些。这样还可以缓冲短时间大量发帖(写操作)引起的对系统冲击。

关键是,因为A B C三个动作我们是在EventHandler事件处理器中实现,那么进行这些重构,丝毫不会影响触发事件那一端的代码,两者松耦合,修改相当轻松,几分钟完成。

具体代码可见:

Jdon框架+Guava的EventBus实现

[该贴被banq于2013-03-26 17:30修改过]

abbasky
2013-03-21 22:03

首先感谢banq的帮助。

你在文中提到的解决方案都是针对写数据。如果出现查询数据与写数据的并发。那会不会出现死锁,或数据不正确的情况?

banq
2013-03-22 08:18

2013-03-21 22:03 "@abbasky

"的内容

如果出现查询数据与写数据的并发。那会不会出现死锁,或数据不正确的情况? ...

出现这个情况还是锁模式下,在读写分离的CQRS模式根本不存在,首先,操作者发出写操作命令,修改的是内存中模型,返回结果也是模型的结果,所以他能够立即查询到自己的修改结果。

如果是单机,其他用户查询也是内存中这个模型,如果担心内存中这个模型修改时有查询会出现不一致,前面讲的布谷鸟算法就是应对这种情况的无锁算法,有简单并发锁的比如JDK的的ReadWriteLock都支持。

因为读写分离,可以针对读优化,有很多台服务器专门读,分布式读取,那么一台服务器上模型在写操作中被修改后,通过发出事件消息可以改变其他读服务器上数据,达到最终一致。

banq
2013-04-09 19:27

jdon框架支持并发异步等概念,能够根据服务器自身处理量,动态调节并发量,如果服务器比较弱,可以删除或延时一些细枝末节的处理。

Jdon框架让延迟和吞吐量之间有一个自主选择,而这些概念传统的JavaEE如EJB/Spring根据就没有。

推荐一篇文章:构建可伸缩系统 Scala vs Java,JdonFramework其实类似这个案例中的Scala,虽然文章作者倾向于Scala,但是使用Jdon框架完全可以做到Scala这种吞吐量等三个指标的平衡。

该文章作者是用Jmeter进行测试,Jdon框架也是使用Jmeter测试了两个写场景和多个读场景,可以与其index payments和search比较。

普通Java的测试图:

由于搜索请求耗费CPU,同时拖累了Index等其他查询,搜索请求实际在独占CPU,同时搜索自己的吞吐量也大幅度缩小,意味着程序中可能有同步锁(当然,我没有看源码,只是凭以往经验)。

下面是Scala的测试图:

在Scala中,Median 和90%line和吞吐量三个指标在三个模块中都没有因为搜索请求处理而影响,文章归结于异步因素,这也是我认同的。

当然文章也不否认Java能够做到,关键是否优雅地做到,而Jdonframework则依靠DDD+ EventSourcing +CQRS不但可以优雅做大,而且性能吞吐量等三个指标因为Jdon框架的异步同样不受影响,下图是Jdon框架Jmeter的测试结果,当然没有转换成文章中竖条图,从Median 90%line和吞吐量三个指标值可以看出:

我也不想好事,所以也就不想针对该文章案例用Jdonframework做一个案例,再PK一下,从道理上了然即可。

英文:Scalable scala vs java

bingyang
2013-07-11 09:26

祝贺了;

CRQS越来越来流行,bang 你的jdonframework 是不是可以克隆个非java的版本,比如.net,让更多人学到这个技术,呵呵;