NoSQL数据库大比拼: Cassandra, HBase, MongoDB, Riak的测试结果可以得出:根据不同的应用特点选择不同的NoSQL,没有万能的NoSQL数据库。
主要选择依据是读写比例,但是这个读写比例操作起来有难度,很多时候只有等到系统完成上线运行后才能知道这个读写比例。但是这时更换数据库相当于更换底层设施,不亚于在新马路上打洞。
有没有在写代码前完成正确的选型呢?
使用CQRS架构。
CQRS也是一种读写分离的架构,写的操作是命令,读的操作是查询,写和读是两条路线,很显然,写路线的存储采取写能力特别快的NoSQL如HBase或Cassandra;而读路线采取读能力比较快,比如Sharded MySQL或MongoDB。
关键是两者同步,结合Event Sourcing,写路线存储的应该是写事件,那么通过一个定时Job,不断从写存储数据库中读取写事件,通过逻辑播放,将结果再写入读数据库中即可。当然逻辑播放是一种批处理机制。如下图:
可参考NOSQL存储的基于事件的事务实现:
在这种情况下,由此诞生了相对于ORM的一种新的持久化方式:面向事件数据库Event Oriented Databases,文章
Event Oriented Databases : a New Kind of Persistence Paradigm对此进行详细描述。
文章首先对描述事实的数据进行了定义:
数据是一种概念的关系和其度量measure,度量主要由一种类型组成:量化特性,比如重量 总数和年龄,以及定性描述,名称 城市和日期。几种数据的在结构上组合形成了事实的描述。
例如:用户浏览电子商务网站并与它进行交互:她增加了一些商品到购物车,并去除了其中一些商品,最后当她已经完成了购买,进行订单验证,并随后支付。每个用户的操作是由系统处理。系统必须保证用户操作的ACID属性:原子性,一致性,完整性和耐用性。
关于最后一点,耐用性,是必不可少的环节,但是在非常复杂的情况下又会失败。耐用性是通过冗余机制实现的,比如持久化写磁盘等,以防止电子设备掉电。
这个案例中有两个视角:
1. 从购物车的这个视角看: 它跟随用户的动作改变(add a product, remove one, modify its quantity, recalculate the balance, etc.). 购物车总是处于一致的状态:带有总数的商品列表,总金额等(不能增加商品,总数和总金额不变,就破坏了购物车自身的一致性)。从这点来看,这个视角根据类似OO范式中“对象和状态”视角。
2. 如果从用户的视角看:用户发生了一系列动作(add, remove, change quantity, etc.). 当然,每个动作都会被购物车接受,产生了购物车的状态变化。这个视角更加面向函数FP一些。事件触发函数,函数改变了状态。事件是一种确定性的 可定义的 具有不变性的定义,这非常类似FP范式中的 « function » 视角。
待续..