架构师面试(三十六):广播消息
题目
在像 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(应试时,一般选择描述最长的选项!)
相关文章:

架构师面试(三十六):广播消息
题目 在像 IM、短视频、游戏等实时在线类的业务系统中,一般会有【广播消息】业务,这类业务具有瞬时高流量的特点。 在对【广播消息】业务实现时通常需要同时写 “系统消息库” 和更新用户的 “联系人库” 的操作,用户的联系人表中会有未读数…...
如何开启远程桌面连接外网访问?异地远程控制内网主机
实现远程桌面连接外网访问,能够突破地域限制,随时随地访问远程计算机,满足远程办公、技术支持等多种需求。下面为你详细介绍开启方法。 一、联网条件 确保本地计算机和远程计算机都有稳定的网络连接,有联网能上网。 二、开启远程…...
基于 Python(selenium) 的百度新闻定向爬虫:根据输入的关键词在百度新闻上进行搜索,并爬取新闻详情页的内容
该项目能够根据输入的关键词在百度新闻上进行搜索,并爬取新闻详情页的内容。 一、项目准备 1. 开发环境配置 操作系统:支持 Windows、macOS、Linux 等主流操作系统,本文以 Windows 为例进行说明。Python 版本:建议使用 Python 3.8 及以上版本,以确保代码的兼容性和性能。…...

TortoiseGit使用图解
前言 记录GitTortoiseGit使用,记录下开发中常用命令,健忘时用到方知好。 TortoiseGit使用 图解 commit-提交代码 pull-拉取远程分支最新代码 push-将本地分支代码推送到远程分支 show log-查看分支提交记录 show log - 切换分支查看 show log - 远程分…...

【时时三省】(C语言基础)循环程序举例
山不在高,有仙则名。水不在深,有龙则灵。 ----CSDN 时时三省 例题: 用公式4/π≈1-3/1+5/1-7/1+...求π的近似值,直到发现某一项的绝对值小于10的-6次方为止(该项不累加)。 解题思路: 这是求值的近似方法中的一种。求π值可以用不同的近似方法。如下面的表达式都可以…...
根据JSON动态生成表单表格
根据JSON动态生成表单表格 一. 子组件 DynamicFormTable.vue1,根据JSON数据动态生成表单表格,支持表单验证JS部分1.1,props数据1.2,表单数据和数据监听1.3,自动验证1.4,表单验证1.5,获取表单数据1.6,事件处理1.7,暴露方法给父组件2,HTML部分二,父组件1, 模拟数据2,…...

珍爱网:从降本增效到绿色低碳,数字化新基建价值凸显
2024年12月24日,法大大联合企业绿色发展研究院发布《2024签约减碳与低碳办公白皮书》,深入剖析电子签在推动企业绿色低碳转型中的关键作用,为企业实现环境、社会和治理(ESG)目标提供新思路。近期,法大大将陆…...

电子电子架构 --- 主机厂视角下ECU开发流程
我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 简单,单纯,喜欢独处,独来独往,不易合同频过着接地气的生活,除了生存温饱问题之外,没有什么过多的欲望,表面看起来很高冷,内心热情,如果你身…...

PyQt6基础_QTableWidget
目录 描述: 代码 演示 描述: 1 单击选中一行 2 右键菜单 3 填充数据 4 提取行数据 5 删除行数据 代码 from PyQt6.QtCore import (Qt ) from PyQt6.QtGui import ( QAction ) from PyQt6.QtWidgets import (QApplication,QAbstractItemView,QL…...

uniapp 上传二进制流图片
文章目录 场景🟢一、步骤1.1、选择图片1.2、 读取图片为二进制数据1.3、上传二进制数据到服务器 🟢二、项目案例2.1、替换头像案例2.1、uView u-upload 上传封面 🟢 三、关键注意事项3.1 二进制流与 FormData 区别3.2 性能优化3.3 跨平台适配…...

赛灵思 XCKU115-2FLVB2104I Xilinx Kintex UltraScale FPGA
XCKU115-2FLVB2104I 是 AMD Xilinx Kintex UltraScale FPGA,基于 20 nm 先进工艺,提供高达 1 451 100 个逻辑单元(Logic Cells),77 721 600 bit 的片上 RAM 资源,以及 5 520 个 DSP 切片(DSP48E…...

Unreal Niagara制作SubUV贴图翻页动画
SubUV翻页动画是游戏中的常见功能,通过对每一小块UV进行移动可以模拟动画效果,接下来对下图进行SubUV动画的制作。 (金币测试图下载地址:https://download.csdn.net/download/grayrail/90684422) 最终效果如下: 1.…...

「零配置陷阱」:现代全栈工具链的复杂度管控实践
一、工具链膨胀的「死亡螺旋」 2024年典型全栈项目的初始化噩梦: $ npm create vitelatest ✔ Project name: … demo ✔ Select a framework: › React ✔ Select a variant: › TypeScript SWC ✔ Install shadcn/ui? … Yes ✔ Add Storybook? … Yes ✔ Co…...

金仓数据库KingbaseES技术实践类深度剖析与实战指南
一、语法兼容及迁移实战 (一)语法兼容的多元魅力 在当今多元化的数据库应用环境中,金仓数据库管理系统KingbaseES凭借其卓越的语法兼容能力脱颖而出。它采用的融合数据库架构,通过多语法体系一体化架构,实现了对Orac…...

基于ssm的个人博客管理系统(源码+数据库+万字文档)
57基于ssm的个人博客管理系统:前端jsp、jquery、easyui,后端 spring、mybatis、maven,集成个人博客浏览、详情查看、博客发布、富文本编辑、评论等功能于一体的系统。 ## 功能介绍 ### 用户 - 首页:博客列表、博客详情、关键词…...
c#加密证件号的中间部分,改为*号
前言 使用场景:在我项目中,我需要给前端提供接口,所以我要吧证件号进行加密。例如:411421199510225612,这是一个身份证号,18为的,那么我加密完成之后就会是 411421********5612,类似…...

综述 | GUI Agent:让AI学会「玩手机」的新革命
想象一下,你的手机里住着一个隐形助理:你说“把亮度调到50%”,它自动操作;你说“下载最新游戏”,它一键完成。这就是GUI智能体——一种能“看懂”屏幕并操作的AI。 论文:A Survey on (M)LLM-Based GUI Agen…...

Canvas入门教程!!【Canvas篇二】
没有一朵花,从一开始就是花。 目录 translate() 方法:rotate() 方法:scale() 方法: translate() 方法: Canvas 2D API 的 CanvasRenderingContext2D.translate() 方法用于对当前网格添加平移变换。 translate() 方法通…...

【中级软件设计师】函数调用 —— 传值调用和传地址调用 (附软考真题)
【中级软件设计师】函数调用 —— 传值调用和传地址调用 (附软考真题) 目录 【中级软件设计师】函数调用 —— 传值调用和传地址调用 (附软考真题)一、历年真题二、考点:函数调用 —— 传值调用和传地址调用🔺1、传值调用🔺2、传引用(地址)调…...

第七届能源系统与电气电力国际学术会议(ICESEP 2025)
重要信息 时间:2025年6月20-22日 地点:中国-武汉 官网:www.icesep.net 主题 能源系统 节能技术、能源存储技术、可再生能源、热能与动力工程 、能源工程、可再生能源技术和系统、风力发…...

大数据分析04 数据查询分析
构建数据源 引入pandas包 数据map中ID为列,值为行,每一列中值个数要一致 import pandas as pd data {ID: [000001, 000002, 000003, 000004, 000005, 000006, 000007],name:[黎明, 赵怡春, 张富平, 白丽, 牛玉德, 姚华, 李南], gender:[True, False, …...

ADVB协议同步
关于视频传输,有多种控制时序。协议标准允许设计者选择有限的几个速率的接口来满足 系统设计目标。例如,一些系统使用总线时序发送信息通过line-by-line;在这个案例中, 容器的sof作为vsync同步的点。horizontal line blanding将插入idles,ADV…...

【kafka初学】启动执行命令
接上篇,启动:开两个cdm窗口 注意放的文件不要太深或者中文,会报命令行太长的错误 启动zookeeper bin\windows\zookeeper-server-start.bat config\zookeeper.properties2. 启动kafka-serve bin\windows\kafka-server-start.bat config\serv…...

论文阅读笔记——π0.5: a Vision-Language-Action Model with Open-World Generalization
π0.5 论文 通过异构数据协同训练与分层推理,用中等规模的目标数据(400小时)实现了大规模泛化能力,为现实世界机器人学习提供了新范式。 高层推理(high-level) 根据当前观测和任务指令预测子任务(如“打开抽屉”&…...

电子削铅笔刀顺序图详解:从UML设计到PlantUML实现
题目:为电子削铅笔刀建立一个顺序图和一个通信图。图中的对象包括操作者、铅笔、插入点(也就是铅笔插入铅笔刀的位置)、马达和其他元素。包括哪些交互消息?有那些激活?如何在图中表示出自身调用。 一、顺序图概述 顺序图(Sequence Diagram)…...

FWFT_FIFO和Standard_FIFO对比仿真
在FPGA中使用FIFO时,如果使用FPGA厂商提供的FIFO IP,一般都会有First Word Fall Through FIFO和Standard FIFO类型选项,那么这两种FIFO有什么差异么。两种FIFO的端口是一样的,看不出区别,只有通过仿真,才能…...

什么是可重入锁ReentrantLock?
大家好,我是锋哥。今天分享关于【什么是可重入锁ReentrantLock?】面试题。希望对大家有帮助; 什么是可重入锁ReentrantLock? ReentrantLock 是 Java 中的一个锁实现,它是 java.util.concurrent.locks 包中的一部分,主要用于提供…...

利用JMeter代理服务器方式实现高效压测
前言 在当今快节奏的互联网时代,确保Web应用和服务能够在高负载下稳定运行变得至关重要。无论是电子商务平台、社交媒体网络还是在线教育服务,用户对网站响应速度和稳定性的期望从未如此之高。因此,性能测试不再是一个可选项,而是…...

WSL 安装过程整理
WSL 安装过程整理 一、WSL 安装教程二、安装后小技巧1、安装位置2、常用命令 三、在 WSL2 中安装 perf: 一、WSL 安装教程 史上最全的WSL安装教程 WSL2 最新最全帮助小白一步步详细安装教程 在WSL2 root 和普通用户的切换 轻松搬迁!教你如何将WSL从C盘迁…...
【go】简单理解梳理go的内存分配原理
Go 内存分配机制原理 Go 的内存分配机制设计非常精细,结合了多级缓存、对象池和垃圾回收等机制,以实现高并发下的高性能分配。 1. 整体内存结构 Go 程序启动时,运行时会向操作系统申请一大块连续内存区域(heap arena࿰…...