Kafka,Mq,Redis作为消息队列使用时的差异?

张开发
2026/4/12 17:20:05 15 分钟阅读

分享文章

Kafka,Mq,Redis作为消息队列使用时的差异?
项目里要引入消息队列Kafka、RocketMQ、Redis这三个名字出现的频率最高。它们都能实现异步解耦和削峰填谷但设计初衷完全不同擅长的场景也不一样。选型之前先把三者的定位搞清楚再按吞吐量、可靠性、功能特性、堆积能力、运维成本这几个维度逐个看差异最后结合大厂的实际用法给出判断依据。三者的定位Kafka是LinkedIn在2011年开源的最初要解决的问题是海量日志的实时收集和分发。它的定位是分布式流处理平台消息队列只是它的能力之一。Kafka的整个存储模型围绕顺序写磁盘和批量处理设计天然适合高吞吐的数据管道场景。RocketMQ是阿里在2012年开源的诞生于电商交易的核心链路。它要解决的问题是在分布式环境下怎么保证消息可靠传递、支持事务消息、做到业务级别的精细管控。RocketMQ从一开始就为金融级可靠性设计功能上比Kafka丰富不少。Redis是内存KV数据库消息队列不是它的主业。Redis通过List、Pub/Sub、Stream5.0版本引入三种机制提供了消息能力。如果项目里已经有Redis只是需要一个轻量的异步通知通道Redis可以兼任。但拿它当正经消息中间件用会碰到不少限制。吞吐量Kafka的吞吐量在三者中最高。它写消息走的是磁盘顺序写入配合操作系统的页缓存写入速度接近内存操作。读消息用了零拷贝sendfile系统调用数据从磁盘直接发到网卡不经过用户态内存。LinkedIn做过一个基准测试3台普通服务器单集群达到了每秒200万次写入。RocketMQ的单机吞吐量在十万级/秒这个量级。它没有像Kafka那样大量使用批量发送和页缓存优化而是在消息可靠性上做了更多投入。不过集群维度的吞吐能力也很可观阿里双11期间RocketMQ支撑了峰值TPS过亿的消息收发。Redis的读写速度很快单机可以跑到十万级/秒。但这个速度是建立在内存操作的基础上消息量一大内存就成了瓶颈。而且Redis是单线程模型6.0之后网络IO多线程命令执行仍然是单线程消息处理的并发能力有上限。如果你的场景是日志采集、用户行为埋点、实时数据管道这类高吞吐需求Kafka的优势最明显。消息可靠性Kafka通过副本机制保证消息不丢。每个分区可以配置多个副本生产者发送消息时设置acksall要求所有同步副本ISR都写入成功才返回确认。这个配置下消息丢失的概率极低。Kafka在3.0版本之后把acks的默认值从1改成了all老版本3.0之前默认acks1只要求主副本写入成功就返回主副本宕机且尚未同步到从副本时消息会丢。升级到新版本后默认行为更安全了但吞吐量会有一定下降。RocketMQ在可靠性上做得更细。它支持同步刷盘消息写入磁盘后才返回确认和同步复制主从都写成功才返回两个都开启的情况下即使机器断电消息也不会丢。RocketMQ的事务消息是一个值得单独说的特性先发一条半消息到Broker本地事务执行成功后再提交失败就回滚保证本地数据库操作和消息发送的一致性。Kafka从0.11版本也引入了事务API但它解决的问题不一样Kafka事务是保证跨分区、跨主题的原子写入用于精确一次语义不涉及外部数据库事务的协调。需要协调本地数据库和消息发送一致性的场景RocketMQ的事务消息更对口。Redis的消息可靠性是三者中最弱的。Pub/Sub模式完全没有持久化消息发出去如果没有消费者在线接收就直接丢了。Stream模式引入了消费者组和ACK机制持久化能力比Pub/Sub好但数据存在内存里依赖AOF或RDB做持久化异常宕机时存在数据丢失窗口。如果你的业务对消息丢失零容忍订单、支付、库存扣减RocketMQ的同步刷盘事务消息组合是最稳的方案。功能特性Kafka的功能设计围绕流数据展开。消息按主题和分区组织消费者通过消费者组实现负载均衡。Kafka有一个很有价值的特性消息消费后不会立刻删除而是按照保留策略默认7天保存在磁盘上。这意味着消费者可以随时回溯到任意时间点重新消费做数据重放。这个能力在大数据场景下非常实用比如修复了一个数据处理Bug之后可以把历史数据重新跑一遍。RocketMQ的功能覆盖面更广尤其在业务消息场景下。它支持延迟消息消息发出后不立刻投递延迟指定时间后才到达消费者。用于订单超时关闭、延迟重试等场景事务消息保证本地事务和消息发送的一致性消息过滤消费者可以按Tag或SQL92表达式过滤消息只接收自己关心的消息减少无效消费死信队列消费失败超过重试次数的消息会进入死信队列方便排查和人工处理消息轨迹可以追踪一条消息从发送到消费的完整链路Redis的消息功能相对基础。List可以做简单的先进先出队列Pub/Sub做广播通知Stream是5.0版本引入的支持消费者组、消息ACK、按ID范围读取。Stream在功能上已经接近一个轻量消息队列但跟Kafka和RocketMQ比缺少延迟消息、事务消息、死信队列、消息过滤这些能力。消息堆积能力Kafka把消息存在磁盘上按分区写入独立的日志文件堆积几个TB的数据对它来说没有压力。磁盘顺序读写的性能衰减很小堆积量增大后对读写性能的影响不大。RocketMQ也是磁盘存储所有主题的消息写入同一个CommitLog文件堆积能力也不错。但当堆积量很大、消费者需要随机读取大量历史消息时磁盘随机IO会增加性能会有一定下降。Redis的消息存在内存里堆积能力是它最大的短板。如果消费者处理速度跟不上消息在内存里越积越多最终会触发内存淘汰策略或者直接OOM。生产环境中用Redis做消息队列必须严格监控内存使用确保消费速度跟得上。运维复杂度Kafka在3.0之前依赖ZooKeeper做集群协调运维时需要同时维护Kafka集群和ZooKeeper集群复杂度较高。从2.8版本开始引入KRaft模式3.3版本之后正式可用于生产环境用Kafka自身的Raft协议替代ZooKeeper。到4.0版本ZooKeeper模式已被完全移除。不过目前很多公司的Kafka集群版本还没升到4.0仍然在用ZooKeeper方案。RocketMQ自带NameServer做服务发现和路由管理不依赖外部组件。它还自带了管控台Dashboard可以查看集群状态、主题信息、消费进度、消息轨迹等。对于Java技术栈的团队来说RocketMQ的运维门槛相对低一些。Redis作为消息队列时部署本身很简单一个实例就能跑。但缺少专门的消息管控工具没有消费进度监控、消息轨迹追踪、死信管理这些能力出了问题排查起来比较麻烦。对比速查表维度KafkaRocketMQRedis单机吞吐量百万级/秒十万级/秒十万级/秒受内存限制消息可靠性高副本ISR很高同步刷盘同步复制低内存存储有丢失风险堆积能力TB级性能稳定TB级量大时性能下降受内存限制不适合大量堆积延迟消息不支持需自己实现原生支持不支持事务消息有事务API跨分区原子写入原生支持协调本地事务不支持消息回溯支持按时间或位点支持按时间Stream支持按ID消息过滤不支持需消费端过滤支持Tag和SQL92不支持死信队列不支持需自己实现原生支持不支持运维复杂度较高ZK/KRaft中等自带NameServer低但缺消息管控工具语言生态Java/Scala多语言客户端Java为主多语言客户端适合场景日志、大数据、流处理电商交易、金融业务轻量通知、缓存失效通知大厂怎么选的美团用Kafka做数据平台的统一消息层。美团的数据平台需要采集各个业务系统的日志和行为数据统一缓冲后分发给下游的实时计算和离线分析系统。这个场景的特点是数据量大、对吞吐要求高、对单条消息的可靠性要求相对没那么严格。Kafka的高吞吐和消息回溯能力正好匹配这个需求。美团技术团队还针对Kafka做了基于SSD的应用层缓存优化解决了消费延迟场景下的磁盘IO问题。LinkedIn是Kafka的诞生地。目前LinkedIn的Kafka集群每天处理的消息量在万亿条级别覆盖活动流、运营指标、数据管道等场景。LinkedIn工程团队公开的基准测试数据显示3台廉价服务器组成的Kafka集群可以达到每秒200万次写入。阿里用RocketMQ支撑双11的交易核心链路。RocketMQ从2012年诞生至今每年都要扛住双11的流量峰值。阿里官方公布的数据是双11期间消息收发TPS峰值过亿日消息处理量达到万亿级。RocketMQ的事务消息在阿里内部被广泛用于订单、支付、物流等需要保证数据一致性的场景。京东自研了JMQ消息中间件存储架构上同时参考了Kafka和RocketMQ的设计。Kafka的分区独立存储适合高吞吐RocketMQ的CommitLog模式适合多主题场景京东根据自身业务特点做了取舍和融合。字节跳动自研了BMQ采用存算分离架构底层存储用HDFS兼容Kafka协议。字节的场景特点是数据量极大、主题数量多传统Kafka架构在主题数很多时性能会下降。BMQ通过存算分离解决了这个问题同时降低了存储成本。Shopify用Redis做异步任务队列。Shopify的后台有大量轻量级异步任务邮件通知、Webhook回调等这些任务对可靠性要求不高处理逻辑简单用Redis的List做队列足够应对。Shopify在RedisConf上分享过他们的Redis消息队列扩展实践。从这些案例可以看出一个规律大数据和日志场景选Kafka交易和金融场景选RocketMQ轻量级异步任务可以用Redis兼任。很多公司实际上同时用了多种消息组件各取所长。选型建议选消息队列不需要找一个万能方案根据场景特点来判断就行如果你的主要需求是日志采集、用户行为追踪、实时数据分析、数据管道Kafka在吞吐量和消息回溯上的优势很难被替代。大数据生态Flink、Spark Streaming、ClickHouse对Kafka的支持也最成熟。如果你的主要需求是业务消息订单、支付、库存对消息可靠性要求高需要延迟消息、事务消息、消息过滤等功能RocketMQ在这些方面的能力是开箱即用的。Java技术栈的团队用RocketMQ上手也快。如果你的项目里已经有Redis消息量不大每秒几千条以内对消息丢失可以接受比如缓存失效通知、非关键的异步通知Redis Stream是一个轻量的选择省去了额外部署和维护消息中间件的成本。实际项目中不同组件互补使用是很常见的做法。比如用Kafka做日志和数据管道用RocketMQ做业务消息用Redis做轻量通知。根据业务场景的特点来选择比执着于找一个全能选手要实际得多。小结消息队列选型这件事做了几年之后会发现技术指标上的差异其实很容易查到真正难的是判断自己的业务场景到底需要什么。很多选型失败不是因为选错了技术而是在选型之前没有想清楚核心诉求是吞吐量、可靠性还是功能丰富度。把需求优先级排清楚对着上面的对比表一看答案基本就出来了。还有一点值得注意随着业务发展消息场景会变得越来越复杂一种消息组件兜不住所有场景是正常的。不要一开始就追求用一个组件解决所有问题根据场景分开选型后期维护反而更轻松。

更多文章