非常认同banq老师。what和how分离是非常重要。只有搞清楚了what,模块和模块之间才能更加程度的松耦合,目前我现在的项目,通过DDD进行建模,模型和底层hbase的存储可以说是完全不匹配的。举个例子,如何使用hbase来设计类似jdon顶的功能。如果要实现记录哪些人顶了某个帖子的话,就需要记录每一次每个人的顶操作,这样某个帖子被顶的次数就可以后台查询来完成。而查询的时候,我们还可以设置缓存。
目前我自己的项目采用了DDD和CQRS架构,同时我还结合了EDA架构,因此我觉得领域模型都是只写的,每一次写操作都会触发一个事件,这个事件根据系统启动的时候注册的事件处理来处理,运行的时候,我们还可以手动替换某一个事件处理器为null even processor,这样就会在运行时停止某一项功能来对某个功能进行升级和维护而不会影响到其它的功能。因此我觉得把不同的事件分开出来,不同的一组事件代表不同的功能,而事件处理器都是有针对性的,这就使得功能和功能之间松耦合,不会因为某个功能的压力过大,而导致整个系统都受到影响。并且目前我不会因为界面上显示一些内容,就将这些内容放入实体中,相反的界面上面显示的东西都是通过查询获取的,而查询的时候,我们可以定制化的来设置缓存。
目前我在使用HBASE的过程中,发现基于列存储的好处,以前基于RDBMS,一个实体的属性往往是很多的,而界面上往往不可能一次都显示所有的属性,因此采用RDBMS查询的时候,就会遇到一些不用到的属性都被查询出来的情况,而且因为是所有的属性都是在一行中,这样当有并发更新的时候就会用锁来实现共享数据的一致性。而目前列存储系统,一个具有丰富行为的实体,它的属性可以被保存到hbase的一张表,或者多张表中,况且根据属性之间关联程度,将关联程度高的属性统一到同一个cloumn family中,这样查询的时候就可以将关联度高的属性一次性查询出来。
同样我也发现了另外一个问题,为什么说hbase的并发读写效率非常高,是因为他们是弱事务的,如果用同样的row key并发更新一行,那么写入的效率也是很低的,之所以能并发写入,是因为并发写入到不同的行,不同的column family,这样因为不同的column family是单独存储的,这样也就不会因为锁而牺牲了并发性。
ps:最近我在寻找一个高性能的MQ来做异步事件处理的时候,发现了kestrel,此MQ是用Scala实现的,twitter就用了它,目前我也正在考虑将其纳入自己的项目中来,不知道其它兄弟是否有使用经验。