CQRS和事件溯源在C++中的应用:复杂系统的架构

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

当常规CRUD失效时:在C++中认识CQRS和事件溯源



您是否遇到过这样的情况:您的C++程序在测试数据上运行良好,但在生产环境中却开始“卡顿”?或者当业务分析师要求查看变更历史时,您却只有最新状态?熟悉吗?那么欢迎来到CQRS(命令查询职责分离)和事件溯源的世界。



这两种模式不仅仅是微服务世界中的流行词汇。它们是强大的工具,能够帮助您构建可扩展、可审计且灵活的系统。是的,它们非常适合C++——一种对性能和内存控制至关重要的语言。



在本文中,我们不会进行枯燥的讲解。我们将探讨如何在纯C++中实现CQRS和事件溯源,无需框架的魔法,并提供真实示例和可直接使用的模板。



CQRS:分离读写操作



在经典的CRUD(创建、读取、更新、删除)架构中,我们使用相同的模型进行读写操作。这在系统规模不大时很方便。但当出现以下情况时,问题就来了:



  • 内存中的对象过于复杂,无法快速序列化以供读取。
  • 写入业务逻辑需要验证,从而拖慢读取速度。
  • 系统的不同部分希望以不同方式查看相同的数据。


CQRS 提出了一个简单而巧妙的解决方案:将模型分为两部分——Command(命令)用于更改状态,Query(查询)用于读取。它们可以使用不同的存储、不同的数据结构,甚至可以在不同的机器上实现。



C++中CQRS的基本实现



让我们从简单的开始。假设我们正在编写一个订单管理系统。我们不再将所有内容存储在一个Order类中,而是分离职责。



首先,定义命令和查询的接口:



#include <memory>#include <vector>#include <string>

// 所有命令的基类class Command {public: virtual ~Command() = default; virtual void execute() = 0;};

// 所有查询的基类template <typename TResult>class Query {public: virtual ~Query() = default; virtual TResult execute() = 0;};


现在,创建一个具体的命令来向订单添加商品:



class AddItemCommand : public Command {private:    std::string orderId_;    std::string productId_;    int quantity_;    // 对存储库(或命令总线)的引用    OrderRepository& repository_;

public: AddItemCommand(const std::string& orderId, const std::string& productId, int quantity, OrderRepository& repo) : orderId_(orderId), productId_(productId), quantity_(quantity), repository_(repo) {}

void execute() override { // 业务逻辑:检查商品是否有库存 if (quantity_ <= 0) { throw std::invalid_argument("数量必须为正数"); } // 调用领域服务或聚合 auto& order = repository_.getById(orderId_); order.addItem(productId_, quantity_); repository_.save(order); }};


而查询订单摘要的方式如下:



class OrderSummaryQuery : public Query<OrderSummary> {private:    std::string orderId_;    ReadModelDatabase& db_;

public: OrderSummaryQuery(const std::string& orderId, ReadModelDatabase& db) : orderId_(orderId), db_(db) {}

OrderSummary execute() override { // 从优化的读取数据库中读取 return db_.getOrderSummary(ord

博客

书籍推荐