命令查询职责分离 CQRS

CQRS(Command Query Responsibility Segregation,命令查询职责分离)是一种在复杂业务系统中常用的架构模式,其核心思想是将“读操作”(Query)和“写操作”(Command)进行职责分离,从而提升系统的可维护性、扩展性和性能。

  • 命令(Command):负责处理数据的更新操作(如创建、修改、删除),通常涉及业务逻辑和事务管理。
  • 查询(Query):仅用于读取数据,专注于高效的数据检索和展示,不包含业务逻辑。

1 具体示例

命令模型:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// 1. 定义命令类
public class CreateOrderCommand {
    private String orderId;
    private String productId;
    private int quantity;

    // 构造函数、Getter/Setter
}

// 2. 命令处理服务
@Service
public class OrderCommandService {
    @Autowired
    private OrderRepository orderRepository;
    @Autowired
    private InventoryRepository inventoryRepository;
    @Autowired
    private EventPublisher eventPublisher;

    public void handleCreateOrder(CreateOrderCommand command) {
        // 1. 创建订单
        Order order = new Order(command.getOrderId(), command.getProductId(), command.getQuantity());
        order.setStatus("Pending");
        orderRepository.save(order);

        // 2. 扣减库存
        Inventory inventory = inventoryRepository.findByProductId(command.getProductId());
        inventory.deduct(command.getQuantity());
        inventoryRepository.save(inventory);

        // 3. 发布事件
        eventPublisher.publish(new OrderCreatedEvent(command.getOrderId(), command.getProductId(), command.getQuantity()));
    }
}

事件模型(Event Model)

1
2
3
4
5
6
7
8
// 领域事件:订单创建事件
public class OrderCreatedEvent {
    private String orderId;
    private String productId;
    private int quantity;

    // 构造函数、Getter/Setter
}

查询模型(Query Model)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// 1. 查询服务接口
public interface OrderQueryService {
    OrderView getOrderStatus(String orderId);
}

// 2. 查询视图类(订单状态缓存)
public class OrderView {
    private String orderId;
    private String status;
    private LocalDateTime createdAt;

    // Getter/Setter
}

// 3. 查询服务实现
@Service
public class OrderQueryServiceImpl implements OrderQueryService {
    @Autowired
    private RedisTemplate<String, OrderView> redisTemplate;

    @Override
    public OrderView getOrderStatus(String orderId) {
        return redisTemplate.opsForValue().get("order:" + orderId);
    }

    // 订阅事件并更新缓存
    @EventListener
    public void onOrderCreated(OrderCreatedEvent event) {
        OrderView orderView = new OrderView();
        orderView.setOrderId(event.getOrderId());
        orderView.setStatus("Pending");
        orderView.setCreatedAt(LocalDateTime.now());
        redisTemplate.opsForValue().set("order:" + event.getOrderId(), orderView);
    }
}

事件总线(Event Bus)

1
2
3
4
5
6
7
8
9
// 简化的事件发布接口
public interface EventPublisher {
    void publish(Event event);
}

// 简化的事件监听接口
public interface EventListener {
    void onEvent(Event event);
}

1.1.1 工作流程

  1. 用户下单
    • 客户端调用命令服务 OrderCommandService.handleCreateOrder()
    • 命令服务创建订单并扣减库存,发布 OrderCreatedEvent
  2. 更新查询视图
    • 查询服务 OrderQueryServiceImpl 监听到 OrderCreatedEvent
    • 将订单状态缓存到 Redis,生成 OrderView
  3. 查询订单状态
    • 客户端调用查询服务 OrderQueryService.getOrderStatus()
    • 查询服务从 Redis 快速返回订单状态。