ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

专项1:千万级短信推送项目难点复盘

专项1:千万级短信推送项目难点复盘 千万级短信推送同步架构带来的并发瓶颈基础痛点知识点核心知识点同步下发架构的六大线上性能缺陷生活化例子把短信推送比作奶茶店接单 老架构是顾客点单前端请求店员当场现做奶茶 直接送货同步调用第三方通道店里面就 5 个工位Tomcat 线程池。一下子冲进来几千个顾客工位全占满后面所有人排队卡死同时所有人点单记录都手写在一本账本MySQL瞬间写满记账速度跟不上接单整个店直接瘫痪。原有架构 6 类真实问题拆解同步调用耗尽服务线程批量筛选人群后直接同步调用第三方短信通道接口每个请求占一条 Tomcat 工作线程。通道网络慢、超时的时候线程一直被占用新来的请求没有线程可用全部超时。无流量控制容易封第三方通道爬虫、批量导入一次性几十万手机号同时请求短时间请求量超出短信服务商限制服务商直接封禁我方通道所有短信都发不出去。单通道无降级故障即整体阻塞只对接一条第三方短信线路这条线路服务器宕机、维护时所有营销任务全部卡住没有备用线路兜底。无消息重试 / 死信网络抖动丢短信网络偶尔波动、瞬时超时这条短信直接丢弃没有二次补发机制用户收不到营销 / 验证码。热点手机号、商户抢占资源个别商户疯狂下发、同一手机号频繁刷验证码占用大量通道额度普通正常用户短信被挤压延迟。日志同步写入数据库 IO 打满每一条短信推送完成立刻往 MySQL 插入日志千万级批量推送瞬间大量写入磁盘 IO 跑满所有业务查询、更新接口全部变慢。同步执行、无分层流量管控、单通道、无失败补偿、日志与主业务耦合是千万级短信推送场景系统雪崩的核心根源后续所有中间件优化方案都是针对这 6 个痛点设计。RabbitMQ 异步削峰解耦设计核心知识点异步化如何解决同步线程阻塞问题生活化举例还是奶茶店例子 改造后顾客下单店员只负责把订单纸条丢进收纳筐RabbitMQ 消息队列立刻接待下一位顾客不用等奶茶做好、送货完成专门的配送小组消费服务慢慢从筐里拿订单制作配送。就算一次性涌入上万顾客前台接单不会卡死高峰压力被收纳筐缓冲。架构流转流程配套可靠性技术点消息持久化队列、消息都标记持久化MQ 重启、宕机后存盘消息不会消失不会丢失待发送短信任务。生产者确认机制publisher-confirm-type消息成功到达队列MQ 会给业务服务返回 ACK 回执如果网络断连、投递失败程序自动重试发送避免消息半路丢失。解决对应痛点专门解决老架构同步调用占满 Tomcat 线程池、批量请求大面积超时的问题把同步阻塞链路改成异步缓冲链路主线程快速释放。RedisLua 多维度滑动窗口限流实现原理核心知识点滑动窗口限流 Lua 原子执行生活化举例奶茶店新增限流规则单个顾客 10 分钟最多点 3 杯奶茶手机号限流连锁分店一天最多下单 10000 杯商户额度限流同一个小区一次性下单不能超过 200 单IP 限流。收银台统一用一本共享登记册Redis记录下单时间登记、判断数量一步完成不会出现多人同时登记导致计数错乱超量直接拒绝接单。执行流程图关键技术点说明Lua 脚本原子性判断剩余额度、增加计数两步逻辑写在同一段 Lua 脚本中Redis 单线程完整执行中间不会被其他请求打断杜绝并发场景下计数超标的问题。三层限流维度IP 维度限制单 IP 单位时间请求频次拦截爬虫批量刷接口商户维度每家商户分配每日 / 每小时短信总额度防止单商户占满通道资源手机号维度验证码 10 分钟最多 3 条营销短信 24 小时 1 条防止同一号码频繁接收消息。搭配布隆过滤器前置过滤启动时把黑名单手机号全部存入布隆过滤器请求先过过滤器黑名单号码直接拦截不用走到限流逻辑减少 Redis 压力。对应解决的架构痛点解决原有系统无流量管控大批量请求触发第三方通道限流封禁、恶意手机号挤占正常资源的问题。Sentinel 熔断降级与多短信通道自动切换机制核心知识点接口熔断、故障隔离、多线路流量分流生活化举例奶茶店同时合作多家外卖配送员多条短信通道。如果某一位配送员经常迟到、丢单通道超时 / 报错率高收银系统会暂时停用这个配送员不再派单给他新来的订单自动分给其他正常配送员。等过一段时间再少量试单确认配送恢复正常才重新启用。不会因为一个配送员出问题导致店里所有订单全部积压。2. 执行流程图示关键技术点拆解单通道独立熔断规则每条第三方短信通道单独配置熔断阈值统计短时间内接口超时占比、异常返回比例。一旦超过设定阈值直接熔断隔离该通道不再发起调用。半开探测机制熔断不会永久关闭通道等待固定窗口期后进入半开状态放行少量消息测试通道连通性。如果测试正常则关闭熔断恢复该通道使用若依旧报错继续熔断。故障流量自动分流当前通道熔断后业务代码自动轮询其他备用通道实现无感切换业务不用人工介入修改配置。故障消息兜底存储所有通道全部不可用时消息不直接丢弃转发至死信队列后续重试补发。对应解决的架构痛点解决旧架构仅单条短信通道、通道故障后全部营销任务阻塞无降级备用方案的问题实现故障隔离避免单点通道故障拖垮整体短信推送业务。RabbitMQ 多级重试 死信队列消息兜底方案核心知识点消息失败分层重试、死信归档、消息零丢失兜底生活化举例奶茶店配送失败处理流程订单第一次配送没人签收先重试 5 次上门5 次都送不成功统一放到失件存放筐一级死信队列后台专人分 3 轮再尝试联系客户配送如果多次还是联系不上就把订单信息登记到台账MySQL 归档表运营可以手动打电话通知、重新配送不会直接扔掉订单。完整流转流程图关键技术点拆解业务队列本地有限重试单条短信下发失败最多自动重试 5 次避免无限死循环占用消费线程间隔递增重试缓解瞬时通道抖动压力。独立死信队列隔离失败消息达到最大重试次数的消息不会直接删除路由到专属死信队列和正常业务消息物理隔离不堵塞正常短信下发流程。定时任务兜底重试单独定时任务拉取死信队列消息执行 3 轮兜底重试应对长时间通道故障恢复后的补发场景。归档入库 人工补发兜底多次重试依旧失败的消息持久存入 MySQL保留完整手机号、活动、模板信息运营后台可视化查询支持一键重发彻底杜绝消息丢失。对应解决的架构痛点解决老架构无重试、无存储兜底网络瞬时抖动直接丢失短信任务用户收不到通知的问题大幅提升短信整体送达率。冷热数据分离存储日志异步写入 ES 优化数据库 IO 压力核心知识点冷热数据分层、异步批量落库、存储介质差异化使用生活化举例奶茶店记账改造以前所有订单小票、配送记录全部手写在一本总账本MySQL高峰期几百人下单写字速度跟不上账本直接写满卡顿。改造后拆分两套记录总账本MySQL只简单记「订单号、客户、是否送达」简短核心信息热数据经常要查状态大容量档案柜Elasticsearch所有完整配送明细、时间、渠道、失败原因全部放这里后台专门有人统一批量整理归档不占用前台记账速度。 前台接单完全不受大量明细记录拖累查详细历史记录再去档案柜翻。数据流转流程图关键技术点拆解冷热数据划分标准热数据MySQL活动 ID、手机号、下发状态、发送时间等核心短字段日常运营高频查询、需要事务保证一致性冷数据Elasticsearch完整渠道回执、错误码、耗时、重试记录、批量人群明细数据量大、用于故障排查、历史数据分析无事务要求。异步批量写入隔离主链路短信下发成功 / 失败后不会同步同步插入全量日志到 MySQL完整日志单独走 MQ 异步队列批量聚合后再写入 ES不阻塞短信推送主流程。ES 按月分索引设计每天百万级日志按月拆分独立索引旧月份冷索引可归档冻结减少检索数据范围提升查询速度。查询分流简单状态统计走 MySQL多条件模糊检索、手机号精准排查走 ES避免大表查询拖垮数据库。对应解决的架构痛点解决原有架构千万级推送同步写入全量日志瞬间打满 MySQL 磁盘 IO全部业务接口卡顿的问题分离存储压力保障短信推送主链路稳定。Nacos 集群水平扩容实现峰值流量支撑核心知识点服务注册发现、集群负载分摊、弹性扩容生活化举例奶茶店高峰期人手不够解决方案原来只有 1 个制作台单服务节点上万订单堆在一起处理不过来新增多个一模一样的制作台多实例服务节点全部在前台公示栏Nacos 注册中心登记在岗。前台接单后自动分给空闲操作台订单均匀分散处理。大促高峰期可以临时多加操作台客流回落再撤走灵活适配流量。集群扩容流转流程图关键技术点拆解服务注册与负载均衡所有短信消费服务启动后自动注册到 Nacos统一维护服务实例列表Feign/Ribbon 客户端自动做负载均衡请求均匀分配到各个节点单机压力被分摊。AP 临时实例适配业务服务短信消费服务采用 Nacos 临时 AP 实例优先保证可用性短暂实例列表不一致不会中断短信推送适合高并发业务。弹性横向扩容营销大促、千万级批量下发前直接新增服务实例无需修改代码、不用停机新增节点自动注册进集群立刻分担消息消费任务线性提升整体处理吞吐量。健康状态自动剔除节点宕机、服务异常时Nacos 自动剔除故障实例流量不会分发到故障节点避免大量请求失败。对应解决的架构痛点解决单机服务处理能力上限低批量推送峰值处理不过来的问题通过集群分摊压力支撑千万级短信并发下发。集群定时任务重复调度底层痛点分析核心知识点单机定时任务集群化后的并发冲突问题生活化举例奶茶店排班打扫货架原本只有 1 个店员每天凌晨自动整理货架单机 SpringTask只会执行一次 后来店里招了 3 个店员同时值班集群多节点部署3 个人手机都设了同一套闹钟到点所有人同时跑去整理货架重复打扫、重复盘点白白浪费人力还会重复给客户发相同通知。问题产生流程图关键技术点拆解原生 SpringTask 无分布式协调能力Spring 内置定时任务仅基于本机内存运行多台服务器之间完全隔离没有统一调度中心协调到时间所有节点同时执行。任务执行无互斥锁控制多个节点并行执行同一任务时没有机制限制 “同一任务同一时间只能一台机器运行”并发筛选人群会重复产出待推送消息。衍生业务问题同一批人群数据多次生成短信消息消息投递至 MQ 后最终用户收到多条重复营销短信增加通道成本、引发用户投诉。本模块小结原生单机定时任务无法适配分布式集群环境缺少跨机器互斥控制是大批量营销场景重复短信的源头问题之一下一模块讲解分布式锁解决该问题。Redis 分布式锁防止定时任务重复调度实现方案核心知识点跨节点互斥、RedLock 分布式锁、任务执行排他控制生活化举例奶茶店新增货架打扫权限锁凌晨到点 3 个店员同时收到打扫提醒但店里只放一把专用钥匙Redis 分布式锁谁先抢到钥匙谁才能去整理货架没拿到钥匙的店员直接下班休息等下一轮闹钟。钥匙设置超时时间防止店员中途晕倒锁死保证任务一定能正常执行。分布式锁执行流程图关键技术点拆解全局唯一任务锁 Key每个营销定时任务分配独立唯一 Redis Key不同任务互不干扰多节点争抢同一个 Key 实现互斥。锁超时时间大于任务完整执行时长预估批量人群筛选、消息生产最长耗时锁过期时间设置更长避免任务没做完锁提前释放出现多节点并行执行。宕机自动释放锁兜底给锁设置 TTL 过期时间防止服务节点卡死、宕机导致锁永久占用后续调度任务彻底无法执行。RedLock 多节点锁提升可靠性Redis 集群部署时使用 RedLock 机制避免单 Redis 节点故障导致锁失效保证分布式互斥稳定。对应解决的架构痛点解决集群多节点同时执行定时任务重复生成短信消息、用户收到多条相同营销短信的源头问题从生产端杜绝重复数据。全局唯一 msgId 实现 MQ 消费幂等防重核心知识点消息唯一标识、Redis 幂等校验、原子防重判断生活化举例奶茶配送订单防重复配送每一张订单都会生成专属单号msgId 商户 活动 手机号 时间戳配送员上门前先查登记本Redis如果单号已经登记过说明这单已经送完直接回店不用重复配送 如果没有记录正常配送配送成功立刻把单号登记在册防止重复派送。完整执行流程图关键技术点拆解msgId 生成规则全局不重复msgId 商户ID 活动ID 手机号 时间戳多维度拼接同一用户同一活动同一时段不会产生重复标识天然保证唯一性。Redis 原子校验 写入使用 Lua 脚本一次性完成「查询是否存在 写入标记」并发场景下不会出现两个线程同时校验通过、重复下发的漏洞。幂等 key 设置过期时间不用永久存储 msgId根据短信业务规则设置过期时长如 24h/7 天自动清理过期记录避免 Redis 内存溢出。失败消息不打幂等标记只有短信下发成功才写入 msgId发送失败不存储标记消息重试时可以正常二次下发不影响失败补发逻辑。对应解决的架构痛点解决 MQ 网络超时、消息重复投递带来的重复短信问题即使同一条消息多次推送到消费端依靠 msgId 幂等校验只会下发一次。Redis 滑动窗口接口限流拦截前端重复提交核心知识点手机号维度频次控制、前端请求层前置防重、滑动窗口限流生活化举例奶茶店单人下单限制规定同一个客户手机号10 分钟最多买 3 杯验证码奶茶营销类奶茶 24 小时只能下单 1 次。客户反复点下单按钮、爬虫疯狂刷号收银台先查登记簿没到冷却时间直接拒绝下单根本不会生成配送订单从源头杜绝重复短信。完整执行流程图关键技术点拆解分业务设置不同限流阈值验证码短信单手机号 10 分钟最多 3 条营销推广短信单手机号 24 小时仅允许 1 条 区分场景兼顾使用体验与防刷需求。Lua 脚本实现滑动窗口原子操作同一脚本完成时间戳记录、数量统计、过期清理防止并发请求同时校验导致限流失效。前置拦截减少下游资源消耗在 Controller 接口层直接拦截重复请求不会走到人群筛选、MQ 投递逻辑节省 Redis、MQ、通道资源。兼顾爬虫防护批量脚本循环刷同一手机号的场景会被窗口规则直接拦截避免恶意占用短信额度。对应解决的架构痛点解决前端重复点击提交、爬虫批量刷验证码接口造成同一手机号短时间收到多条重复短信的问题在请求源头拦截重复流量。重试链路隔离规避重试机制引发重复下发核心知识点业务队列与死信队列物理隔离、成功消息不进入重试链路、幂等标记区分消息状态生活化举例奶茶店区分正常单和失败退单正常下单成功的订单会盖上 “已送达” 印章Redis 幂等 msgId 记录单独存放完成订单收纳盒配送失败的订单才放到退件筐死信队列只对退件筐里的订单重试配送。已经盖过章的成功订单永远不会再拿出来重试不会重复送奶茶。完整执行流程图关键技术点拆解业务队列、死信队列物理隔离正常消息、失败重试消息存放在两个完全独立的队列互不干扰成功消息直接丢弃不会流入重试队列占用资源。下发成功才写入幂等标识只有真正推送成功的短信才会在 Redis 存入 msgId发送失败无幂等标记允许正常重试补发不会拦截必要的重试流程。重试流程仅处理失败消息系统不会把已经送达用户的消息再次丢进重试链路从链路层面隔绝重复下发的可能性。多层校验兜底即使死信队列重复投递消费时依然会先走 msgId 幂等校验形成双重防护。对应解决的架构痛点解决消息重试逻辑无状态区分已成功下发的消息被重复重试导致用户收到多条相同短信的问题隔离重试链路和前面分布式锁、msgId 幂等、接口限流组成四层完整防重体系。千万级短信推送优化方案整体落地效果总结核心知识点高并发稳定性指标、幂等防重业务指标、全链路优化收益汇总生活化举例改造前后奶茶店整体对比改造前高峰期挤爆、重复送单、经常丢单、记账卡顿、配送员罢工就全部停业客诉多、成本高改造后上万单平稳承接不会重复送奶茶漏单极少某个配送员出事自动换其他人记账不耽误接单客户投诉几乎清零人力与物料成本大幅下降。两大优化体系成果梳理图关键指标拆解系统稳定性相关指标接口性能百万级短信下发峰值接口平均响应稳定控制在 50ms 以内无线程池耗尽、接口大面积超时通道安全多层限流拦截恶意流量第三方短信通道从未因瞬时流量超限被封禁故障容错单通道故障自动切换备用线路业务中断仅秒级送达质量网络抖动、接口超时失败消息全部支持重试补发短信整体送达率提升至 99.95%服务可用性全年未出现因短信推送业务引发的系统宕机故障数据库压力日志异步写入 ESMySQL IO 不再被批量推送打满核心业务查询无卡顿。幂等防重业务指标集群定时任务彻底杜绝多节点重复调度生成批量短信MQ 重复投递网络超时、消息重发场景零重复短信用户投诉接口防刷验证码、营销短信严格限制下发频次无频繁接收短信的客诉成本优化线上重复短信产生量趋近于 0大幅减少无用的第三方通道调用费用。本模块小结整套架构分为两套独立防护体系一套负责高并发下系统不雪崩一套负责全链路杜绝重复短信多层方案层层兜底互相配合完整解决千万级短信推送场景下两大核心线上难题。全套整合总流程图全链路完整流转
返回列表