■命令和查询责任分离 (CQRS) 模式
命令和查询责任分离 (CQRS) 模式分隔数据存储的读取和更新操作 。在应用程序中实现 CQRS 可以最大限度地提高其性能、可扩展性和安全性 。迁移到 CQRS 创建的灵活性使系统能够随着时间的推移更好地发展 , 并防止更新命令在域级别引发合并冲突 。
问题
在传统的体系结构中 , 使用同一数据模型查询和更新数据库 。这十分简单 , 非常适用于基本的 CRUD 操作 。但是 , 在更复杂的应用程序中 , 此方法会变得难以操作 。例如 , 在读取方面 , 应用程序可能执行大量不同的查询 , 返回具有不同形状的数据传输对象 (DTO) 。对象映射可能会变得复杂 。在写入方面 , 模型可能实施复杂验证和业务逻辑 。结果 , 模型执行太多操作 , 过度复杂 。
读写工作负载通常是不对称的 , 具有非常不同的性能和规模要求 。
文章图片
文章图片
数据的读写表示形式之间通常不匹配 , 例如必须正确更新的其他列或属性 , 即使这些列在操作的一部分不需要 。当在同一组数据上并行执行操作时 , 可能会发生数据争用 。由于数据存储和数据访问层的加载以及检索信息所需的查询的复杂性 , 传统方法可能会对性能产生负面影响 。管理安全性和权限可能会变得复杂 , 因为每个实体都受读取和写入操作的约束 , 这可能会在错误的上下文中公开数据 。
CQRS 将读取和写入分离到不同的模型中 , 使用 命令更新 数据 , 查询用于读取数据 。命令应基于任务 , 而非以数据为中心 。("预订酒店客房" , 而不是"将预订状态设置为保留") 。命令可以放置在队列中进行异步处理 , 而不是同步处理 。查询从不修改数据库 。查询返回的 DTO 不封装任何域知识 。
然后可以隔离模型 , 如下图所示 , 尽管这不是绝对要求 。
文章图片
文章图片
具有单独的查询和更新模型可简化设计和实现 。但是 , 一个缺点是 CQRS 代码不能使用基架机制(如 O/RM 工具)从数据库架构自动生成 。
为更好地实现隔离 , 可将读取数据与写入数据通过物理方式分离 。在此情况下 , 读取数据库可使用自己的已针对查询进行优化的数据架构 。例如 , 它可以存储数据的具体化视图 , 从而避免复杂联接或复杂 O/RM 映射 。它甚至可能使用不同类型的数据存储 。例如 , 写入数据库可能是关系数据库 , 而读取数据库是文档数据库 。
如果使用单独的读写数据库 , 则必须保持同步 。通常 , 每当编写模型更新数据库时 , 都会发布事件 , 从而完成这一目的 。必须在一个事务中更新数据库和发布事件 。
文章图片
文章图片
读取存储可以是写入存储的只读副本 , 或者读取和写入存储可以具有完全不同的结构 。使用多个只读副本可以提高查询性能 , 尤其是在只读副本位于应用程序实例附近的分布式方案中 。
读取和写入存储的分离还允许彼此适当地缩放以匹配负载 。例如 , 读取存储通常会遇到高于写入存储的负载 。
某些 CQRS 实现使用事件溯源模式 。在此模式中 , 应用程序状态存储为事件序列 。每个事件表示对数据所作的一系列更改 。通过重播事件构造当前状态 。在 CQRS 上下文中 , 事件溯源的一个好处是 , 可以使用相同的事件通知其他组件 — 特别是通知读模型 。读模型使用事件创建当前状态的快照 , 这对查询而言更高效 。但是 , 事件溯源增加了设计的复杂度 。
推荐阅读
- |为什么使用B+Tree?
- 滴滴|滴滴程维:扫描安全风险,责任落实到人,真正做到警钟长鸣
- 行程通信大数据行程卡累计查询超12亿次,UCloud优刻得提供云技术支持
- 五分钟法商学院|未年检机动车转让后发生交通事故,应由谁承担赔偿责任?
- Excel函数与VBA实例|向左查询只会vlookup函数就out了,这两组函数公式效率更高
- 工商|工商注册查询步骤有哪些?
- 何鸿燊何鸿燊逝世享年98岁 家人称继续完成父亲惠泽社会的责任
- []抖音小店订单物流轨迹如何查询?
- zol中关村在线不支持局域网?命令与征服:重制版将上线
- 社会责任支付宝社会责任报告:危中寻机100天 中国率先迈入数字生活时代