题目
在像 IM、短视频、游戏等实时在线类的业务系统中,一般会有【广播消息】业务,这类业务具有瞬时高流量的特点。
在对【广播消息】业务实现时通常需要同时写 “系统消息库” 和更新用户的 “联系人库” 的操作,用户的联系人表中会有未读数字段,写入一条系统消息,肯定要更新用户的 “系统联系人” 的未读数了。
我们知道:“系统消息库” 和 “联系人库”是两个不同的数据库,不具备【原子性】操作;这样就很容易出现用户收到了系统消息,但是没有未读数的提醒,或者有未读数的提醒,但是没有真正的系统消息内容,这样非常差的用户体验。
那么在瞬时广播 6000万 系统消息时,为了保证系统消息和未读数的【一致性】,下面哪一个才是最优的解决方案呢?
A. 引入 XA 解决方案;
B. 引入 Saga 解决方案;
C. 引入事务消息解决方案;
D. 改造实现流程,在广播时只写系统消息库;在用户登录时,由登录事件触发拉齐系统消息与用户未读数的一致性动作。
解析
先说 XA 解决方案。
XA是一个规范,该规范定义了TM与RM之间的接口;什么是 RM 呢?即资源管理器,就是数据库,MySQL 和 Oracle 都实现了 XA规范,那么 MySQL 和 Oracle 都可以作为 RM;什么是 TM 呢?即事务管理器,就是与所有的RM(数据库)通信的一个组件,该组件往往嵌入在应用程序中运行,如下图所示。
2PC,即两阶段提交,是一个协议,该协议基于 XA 规范实现了分布式事务的细节。基于 XA 规范的 2PC 协议是分布式事务的强一致性实现,从理论上完全可以满足题目中所描述的业务场景,即实现 “系统消息库” 和 “联系人库” 数据的一致性。但是 2PC 以及后面推出的 3PC存在一个最大的问题,就是性能太低;之前我们团队有人做过测试,其性能与不用 XA方案时几乎差一个数量级;所以面对 瞬时广播 6000万 的系统消息,XA解决方案是不合适的。
再说 Saga解决方案。Saga 也是一种协议,又叫做分布式事务的补偿协议方案,由实现者对该协议方案进行落地;一个分布式事务可以拆分为多个本地事务,每个本地事务包括相应的“执行模块”和“补偿模块”,“执行模块” 负责正常的业务逻辑,在 “执行模块” 失败时由TM(事务管理器)负责调度 对应的 “补偿模块” 来对已经提交的事务进行数据恢复,如下图所示。
Saga 解决方案没有 XA 解决方案低性能的问题,但是需要业务开发同学针对每一个本地事务都需要编写相应的“补偿逻辑代码”,这样的解决方案对业务的侵入性较大;更重要的是,如果“补偿模块”执行失败了又该如何处理呢?尤其是在 瞬时6000万的广播系统消息的场景中,“执行模块”会失败,其“补偿模块”失败的概率是非常高的;所以在该场景中,Saga解决方案也是不合适的。
接着说事务消息解决方案。所谓【事务消息】即意图通过MQ消息中间件的“消息”达到“分布式事务”的目的。RocketMQ 官方推出了基于 RocketMQ的事务消息解决方案(我们在P7架构师课上曾详细分析过),生产者通过预先发送 “半消息” 的方式通知 MQ 服务端,在本地事务完成或失败后再确认“半消息”是否提交,若生产者出现异常可由MQ服务端进行回调确认; 如下图所示。
事务消息方案因为需要业务开发者提供回调接口,所以对业务的侵入性仍然很大;对于此,我们公司实现了【本地消息事务方案】,即生产者不需要提供回调接口,在执行本地事务时向本地数据库的消息表中写入一条消息,然后开启另外专门的线程读取消息和发送消息。不管是【官方版的事务消息解决方案】,还是【本地消息事务解决方案】,对于消费端来说,在消费16次仍然失败的情况下,是需要人工介入才能解决的;而且更重要的,站在整个业务系统的角度分析,为了实现“系统消息库”和“联系人库”的数据一致性,需要额外引入一个 MQ 中间件,会加大整个系统的架构复杂度,增加维护的工作量。所以在业务场景下,事务消息解决方案也是不合适的。
最后看一下改造业务实现流程的落地方案。在业务场景中,大部分用户(80%左右)是处于离线状态的,所以可以据此降低瞬时广播时对数据库的瞬时压力。如下图所示,流程改造如下:在广播系统消息时,对于离线用户,只写 “系统消息库” (允许写失败,在这里数据的一致性才是重点要考虑的);在用户登录的时候(用户登录动作不是集中发生的,这就起到了压力分摊的效果),发送一条消息到MQ,触发拉齐“系统消息库” 和 “联系人库”的 【数据对齐逻辑】。这样登录的用户就可以从 “联系人库” 中获取到 未读数,然后从 “系统消息库”中获取到 广播的系统消息了。该解决方案相对于 上面的三种解决方案来说,改造成本最低,改造风险最低,更容易达到效果!
最后总结一下:对于业务系统开发过程中碰到的问题,可以借鉴市面上流行的解决方案,但是一定要结合自己实际的业务场景来设计 解决方案;【降本增效】是架构设计最根本的原则。
所以,题目中D选项是最合适的解决方案!大家若有疑惑,我们随时探讨!
参考答案
D(应试时,一般选择描述最长的选项!)