当前位置:首页 > 科技  > 软件

从CRUD到CQRS:使用Spring微服务转变你的架构策略

来源: 责编: 时间:2023-10-16 17:10:05 348观看
导读介绍微服务的兴起以及现代软件架构对可扩展性、灵活性和可维护性的需求,促使开发者采用各种设计模式。近年来,命令查询责任分离(Command Query Responsibility Segregation,CQRS)模式在实践中获得大量推广。CQRS特别适用于

介绍

iCW28资讯网——每日最新资讯28at.com

微服务的兴起以及现代软件架构对可扩展性、灵活性和可维护性的需求,促使开发者采用各种设计模式。近年来,命令查询责任分离(Command Query Responsibility Segregation,CQRS)模式在实践中获得大量推广。CQRS特别适用于那些命令(用于修改状态)和查询(用于读取状态)之间存在明显区别的系统。本文将深入探讨CQRS,并演示如何使用Spring微服务进行实现。iCW28资讯网——每日最新资讯28at.com

什么是 CQRS?

命令查询职责分离(CQRS)是一种架构模式,建议将数据修改操作(命令)与数据检索操作(查询)分离。这种分离允许为查询和更新数据开发专门的模型,提高应用程序的清晰度和可扩展性。iCW28资讯网——每日最新资讯28at.com

CQRS 的核心目标是通过确保每个任务负责单个操作(命令或查询,但绝不会同时负责两者)来简化任务。iCW28资讯网——每日最新资讯28at.com

起源和演进

CQRS并不是一个全新的概念。它的根源可以追溯到CQS(Command Query Separation,命令查询分离)原则,该原则由Eiffel编程语言的创建者Bertrand Meyer推广。尽管CQS主要关注方法层面,即一个方法应该执行命令或回答查询,但CQRS将这一原则扩展到了应用程序的架构层面,建议使用独立的架构组件处理命令和查询。iCW28资讯网——每日最新资讯28at.com

为什么使用CQRS?

  • 可扩展性:CQRS允许水平扩展,可以根据需求部署多个命令或查询服务的实例。读操作和写操作可以独立进行扩展,优化资源利用率。
  • 灵活性:命令和查询之间职责明确,意味着开发者可以针对每个操作使用最适合的持久化机制、策略和优化方式。例如,虽然关系数据库可能用于事务性命令操作,但非规范化的视图存储甚至全文搜索引擎可以用于处理查询。
  • 可维护性:良好实现的CQRS模式简化了代码库。通过为读操作和写操作分别建立模型,开发者可以专注于每个操作的具体内容,而不会被无关的问题分散注意力。这种分离有利于开发出更清晰、更易于维护和扩展的代码。
  • 增强安全性:CQRS本质上促进了更好的安全实践。通过分离命令和查询操作,可以更容易地对写操作进行严格的验证和授权检查,同时优化读操作以提高性能。

CQRS在微服务中的应用

在分布式系统中,服务通常需要具有自治性和高度解耦,CQRS提供了一个清晰的路径。每个微服务都可以采用CQRS模式,确保它处理命令和查询的内部细节与其他服务分离。这也与领域驱动设计(DDD)非常契合,其中领域事件可以触发不同微服务中的命令操作。iCW28资讯网——每日最新资讯28at.com

潜在的问题

尽管CQRS带来了许多好处,但也存在一些挑战:iCW28资讯网——每日最新资讯28at.com

  • 复杂性增加:引入CQRS可能会增加开销,特别是在读操作和写操作之间的区别不明显的系统中。并不总是需要将每个读操作和写操作分离,这样做可能会导致不必要的复杂性增加。
  • 一致性:考虑到写存储和读存储可能是不同的,确保它们之间的数据一致性可能具有挑战性,特别是在分布式系统中。

使用Spring微服务实现CQRS

Spring生态系统中丰富的工具和框架非常适合在微服务环境中实现CQRS模式。iCW28资讯网——每日最新资讯28at.com

新建一个Spring Boot项目

第一步是创建一个基本的Spring Boot项目。如果你是第一次使用Spring Boot,可以使用Spring Initializr初始化项目。可以根据自己偏好引入一些必需的依赖项包括Spring Web、Spring Data JPA、数据库连接器等。iCW28资讯网——每日最新资讯28at.com

命令、命令处理器和聚合

在基于Spring的CQRS系统中,命令表示改变某个状态的意图,而命令处理器则用于处理这些命令。iCW28资讯网——每日最新资讯28at.com

命令示例如下:iCW28资讯网——每日最新资讯28at.com

public class CreateUserCommand {    private final String userId;    private final String username;    // 构造函数, getters,以及其他方法...}

对于每个命令,都需要定义了相应的命令处理器。该处理器需要包含处理命令的实际逻辑,如下:iCW28资讯网——每日最新资讯28at.com

@Servicepublic class CreateUserCommandHandler implements CommandHandler<CreateUserCommand> {        @Autowired    private UserRepository userRepository;    @Override    public void handle(CreateUserCommand command) {        User user = new User(command.getUserId(), command.getUsername());        userRepository.save(user);    }}

在领域驱动设计(DDD)的上下文中,状态变更通常发生在聚合根上。这些聚合根需要遵循所有领域规则,然后在对数据变更进行持久化。iCW28资讯网——每日最新资讯28at.com

查询和查询处理器

类似地,查询表示读取某些状态的请求,而查询处理器则处理这些请求。iCW28资讯网——每日最新资讯28at.com

查询命令示例:iCW28资讯网——每日最新资讯28at.com

public class GetUserByIdQuery {    private final String userId;    // 构造函数, getters, 以及其他方法}

对应的查询处理器:iCW28资讯网——每日最新资讯28at.com

@Servicepublic class GetUserByIdQueryHandler implements QueryHandler<GetUserByIdQuery, User> {        @Autowired    private UserRepository userRepository;    @Override    public User handle(GetUserByIdQuery query) {        return userRepository.findById(query.getUserId()).orElse(null);    }}

事件溯源及Axon框架集成

尽管CQRS提供了分离的机制,但使用事件溯源可以简化在命令和查询之间维护状态的过程。Axon Framework是一个实现了CQRS和事件溯源的流行框架。iCW28资讯网——每日最新资讯28at.com

在Axon中,事件在命令处理后进行发布。这些事件可以被持久化,然后用于重新创建聚合根的状态,有助于保持查询端与命令端的同步。iCW28资讯网——每日最新资讯28at.com

使用Apache Kafka进行异步通信

考虑到微服务的分布式特性,实现服务之间的异步通信是非常有必要的。可以将Apache Kafka集成到Spring生态系统中,以实现强大的事件驱动架构,这在CQRS设置中尤其有用。iCW28资讯网——每日最新资讯28at.com

由命令端产生的事件可以推送到Kafka的主题中,查询端可以消费这些事件来更新自己的数据存储。这确保了命令端和查询端之间的解耦,使系统更具弹性和可扩展性。iCW28资讯网——每日最新资讯28at.com

事件溯源和CQRS

尽管CQRS专注于分离命令和查询的责任,但事件溯源确保将应用程序状态的每次更改捕获在事件对象中,并按照应用顺序存储在相同聚合根上。这样允许你重建过去的状态,在与CQRS结合使用时特别有优势。iCW28资讯网——每日最新资讯28at.com

事件溯源的核心思想

事件溯源是一种将领域事件持久化而不是持久化状态本身的方式。这些事件捕获状态转换。通过重新播放这些事件,可以重建聚合根的当前状态。iCW28资讯网——每日最新资讯28at.com

例如,可以存储银行账户的所有交易(像存款和提款这样的事件),而不是仅存储当前余额。通过重新播放这些事件,可以计算出当前余额。iCW28资讯网——每日最新资讯28at.com

事件溯源的好处

  • 审计追踪:事件溯源提供了自然的更改审计日志,这对于需要追溯性和历史记录的领域非常重要。
  • 时间查询:可以确定系统在任何时间点的状态。这对于调试和理解过去的状态非常有用。
  • 事件重放:通过重新播放事件,可以重新生成面向读取的优化视图。当你想要创建新投影或重建损坏的投影时,这特别有用。

事件溯源与CQRS集成

CQRS和事件溯源是相辅相成的,表现在以下几个方面:iCW28资讯网——每日最新资讯28at.com

  • 解耦:就像CQRS中的命令和查询解耦一样,通过事件溯源,事件(代表状态变化)与实际状态解耦,这促进了松散耦合的架构。
  • 可扩展性:CQRS中读操作和写操作的分离性与事件驱动系统非常契合。命令模型处理命令并生成事件,而查询模型处理查询并可以通过侦听这些事件进行更新。
  • 弹性:通过重播事件,可以在发生故障甚至迁移到全新系统时重新构建系统的状态。

使用Spring和Axon框架实现

正如之前提到的,Axon Framework为在Spring应用程序中实现CQRS和事件溯源提供了一种无缝的方案:iCW28资讯网——每日最新资讯28at.com

  • 聚合根和事件处理:在Axon中,聚合根负责处理命令和生成事件。在处理完命令后,它们会应用导致状态变化的事件。
@Aggregatepublic class Account {    @AggregateIdentifier    private String accountId;    private int balance;    @CommandHandler    public void handle(WithdrawMoneyCommand cmd) {        if (cmd.getAmount() > balance) {            throw new InsufficientFundsException();        }        apply(new MoneyWithdrawnEvent(cmd.getAccountId(), cmd.getAmount()));    }    @EventSourcingHandler    public void on(MoneyWithdrawnEvent evt) {        this.balance -= evt.getAmount();    }}
  • 事件存储:Axon提供了一种存储和检索事件的机制。这些事件可以重播,以重建聚合根的状态。
  • 投影:Axon中的投影提供了CQRS的查询端。它们监听事件并更新读取优化的视图。这样,查询模型始终与最新的更改保持同步。

挑战和考虑因素

尽管CQRS和事件溯源可以带来巨大的好处,但也带来了复杂性。iCW28资讯网——每日最新资讯28at.com

复杂性开销

  • 架构复杂性:CQRS和事件溯源引入了额外的层次和组件到系统中,如事件存储、命令和事件总线以及同步机制。
  • 学习曲线:对于不熟悉这些模式的团队来说,需要一个学习阶段。从传统的基于CRUD的系统转变思维可能是具有挑战性的。

数据一致性

  • 最终一致性:由于命令和查询模型的分隔性质,即时一致性常常被牺牲以换取最终一致性。这意味着在命令端进行的更改在查询端反映出来之前可能会有延迟。
  • 事件顺序:确保事件按照生成的顺序进行处理,特别是在分布式系统中,可能会很棘手,但对于维护一致的状态至关重要。

事件版本控制

随着时间的推移,事件的结构或语义可能会发生变化,从而带来以下挑战:iCW28资讯网——每日最新资讯28at.com

  • 版本不匹配:处理同一事件类型的不同版本可能变得复杂。
  • 事件升级:随着事件的演变,系统必须能够将旧版本的事件升级到新版本,而不修改存储的事件。

数据存储和重放

  • 存储考虑:由于所有事件都被存储,事件存储库可能会迅速增长,导致存储成本增加和潜在的性能问题。
  • 重放持续时间:通过重放大量历史事件来重建系统状态可能耗时很长,影响系统的恢复和初始化时间。

其他系统集成

使用CQRS和事件溯源的系统与不遵循这些模式的外部系统集成可能具有挑战性,特别是在数据同步和事务管理方面。iCW28资讯网——每日最新资讯28at.com

边界确定

  • 粒度决策:决定应用CQRS和事件溯源的粒度非常重要。在微观级别实施可能导致过度复杂化,而过于广泛地实施可能会削弱其好处。
  • 领域复杂性:对于简单的域来说,这些模式可能过于复杂。它们更适用于复杂的领域,其中好处超过了实施和维护成本。

工具和基础设施

虽然有像Axon这样的工具和框架支持CQRS和事件溯源,但它们可能并不完全适合所有场景。可能需要进行定制实现,这可能会增加项目的复杂性和持续时间。iCW28资讯网——每日最新资讯28at.com

结论

CQRS为扩展和组织微服务提供了一种独特的方式。当与Spring生态系统结合使用时,它可以提供一个强大的工具包,用于构建健壮、可扩展和易于维护的系统。然而,就像所有架构决策一样,需要权衡利弊并确保它是否适合你的实际场景。iCW28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-13617-0.html从CRUD到CQRS:使用Spring微服务转变你的架构策略

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 向量化操作简介和Pandas、Numpy示例

下一篇: 掌握这五个要点,利用IntelliJ IDEA进行前端开发

标签:
  • 热门焦点
  • 俄罗斯:将审查iPhone等外国公司设备 保数据安全

    iPhone和特斯拉都属于在各自领域领头羊的品牌,推出的产品也也都是数一数二的,但对于一些国家而言,它们的产品可靠性和安全性还是在限制范围内。近日,俄罗斯联邦通信、信息技术
  • 摸鱼心法第一章——和配置文件说拜拜

    为了能摸鱼我们团队做了容器化,但是带来的问题是服务配置文件很麻烦,然后大家在群里进行了“亲切友好”的沟通图片图片图片图片对比就对比,简单对比下独立配置中心和k8s作为配
  • 一文看懂为苹果Vision Pro开发应用程序

    译者 | 布加迪审校 | 重楼苹果的Vision Pro是一款混合现实(MR)头戴设备。Vision Pro结合了虚拟现实(VR)和增强现实(AR)的沉浸感。其高分辨率显示屏、先进的传感器和强大的处理能力
  • 企业采用CRM系统的11个好处

    客户关系管理(CRM)软件可以为企业提供很多的好处,从客户保留到提高生产力。  CRM软件用于企业收集客户互动,以改善客户体验和满意度。  CRM软件市场规模如今超过580
  • 微信语音大揭秘:为什么禁止转发?

    大家好,我是你们的小米。今天,我要和大家聊一个有趣的话题:为什么微信语音不可以转发?这是一个我们经常在日常使用中遇到的问题,也是一个让很多人好奇的问题。让我们一起来揭开这
  • .NET 程序的 GDI 句柄泄露的再反思

    一、背景1. 讲故事上个月我写过一篇 如何洞察 C# 程序的 GDI 句柄泄露 文章,当时用的是 GDIView + WinDbg 把问题搞定,前者用来定位泄露资源,后者用来定位泄露代码,后面有朋友反
  • 8月见!小米MIX Fold 3获得3C认证:支持67W快充

    这段时间以来,包括三星、一加、荣耀等等有不少品牌旗下的最新折叠屏旗舰都得到了不少爆料,而小米新一代折叠屏旗舰——小米MIX Fold 3此前也屡屡被传
  • OPPO K11样张首曝:千元机影像“卷”得真不错!

    一直以来,OPPO K系列机型都保持着较为均衡的产品体验,历来都是2K价位的明星机型,去年推出的OPPO K10和OPPO K10 Pro两款机型凭借各自的出色配置,堪称有
  • Windows 11发布,微软一改往常对老机型开放的态度

    距离 Windows 11 发布已经过去一周,在过去一周里,很多数码爱好者围绕其对 Android 应用的支持、对老机型的升级问题展开了激烈讨论。与以往不同的是,在这次大
Top