凯发app官方网站-凯发k8官网下载客户端中心 | | 凯发app官方网站-凯发k8官网下载客户端中心
  • 博客访问: 85520
  • 博文数量: 165
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1655
  • 用 户 组: 普通用户
  • 注册时间: 2022-09-26 14:37
文章分类

全部博文(165)

文章存档

2024年(2)

2023年(95)

2022年(68)

我的朋友
相关博文
  • ·
  • ·
  • ·
  • ·
  • ·
  • ·
  • ·
  • ·
  • ·
  • ·

分类: 架构设计与优化

2023-01-30 10:14:09

作者:京东科技 倪新明
cqrs只是一种非常简单的模式(pattern),cqrs本身并不是一种架构风格,和{banned}最佳终一致性/消息/读写分离/事件溯源/ddd等没有必然的联系,它{banned}最佳大优势是给我们带来更多的架构属性选择

认知篇:cqrs架构模式的本质-凯发app官方网站

命令和查询分离,command and query segregation,其核心思想是在任何一个对象的方法可以划分为两类

?查询:获取数据,返回查询数据,但不改变数据状态

?命令:改变数据状态,不返回任何数据

基于cqs的思想,任何一个方法都可以拆分为命令和查询两部分:

private int origin = 0; private int add(int value) {
    origin  = value; return origin;
}

上述方法既改变了数据,又返回了数据状态,如果按照cqs的思想,则该方法可以拆成command和query两部分,如下:

private void add(int value) {
    origin  = value;
} private int queryvalue() { return origin;
}

是否严格遵循上述约定存在争议,对于命令侧是否返回数据实际业务诉求中并不一定能够完全统一。比如:

?"出栈" 操作同时改变栈状态和返回数据

?某些业务场景下可能会有返回业务主键的诉求,比如下单操作返回订单号

command and query responsibility segregation,即命令查询职责分离,由greg young提出 。cqrs在cqs基础之上,将分离的级别从代码方法级别扩展到对象级别。cqrs 模式的应用非常简单,如下图所示


假设凯发k8官网下载客户端中心的服务为 orderservice,在非cqrs模式下同时包含了查询和更新服务接口:

public class orderservice { //  根据id查询订单 order getorder(orderid) // 查询已支付订单 list getpayedorders() // 下单 void placeorder(order) // 取消订单 void cancelorder(orderid) 
}

应用cqrs模式之后的orderservice被拆分成了两个接口,分别承担查询和写职责:

/**
命令侧服务
*/ public class orderservice { void placeorder(placeordercommand command) void cancelorder(cancelordercommand command)
} /**
 查询服务
*/ public class orderqueryservice{ order getorder(orderid)
    list getpayedorders()
}

以上这种简单的分离就是cqrs模式的全部了,是不是非常简单?确实,单纯的看,cqrs的确就是这么简单。

cqrs{banned}最佳大优势就是基于这种职责分离能带给我们更多的架构属性选择

?“查询” 和 “命令” 两侧进行独立部署以获取更好的伸缩性

?“查询” 和 “命令” 两侧独立架构设计

?“查询” 和 “命令”两侧进行独立数据模型设计

基于cqrs,我们可以衍生出更多的架构属性,结合实际的业务场景,进行差异化的架构设计。

团队引入cqrs模式之后,往往不仅仅是简单的在类的职责层面对读写进行分离,一般会采用更为复杂的应用架构风格,如下是典型的cqrs架构风格:


?命令侧:命令侧引入命令总线以支持对不同命令的灵活路由;突出领域模型的应用

?查询侧:引入查询总线对查询请求进行路由;请求链路一般直接连接到存储层,实现不同的定制化查询需求

cqrs强调命令和查询的职责分离,但在底层的数据模型层面,cqrs并没有进行强制限定,即采用cqrs模式并没有要求必须要进行数据模型的分离。是否要进行模型分离开发人员需要具体情况具体分析。

?分离模型:查询侧和写侧模型不互相干扰,各自在应用层的实现复杂度比较低。但由于模型的分离,命令侧和查询侧的数据一致性需要纳入考虑范围

?不分离:不需要考虑数据一致性问题,但由于查询侧和写侧对模型的诉求可能不一致,模型的设计往往需要折衷考虑。

cqrs和消息模式没有必然联系,落地cqrs 并不一定需要使用消息模式?


如果我们采用了cqrs模式,但是命令和查询两侧底层所依赖的数据模型并未分离,而是基于共享的数据存储和数据模型,命令和查询之间不需要额外的交互,命令侧的数据更新对查询侧实时可见。在这种架构模式下,两侧基于共享的数据已经天然的集成在一起,不需要额外机制进行通信,自然也无需引入消息了。如果我们采用cqrs模式,并且命令和查询两侧进行了数据模型的分离,二者各自依赖独立的数据模型。同时,数据存储也分开部署。命令侧负责数据的更新,而查询侧只负责数据的查询,如何将数据的更新及时同步到查询侧是需要解决的问题。在这种架构模式下,使用消息模式作为两侧的通信机制是个不错的选择,当然,这并不是唯一的选项。

es 并不是一个新的概念,在{banned}最佳早的金融系统中就已经应用。要了解es,我们需要先看看传统的数据存储。在传统应用中,数据库例如mysql(假设存储介质是数据库,)中存储的始终是数据的{banned}最佳新的状态。例如我们对某条用户的信息进行了多次的修改或编辑,然后保存将数据存储到数据库中。无论何时,数据库中都会记录{banned}最佳后的、{banned}最佳新的用户状态。我们只要根据id或其他信息查询数据库中相应的记录就能获取该用户的{banned}最佳新信息。这是应用中典型的数据存储特点。

当然,我们可以基于特定的数据模型设计以保存数据的更改记录。

这种数据存储模式的特点是简单,不需要额外的维护复杂的设计,我们能够非常容易的获取{banned}最佳新的用户信息。但是不幸的是,我们丢失了历史信息,包括用户的意图信息。而这些信息则有助于我们进行数据回滚、用户行为分析以及开发过程中的调试等等。


在es模式下,数据库中存储的不在是数据{banned}最佳新状态,而是数据的变更记录,更官方的说法是 “事件(event)”。数据库中存储的数据变化的事件流。我们基于事件流可以对{banned}最佳新状态进行重建,同时也可以便捷的重现任何历史节点数据。es需要解决大量事件的存储和高效的实例重建问题,后续单独的文章再介绍es。

{banned}最佳终一致性也常常在服务之间引入,{banned}最佳终一致性的目的是为了提高扩展性和可用性。

cqrs和{banned}最佳终一致性同样没有必然的联系。往往采用cqrs后,查询和命令两侧会采用独立的数据模型,在这种架构模式下,命令侧的数据变化后及时同步到查询侧,两侧数据并非实时,在一定的延时后两侧数据{banned}最佳终达成一致。

cqrs的{banned}最佳大优势在于通过将命令和查询的职责分离,为架构师提供了更多的架构属性选择,我们可以在查询侧和命令侧进行独立的架构设计。对象级别的职责分离就是cqrs的全部了,但在实践中涌现出了很多更为灵活也更为复杂的架构风格,比如总线的引入、数据模型的分离、一致性报这个策略、事件溯源等等。额外的组件或技术的引入必然导致复杂性和成本上升,这些选型的采纳需要团队的权衡。

阅读(207) | 评论(0) | 转发(0) |
0

上一篇:

下一篇:trie树简介及应用

给主人留下些什么吧!~~
")); function link(t){ var href= $(t).attr('href'); href ="?url=" encodeuricomponent(location.href); $(t).attr('href',href); //setcookie("returnouturl", location.href, 60, "/"); }
网站地图