扩展性
扩展性就是:如果一个新的下游要接入进来有多难?在使用消息队列的时候,新的下游要接入,只需要自己去订阅消息就可以,完全不需要通知任何人。
但是如果是同步调用,事情就麻烦很多,你需要下游提供RPC服务地址(定位信息),根据下游的API设计构造请求、处理响应,再一起联调、测试、上线。
在使用消息队列的情况下,消息发送者完全不关心谁会去消费这些消息。同样地,如果有一个新的业务方要订阅这个消息,它可以自主完成。而同步调用的时候,上游必须知道下游的接口,然后要知道如何构造请求、如何解析响应,还要联调、测试、上线,整个过程都得和下游密切合作,因此效率特别低,可扩展性很差。
但是这里你可以刷一个亮点,就是在类似的场景下,如果因为一些业务情况确实不能使用消息队列,那么可以考虑提供一个一致性的抽象来减轻这种接入的负担。
如果在某些场景下确实不能用消息队列,那么这个扩展性问题可以通过一些技术手段来缓解。比如说上游提供一整套的对接规范,包括 API 定义、请求和响应中每个字段的含义。这样下游就对着这个 API 定义来提供实现,上游就不需要适配每一个下游了。
然后你进一步总结。
这是对接众多下游的基本设计,可以充分保障高可扩展性和高研发效率。
可用性
在使用消息队列的方案里,你只需要确保自己把消息发送到了消息队列里,就认为操作已经成功了。
在同步调用方案里,必须要确保所有的下游都成功了才算成功,还需要额外考虑部分成功部分失败的问题。对比而言,同步调用方案更容易出错,容错也更难。
事件驱动
事件驱动是一种软件开发模式,也可以看作一种架构,核心思想是通过把系统看作一系列事件的处理过程,来实现对系统的优化和重构。
可以直观地理解为,整个系统不同组件之间的通信是通过事件完成的。也就是组件1发送一个事件到消息队列上,然后组件2消费这个消息。组件2消费完成后再发出一个消息到消息队列。每一个事件就是一个消息。
这些消息可能有不同的Topic,也可能发送到不同的消息队列集群。但是毫无疑问他们需要通过紧密合作来解决一个问题。
它的优点十分明显:
低耦合性: 各个组件只依赖消息队列,组件之间通过消息的定义间接地耦合在一起。组件只需要知道消息的定义,并不需要知道发送消息的组件是哪个。
可扩展性: 事件驱动的应用程序有很强的扩展性,可以通过添加新的事件处理程序、组件等来实现系统的扩展和升级
高可用: 可以充分利用消息队列的可靠性、可重复消费等特性,来保证消息发送、消费高可用,从而保证整个系统的高可用。
事件驱动适合用来解决一些复杂、步骤繁多、流程冗长的业务问题。在下面的亮点方案里面,我用的就是事件驱动结合 SAGA 分布式事务的方案。这个方案足够高级、冷僻、奇异。它原本用在一个大规模的分布式系统里面,是一个高性能和高可用的分布式事务解决方案。你可以看一下事件驱动和 SAGA 结合之后的形态。
也就是说,当某一个步骤完成之后,就会发出一个或者多个事件,驱动事务中的后续步骤。包括回滚也是这样,比如说发出一个代表某一个步骤执行失败的事件,对应的消费者就会去执行反向补偿步骤。
使用事件驱动的优点是低耦合、高扩展性、异步、高可用。不过在实时性上要比同步调用差一点。我用一个最简单的例子给你解释清楚它的运作。比如说你有一个分布式事务,就是要求先更新 DB,再更新缓存。那么在缓存更新失败的场景下,过程看起来就像图里展示的这样。
可以考虑这样介绍这个方案。
之前我们公司用事件驱动实现了 SAGA 的分布式事务解决方案。基于事件驱动的 SAGA 模式就是在每一个步骤结束之后发送事件,不同的步骤会发送一个或者多个事件。然后消费者消费了消息之后,就开始执行下一个步骤。比如说在更新 DB 再更新缓存的场景里就可以这样用。这种形态和一般的事务比起来,优势是低耦合、高扩展、高可用。