命令查询职责分离 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 快速返回订单状态。