直播房间服务基于CQRS的架构演进实践( 三 )


当然,上游业务服务fanout过多读流量到下游服务也是需要治理的,这在另一个议题中去开展了 。
在具体的实现过程中 , 我们将整个拆分划分成三大阶段 。

直播房间服务基于CQRS的架构演进实践

文章插图
图片
  • 数据对齐阶段
本阶段目标是把B端的数据库从C端复制 , 并且保持数据一致 。并且此阶段可以拆分成增量对齐阶段和存量对齐阶段 。
增量对齐,将新数据的创建和更新通过双写同步 。
存量对齐,通过同步JOB将C端DB的存量数据同步到B端新DB,并且需要一种对账系统去针对全量数据进行周期性的对比 , 来确保数据一致性 。
  • 数据同步阶段
针对数据一致性问题和业务上数据实时性问题,需要对相应的实时场景进行改造 。B端构建新的房间领域事件消息,并同步到C端 。
此阶段完成C&B分写逻辑,通过在DAO层控制BC表级和字段级的写入控制 , 将写操作分流到B和C的各自服务内 , 并且通过消息事件,来同步数据变更 。此阶段完成了数据拆分和同步的目标 。
If the choice is made to keep the updates asynchronous, the entire system is forced to deal with the fallout of eventual consistency.
如果选择保持更新为异步的,整个系统将不得不处理最终一致性所带来的后果 。
  • 最终闭环阶段
此阶段作为收尾 , 我们将上游的调用梳理出来,并且改造读取各自领域真正的依赖服务,最终达到完全解耦的目标 。
核心设计 数据拆分 Data Division当前直播的核心实体数据库,BC属于公用的状态,每张表和每个字端按照上述的原则是可以划分出BC属性的 。所以我们一步到位,颗粒度到最小单位字段级别,确保完全解耦 。
BC拆分后短时间内两套独立数据库的表字段可以保持相同 , 长期根据业务迭代节奏不同,两边可以变为异构shcema模式 。同时要注意的是,业务数据层面切分后,需要联动大数据层面同步hive表的变更,单独重新建模或数据任务换源 , 这点是比较容易遗漏的 。
领域事件驱动 Domain Event-DrivenBC房间业务各自划分业务域边界后,域之间的数据同步应通过领域事件驱动+观察者模式去实现;域内的核心业务逻辑,可以走应用服务编排 。
本次实践过程中重新梳理制定了“房间状态变更”事件,basic room info + extra info,满足订阅者服务对房间业务域核心字段的要求 。
跨微服务的事件机制要总体考虑事件构建、发布和订阅、事件数据持久化、消息中间件,甚至事件数据持久化时还可能需要考虑引入分布式事务机制等 。完整实践下来还是成本还是比较高的,实施者应考虑结合业务场景和对数据的实时性/一致性要求来决定实践到哪一步 。
Tip1:订阅者需要实现消费幂等,业务场景如果有诉求需要额外实现数据版本协议(eg:稿件系统BC CQRS拆分,B端稿件数据被重新编辑审核,C端已开放的版本仍然可以浏览,即使用了数据版本协议字段) 。
Tip2:如果订阅者有实现接收Message后反向callback query的模式(更适合去保障最终一致性),需要关注query的数据源是来自主库or从库 , 不然会有因主从同步时延导致的数据不一致case 。
Tip3:绝对不要将核心DB的binlog消息暴露为Domain Message,一是暴露了过多细节字段下游并不一定都需要订阅关心,要做很多filter逻辑 , 二是核心DB的字段变更将需要牵动所有下游,不利于变更 。
灰度控制 Gray Scale Control核心服务变更依赖一个比较完备的灰度发布方案,基于分布式KV组件(服务可以近实时地获取到KV系统中配置的开关变更)我们设计了从BFF网关到服务的开关,来控制字段的外显和关键Topic发送 。
灰度策略有:功能总体关闭、白名单模式放量、百分位/千分位放量、功能全量打开,服务发布观察遵从这个流程,从APIGW+服务染色发布引入流量+功能KV开关做到谨慎放量 。
可观测性建设 Observability Construction新的架构落地只是起点 , 真正的考验刚刚开始 。我们必须为架构的稳定性,可用性负责 。
保障整个CQRS系统,需要“配套设施”,其中的首要利器就是做可观测性建设(Observability Construction),基于现有的基架能力,我们搭建了直播CQRS监控大盘,从生产方到消费方 , 全链路监控核心指标 。


推荐阅读