• 作者:老汪软件技巧
  • 发表时间:2024-09-28 21:01
  • 浏览量:

文章内容收录到个人网站,方便阅读:/

文章内容收录到个人网站,方便阅读:/

文章内容收录到个人网站,方便阅读:/

CQRS叫命令查询职责分离,事实上就是读写分离的意思。

CQRS指的读写分离是指在应用程序内部的代码级别的读写分离。

在本文中,我将对此做出详细解释。

CQS思想

CQS:命令和查询分离:Command and Query Segregation。

其核心思想是在任何一个对象的方法可以划分为两类:

CQRS模式的核心设计理念来自于一条设计原则,即单一职责原则。

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

private int data = 0;
private int update(int value) {
    data += value;
    return data;
}

上述方法既改变了数据,又返回了数据状态。

如果按照CQS的思想,则该方法可以拆成Command和Query两部分,如下:

private void update(int value) {
    data += value;
}
private int query() {
    return data;
}

对于命令侧是否返回数据实际业务诉求中并不一定能够完全统一。

比如:

基本原则

CQS的主要原则是:

CQRS架构

架构分析的两种方法_架构设计模型_

Command and Query Responsibility Segregation

架构思想:

CQRS将系统的读操作和写操作分离到不同的模型中:

查询模型(Query Model):

这种分离可以通过不同的数据模型、数据库甚至服务来实现,从而优化读写性能和可伸缩性。

CQRS 模式的应用非常简单,如下图所示:

假设服务为 UserService,在非CQRS模式下同时包含了查询和更新服务接口。

public class UserService {
   //  根据id查询用户
    UserId getUserId(int userId);
    // 更新用户
    void updateUser(User user);
}

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

/**
   命令服务
*/
public class UserCommandService {
    void updateUser(UserCommand command);
}
/**
   查询服务
*/
public class UserQueryService{
    User getUserById(int userId);
}

最终一致性

采用CQRS后,查询和命令两侧通常会采用独立的数据模型。

在这种架构模式下,命令侧的数据变化后及时同步(事件、消息队列)到查询侧,两侧数据并非实时。

最后总结

CQRS的使用者可以根据实际情况,将读写分离开单独部署,然后引入领域事件,使用消息队列做通信。

读写分离部署+消息通信:

《重构:改善既有代码的设计》的作者也提醒要小心使用CQRS,不推荐将CQRS复杂化处理。

参考资料: