前言
最近在为自己想做的一个微服务系统thing on map做准备,考虑项目读的需求远大于写,所以一路查资料,就查到了CQRS这个设计。
主要参考资料
CQRS pattern
SpringBoot+CQRS微服务设计模式教程
CQRS是什么
一种对数据读写分离的架构模式。即command和queries(或称作read和update)拆分,提升可拓展性,提升读的性能。通俗来说,就是读写分离成两个系统,根据每个系统的特点为其量身定做。
以下文字引自微软文档:
The CQRS pattern is often used along with the Event Sourcing pattern. CQRS-based systems use separate read and write data models, each tailored to relevant tasks and often located in physically separate stores. When used with the Event Sourcing pattern, the store of events is the write model, and is the official source of information. The read model of a CQRS-based system provides materialized views of the data, typically as highly denormalized views. These views are tailored to the interfaces and display requirements of the application, which helps to maximize both display and query performance.
适用/不适用场景
世上没有万能解决方案,只有尽可能合适的。
首先,如果系统简单——业务,模型等方面,常规CURD就可以满足需求,那没必要为一双小脚套上大号鞋子。解耦增加了设计上的复杂度,对团队人员的素质要求也更高!
适用场景有:
团队人数够,可以分成command和queries两团队。
系统读数据的需求远远大于写数据的需求。
写业务复杂,通常操作多个实体,基于任务性,还有一致性要求等。(如转账)
特点
传统模型是这样的:
所有的读/写请求都落在同一个web实例中且读写都访问同一个数据库,这种架构的缺点有:
1、读的需求远大于写时,系统扩展性问题。
2、读时复杂的sql造成的性能问题(是不是select总使用join?每多一个join就是多一层笛卡尔积,怕不怕)。
3、读写各自的其他需求不一致而不得不增加系统复杂度(如:权限校验,数据校验,数据响应,业务等)。
4、写数据时数据库的锁机制造成的性能问题。(如:Mysql的排他锁,阻塞其他sql)
既然它们两这么不合适,于是CQRS模式就将它们给分开,让读-写各管各的。
上图分开了读写数据库,在写库写入时,同时触发同步指令,同步数据至读库。(只保证数据的最终一致性)而读则直接在读库中读。
读库可以自定义scheme(表结构)来减少join及复杂的sql
读库可以采用不同于传统RDBMS的Nosql,提升查询性能,如:mongoDB,Redis等
但是,以上只分开数据库的解决方式并不是完全解耦,上面的缺点1和3问题还是存在,即系统扩展性和读写校验/业务上差异大的问题。
所以彻底的CQRS架构,是面向微服务的,读,写再细化成两个服务(微服务是按模块来划分的,所以是再细化),分成两个项目,既可解决开发中差异造成的复杂度问题,又可以动态扩展。比如:某某节日,写的流量剧增,就可以多开几个写服务。
读服务与写服务可以采用不同的架构及技术(根据项目需求来确定),如:写才用hibernate/jpa,读采用mybatis。
当然,要想要真正理解CQRS,还得多阅读别人的代码,多看书,多实战。
相关书/知识推荐(引自知乎阿莱克西斯):
- Patterns, Principles, and Practices of Domain-Driven Design
- Designing Data-Intensive Applications
- least expressiveness principle
相关联想
DDD(Domain-Driven Design)
Event-Sourcing
微服务
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。