通过使用CQRS架构模式优化你的数据访问 - 第一部分
一个理论和实践的方法

你有没有想过,有多少次你开始用一个简单的CRUD架构来开发一个新的服务,从你的边界环境中的某个领域对象,在那一刻是 "OK "的,而周围的生态系统随着时间的推移不断增长和扩展,直到你开始注意到这一点,要么(或两者)。
- 围绕你的对象执行查询的需求变得复杂,难以处理(对其他服务的多次HTTP调用,昂贵的跨表连接,等等)。
- 由于你的服务最终有更多的读操作而不是写操作,所以你的写操作的性能下降了。
当然,上面指出的一些问题可以通过很多方式来解决。从我的头脑中,我可以想出一些数据模式,如分片策略,DB上的物化视图,数据报告卸载(数据仓库),不同的数据库访问技术的读取和更新,可能还有其他一些肯定是通过使用不同的模式和方法的组合来解决的。
然而,我将把写作重点放在我最喜欢的一个模式上,即CQRS模式。
它能解决什么问题?
当使用像CRUD这样的传统架构时,同样的数据模型被用来更新和查询大规模解决方案的数据库,它最终可能成为一种负担。比如说。
- 读取端点可能在查询端对不同的来源进行多次查询,以返回具有不同形状的复杂的DTOs映射。而我们已经知道,映射可能变得相当复杂。
- 在写端,模型可能实现多个复杂的业务规则来验证创建和更新操作。
- 我们可能想以其他方式查询模型,也许是将多条记录折叠成一条,或者将更多的信息汇总到模型上,而这些信息目前在其领域内是不可用的,或者只是通过使用一些二级字段作为键来改变查询的方式来查看记录。
结果,我们围绕着模型对象的CRUD服务开始做太多的事情,而且当它增长时变得很糟糕。这时,这个模式出现在我们的工具带中,帮助我们解决这些可扩展性问题。
这个模式!
CQRS的缩写是_命令和查询责任隔离_。它的主要目的是基于将数据变异操作(命令)和读取操作(查询)分开的简单想法。为了达到这个目的,它将读和写分离成不同的模型,用命令来创建/更新,用查询来读取其中的数据。
一般CQRS的概念架构
如上图所示,你会注意到有一个事件队列,通过向主题推送一个事件来连接写和读两个世界,每次我们的域的实例在写方面被创建/更新。之后,查询服务将从传入的事件中读取,对数据进行规范化、丰富化、切片和切块,以创建查询优化的模型,并将其存储起来以便日后读取。
特别是,我把这一系列文章的重点放在利用CQRS模式上,把事件源架构加入其中。当我们想保持这个流程有明确的关注点分离,异步,并且利用适当的数据库引擎来实现查询性能(比方说,一个SQL数据库用于写,一个NoSQL用于查询操作,通过物化视图优化查询,以避免昂贵的连接)时,它就很适合。
除此之外,当我们使用事件源架构时,事件主题将成为我们的黄金数据源,因为它可以在任何时候被用来重放整个事件集合并重现数据的当前状态。这样,我们就有可能从一开始就异步地读取队列,并在系统演化时,或在读取模型必须改变时,从原始数据中生成一组新的物化视图。物化视图实际上是数据的持久只读缓存。
然而,分离世界的另一个好处是有机会单独扩展两者,从而减少锁的争夺。另外,由于大部分复杂的业务逻辑都在写模型中,所以通过分离模型使它们更灵活,也更容易维护。读取模型则相对简单。
这种模式在什么时候是一种方便的解决方案?
像任何模式一样,CQRS有时是有用的,但并不总是。我们已经在很多场合了解到,没有银弹可以杀死我们所有的问题。但是,在这些可能的要求下,它是会有用的。
- 数据读取的性能必须与数据写入的性能分开进行微调,特别是当读取的数量远远大于写入的数量时。在这种情况下,你可以扩大读取模型的规模,但只在少数实例上运行写入模型。
- 在这种情况下,一个开发团队可以专注于作为写模型一部分的复杂领域模型,而另一个团队可以专注于读模型和用户界面。
- 系统预计会不断发展,可能包含多个版本的模型,或者业务规则经常变化的地方。
- 与其他系统的集成,特别是与事件源的结合,一个子系统的时间性故障不应该影响其他子系统的可用性。
- 允许读取最终一致的数据。由于这种模式的异步性。
摘要
正如我上面所说,这不是我们所有扩展/查询问题的解决方案。在使用CQRS模式时,我们应该非常谨慎。它有时是有用的,但并不总是。许多系统确实适合,而且只用CRUD模式就能很好地工作,因为它们足够简单,因此,如果我们想改用CQRS模式,就会浪费时间,把容易管理的东西变成非常复杂的架构来实现和维护。因此,除非有必要,否则尽量保持简单。请记住,从队列中读取数据并进行所有的数据转换以对原始输入进行反规范化,在时间消耗和资源使用方面可能会非常昂贵。
然而,尽管很复杂,在面对需要有多种方式来查询我们的模型而不影响写入性能等问题时,我很容易发现这种模式非常有用。不仅如此,值得强调的是,我们可以直接重放整个队列来创建原始数据的新视图,使查询更加简单和便宜,因为我们可以避免表连接和数据合并。
接下来的步骤
当然,这种模式还有很多其他方面需要在一篇较长的文章中讨论,但我想在这里至少强调统治这种架构的核心原则。那么,让我们直接跳到这个系列的第二部分,通过使用GoLang、Kafka、MongoDB和Cassandra编码一些愚蠢的例子,看看这个模式的实际例子以及移动部分的交互方式。下一次见!
[更新]第二部分已经为你们准备好了!
通过使用CQRS架构模式来优化你的数据访问--理论与实践的结合。
通过使用CQRS架构模式来优化你的数据访问--一种理论和实践的方法最初发表在ITNEXT的Medium上,人们通过强调和回应这个故事来继续对话。