做游戏饰品交易这几年,最常被同行问的一个问题是:你们这种垂直电商,凭什么敢在活动高峰期让几万人同时抢一件饰品?说句实话,光靠业务代码硬扛肯定扛不住,真正在底下兜底的是消息中间件。悠悠有品这个平台,核心交易链路全部走 RocketMQ,海量行为数据和日志管道全部走 Kafka,两个消息引擎各管一摊,才把高并发这块撑了起来。这篇文章不聊虚的,把我自己在选型、部署、调优和排障过程中积累的东西完整梳理一遍,给正在折腾 RocketMQ 和 Kafka 的朋友一份能直接抄作业的参考。
我自己也是从单机 RabbitMQ 一路踩坑踩过来的,RocketMQ 和 Kafka 这俩货看起来都是"发消息的",但脾气完全不同。RocketMQ 适合承载交易类场景,事务消息、延迟消息、顺序消息这些都是为业务量身定做的;Kafka 则天生适合做海量数据管道,吞吐量高、持久化强、生态庞大,Flink、Canal、ES 几乎都能跟它无缝对接。把这俩组合在一起用,不是炫技,而是业务逼着你这么干。
1. 业务场景与消息中间件选型考量
1.1 游戏饰品交易平台到底有什么特殊性
先说清楚业务场景,不然下面的架构决策看着就像空中楼阁。游戏饰品交易平台,核心业务是玩家之间买卖 CS:GO、Dota 2 这类游戏的皮肤、道具。听起来很简单,但实际做起来有几大痛点。
第一,高价值单品并发抢购。一个稀有皮肤可能价值几万块,上架瞬间会涌入大量买家请求,系统必须在极短时间内完成"冻结库存、创建订单、通知卖家、锁定饰品"这一串操作。任何一个环节出问题,轻则超卖,重则资损,这在游戏饰品交易里是不可接受的。
第二,交易链路长且状态多变。饰品交易不是简单的"买家付款卖家发货",中间涉及平台担保、API 发货、第三方机器人交割、超时自动关单、申诉仲裁等多个状态。每笔订单的状态流转都可能触发消息通知、库存变更、资金流水记录等一堆下游操作,这些操作天然需要异步化。
第三,海量埋点行为和日志数据。除了交易,用户浏览、搜索点击、价格曲线、风控行为等数据每时每刻都在产生,这些数据量远大于交易本身,需要进入数据仓库或搜索引擎供后续分析使用,但它们对实时性和事务性的要求很低。用一句话总结:交易数据要稳、要准、不能丢;行为数据要快、要大、能扩展。这两种诉求天然适合用不同的消息引擎来承接。
1.2 为什么核心交易必须交给 RocketMQ
先从交易链路说起。当初选型时,我们其实在 RabbitMQ、RocketMQ、Kafka 之间纠结了很久,但最终核心交易场景坚定地选了 RocketMQ。
最直接的原因是 RocketMQ 的事务消息。游戏饰品交易中,"创建订单 + 冻结饰品 + 扣减库存"这几个操作必须保持最终一致性。比如买家下单购买一件饰品,我们需要在本地事务里写入订单记录,然后发送一条"锁定饰品"的消息给库存服务,库存服务再通过消息确认冻结。如果消息发送和本地事务不同步,就会出现订单建了但饰品没锁住,或者饰品锁了但订单没建的情况,这在传统 MQ 里非常难处理。RocketMQ 的事务消息机制就是专门解决这个问题的:先发一条半消息,本地事务执行成功后再提交确认,Broker 才会把消息投递给消费者;如果本地事务不确定,Broker 还会主动回查,最终保证两边状态一致。这个能力 RabbitMQ 和 Kafka 原生都不具备。
另一个关键点是 RocketMQ 的延迟消息。交易场景里大量用到"超时关单""超时未支付自动取消""发货超时提醒"这类定时逻辑。RocketMQ 内置 18 个延迟级别,用一条消息就能实现 30 分钟超时关单,加一个 topic 就能把任务顺延,不需要额外引入一套定时任务系统。Kafka 在这块明显不如 RocketMQ 方便,它不支持延迟消息,要不自己用时间轮实现,要不依赖外部存储,复杂度会大不少。
再加上 RocketMQ 的消息语义更贴近业务开发者的思维模式,支持标签过滤、Key 索引、批量消息、Pull/Push 两种消费模式,在 Spring Boot 生态里用起来几乎无脑。社区又有阿里这么大一个使用方在背后,出问题的概率极低。所以核心交易链路,RocketMQ 是当之无愧的第一选择。
1.3 Kafka 负责的"海量数据"指的是什么
如果用一句话定位 Kafka 在我们平台里的角色,那就是"所有不要求强一致、只要求高吞吐的数据搬运工"。
实际上线后,Kafka 承担的职责大概有这么几块。第一块是用户行为埋点,浏览、点击、搜索、收藏这些事件数据,从 Nginx 网关和客户端上报过来后,先打入 Kafka,再由 Flink 实时消费写入 Elasticsearch 和 ClickHouse,供运营后台和推荐系统使用。第二块是业务日志与链路追踪,所有微服务的日志都通过 Kafka 汇聚后进 ELK,高峰期每秒几万条日志,只有 Kafka 能扛得住这个写入速度。第三块是 Canal 同步 MySQL Binlog 到其他存储,我们用 Canal 监听交易库的 Binlog,把变更事件发到 Kafka,下游消费者负责更新缓存、同步数据到数仓,这比用定时任务去扫表高效得多。
Kafka 在这类场景里展现出的优势非常明显:单分区顺序写磁盘,吞吐量轻轻松松上十万条每秒;分区机制天然支持水平扩展,流量涨了加分区就行;消息默认保留 7 天,即使下游临时故障,起来后也能从之前的 offset 接着消费,数据不容易丢。RocketMQ 也能做这些事,但它更适合复杂业务,在某些极端吞吐场景下不如 Kafka 纯粹,加上 Kafka 周边生态更加庞大,Flink、Spark、ES 这些组件对 Kafka 的支持都是第一优先级的,所以海量数据这块交给 Kafka 是完全合理的分工。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
