八年前,我们接了一个看起来简单的项目:给一场户外寻宝活动做实时定位系统。GPS坐标、用户点击、传感器数据,汇总后推送到参与者手机上。团队觉得这事不难——Redis Pub/Sub配WebSockets,标准实时架构,两周上线。
结果活动第一天就崩了。不是小卡顿,是彻底的灾难:有人收到三条重复提示,有人完全收不到线索,最惨的是一群人挤在同一个热点区域时,系统直接僵死。我们盯着监控面板,看着Redis连接数飙到极限,才明白自己踩了多大的坑。
![]()
这篇文章不是技术布道,是一个团队从"能跑就行"到"必须可靠"的复盘。核心教训只有一句话:在不可预测的手机流量面前,内存快不等于系统稳。
![]()
我们的初始方案选Redis Pub/Sub,逻辑很顺:事件进来,发布到频道,Worker订阅后推给手机。Redis的内存操作够快,Pub/Sub模式又天然支持一对多广播,看起来完美匹配寻宝场景——一个线索发布,几百人同时收到。
问题是,寻宝活动的流量模式根本不是平稳的。平时可能每秒几百条事件,但某个热门线索点一开放,瞬间涌入几万条GPS上报。Redis Pub/Sub的瓶颈暴露了:它是内存队列,没有持久化,消费者跟不上时直接丢消息;频道层面的锁竞争让并发读取变成串行;更麻烦的是,我们为了"保证送达"做了客户端重试,结果网络抖动时同一事件被反复推送。
活动结束后的日志分析让人头皮发麻:峰值时段事件重复率高达12%,丢包率3%,平均延迟从预期的50毫秒暴涨到200毫秒以上。用户端的体验是——有人手机震了三次收到同一条"宝藏就在附近",有人走到坐标点却什么都没触发。
团队花了三天做故障复盘,最终结论很清晰:Redis Pub/Sub的设计目标不是这种场景。它适合内部服务间的轻量通知,不适合面向公网、设备离线/在线状态混乱、流量尖峰随机的移动应用。
我们决定彻底换架构。核心思路从"内存广播"转向"日志驱动"——用Apache Kafka做中央事件总线,Producer只管写日志,Consumer按自己的节奏拉取,两边彻底解耦。
Kafka的选型基于三个硬性需求。第一,水平扩展:多Broker、多分区的架构让我们能把不同地理区域的事件分到独立分区,热点自动分散。第二,持久化缓冲:即使Consumer暂时跟不上,事件也安全落盘,不会内存溢出丢数据。第三,回溯能力:如果某个Worker崩溃重启,可以从上次提交的位点继续消费,而不是像Redis那样一旦错过就永远丢失。
配套调整也很关键。我们在Kafka前面加了一层商业版Redis做写透缓存(write-through cache),专门服务高频查询——比如"我当前位置附近有哪些未解锁线索"。这类请求占流量大头,但数据更新频率低,缓存命中率做到90%以上,直接卸掉Kafka Consumer的大部分读压力。
新架构上线后的数据对比很直观。事件处理延迟从平均200毫秒降到50毫秒以内,系统吞吐量提升5倍。缓存层把最热查询的响应时间压到10-15毫秒。更重要的是,活动期间我们再没出现过消息重复或丢失,即使某个区域突然聚集上千人,Kafka的分区机制也能自动把负载拆到多个Broker上。
用户端的反馈最实在:寻宝App的推送从"时灵时不灵"变成"人到提示到",离线重连后自动补发未收到的线索,整个活动的完成率比预期高出23%。
![]()
如果重来一次,我会不会直接跳过Redis Pub/Sub?说实话,可能不会。但我会做几件事 differently。
首先是Redis实例的规格选型。我们最初用的是标准配置,连接池上限、网络带宽都没按峰值设计。如果一开始就上集群模式,配合客户端侧的队列缓冲和指数退避重试,Pub/Sub的崩溃或许能延缓——注意是延缓,不是解决。Redis的单线程模型决定了它终究会在某个并发阈值上撞墙。
其次是监控埋点。我们当时只看了"平均延迟",没关注P99延迟和频道级别的锁等待时间。如果早点发现长尾延迟在恶化,可能能提前预警,而不是等到用户投诉才反应。
最后是对"实时"这个词的敬畏。很多团队(包括当时的我们)把实时等同于快,但真正的实时系统需要的是可预测的延迟边界。Kafka的延迟比Redis内存操作高,但它的延迟分布是稳定的、可量化的、能根据分区数线性扩展的。这种确定性在高 stakes 场景里比峰值速度更重要。
这个项目教会我的,不是"Kafka比Redis好"这种无聊结论。而是:事件驱动架构的选型,本质是流量模式的匹配。如果你的事件源是可控的内部服务,Redis Pub/Sub足够优雅;但一旦面对公网移动设备、离线状态混乱、流量尖峰不可预测,就需要一个能背压、能缓冲、能水平扩展的日志中心。
寻宝活动的技术挑战其实很典型——它把"边缘计算+实时推送+最终一致性"三个难题压缩到一个场景里。我们的解法也不是唯一答案,有人用Pulsar,有人用NATS JetStream,甚至有人用云厂商的托管队列。核心判断标准只有一个:当十万台手机同时抖动时,你的系统能不能不崩、不丢、不重。
那个项目结束后,团队形成了一条铁律:任何涉及移动端的实时系统,原型阶段必须做混沌测试——模拟网络分区、模拟设备批量离线、模拟流量十倍突增。如果架构在这些测试下还能保持延迟可控,才值得投入生产。
毕竟,寻宝活动的参与者不会关心你用了Kafka还是Redis。他们只关心:当我站在那棵老橡树下时,手机会不会准时告诉我,宝藏就在脚边三米处。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.