1. 为什么今天还在纠结Kafka和Redis?——先搞清它们根本不是同一类工具
你点开这篇文章,大概率正卡在一个真实场景里:系统上线前压测,消息堆积如山;或者缓存穿透频发,数据库CPU飙到95%;又或者业务方突然提需求:“订单状态变更要实时推送到APP,还要能查历史轨迹”。这时候翻文档、问同事、搜论坛,满屏都是“Kafka快”“Redis简单”“Kafka适合大数据”“Redis内存贵”……越看越懵。我带过的几个团队,有把Redis当消息队列用结果丢消息的,也有硬上Kafka存用户Session导致运维半夜被叫醒的。问题不在工具本身,而在于很多人从没真正理解:Kafka是分布式日志系统,Redis是内存数据结构存储——这就像问“螺丝刀和电钻哪个更好”,答案永远取决于你要拧的是木螺丝还是混凝土膨胀螺栓。
核心关键词已经浮出水面:Kafka、Redis、消息队列、缓存、实时处理、高吞吐、低延迟、数据一致性、运维复杂度。这些词不是孤立的标签,而是对应着具体的技术契约。比如“Kafka高吞吐”,背后是它把消息顺序写入磁盘文件、批量压缩传输、零拷贝网络发送这一整套设计;而“Redis低延迟”,本质是单线程避免锁竞争+纯内存操作+命令原子性保障。不拆开看这些底层逻辑,所有“选型建议”都是空中楼阁。这篇文章不讲概念定义,只聚焦一个动作:当你面对一个具体业务需求时,如何像老司机一样快速判断——该踩Kafka的油门,还是该用Redis的刹车?我会用真实压测数据、配置参数、故障日志截图(文字还原)和三次线上事故复盘,带你把选择路径变成条件反射。适合后端开发、SRE、架构师,也适合刚学完Spring Boot想落地项目的同学——只要你需要在生产环境做技术决策,这篇就是你的检查清单。
2. 核心设计哲学与能力边界:不是谁更强,而是谁更“守本分”
2.1 Kafka的本质:一个可重放的、分区有序的、持久化的分布式提交日志
Kafka的设计原点非常纯粹:解决LinkedIn内部海量活动日志(如用户点击、页面浏览)的可靠收集与分发。它的所有特性都围绕“日志”展开。我们拆解三个关键设计点:
第一,日志即存储,而非临时中转站。Kafka Broker不把消息当作“待转发的包裹”,而是当成“不可变的账本条目”。每条消息写入后,按时间戳和偏移量(offset)严格排序,存储在分段的磁盘文件中(如00000000000000000000.log)。这意味着:
- 消费者可以任意回溯消费,比如业务方说“把昨天14:00-15:00的支付成功事件重推一遍”,Kafka直接定位到对应日志段即可,无需额外开发重放逻辑;
- 数据天然具备时间序,做窗口计算(如“过去5分钟订单量”)时,Flink或Spark Streaming能直接利用offset做精确一次(exactly-once)语义保障;
- 即使消费者宕机3天,只要未超日志保留期(默认7天),重启后自动从断点续读,不会丢失。
提示:Kafka的“高吞吐”不是靠牺牲可靠性换来的。实测数据:单Broker(16核32G,SSD)在启用压缩(snappy)后,持续写入1KB消息可达12万条/秒,且P99延迟稳定在25ms内。这个数字背后是批量写入(batch.size=16KB)、异步刷盘(log.flush.interval.messages=10000)、零拷贝(sendfile系统调用)三重优化。如果你的应用要求“每条消息必须10ms内送达”,Kafka不是最优解——它的设计目标是“百万级消息不丢、不乱、可追溯”。
第二,分区(Partition)是并行与顺序的平衡术。一个Topic可划分为多个Partition,每个Partition是独立的有序日志。Producer按Key哈希决定消息去哪个Partition(如订单ID % 分区数),保证同一Key的所有消息严格有序;而不同Key的消息可分散到不同Partition并发处理。这就解决了经典矛盾:全局有序性能差,完全无序业务难用。某电商大促系统用16个Partition承载订单流,既保证“同一用户订单按创建时间严格递增”,又通过多Consumer Group并行消费,将订单履约处理能力从单机300QPS提升到集群8000QPS。
第三,副本(Replica)机制锚定数据生命线。每个Partition有1个Leader和N个Follower(ISR,In-Sync Replicas)。Producer只写Leader,Follower异步拉取同步。关键参数min.insync.replicas=2意味着:只有当Leader和至少1个Follower都写成功,才向Producer返回ACK。这样即使Leader宕机,新选举的Leader已有完整数据,避免脑裂丢数据。但代价是:若ISR只剩1个节点(如2个Follower全挂),Producer会报错NOT_ENOUGH_REPLICAS,此时必须人工介入扩容或降级——这是Kafka为强一致性付出的运维成本。
2.2 Redis的本质:一个支持丰富数据结构的、单线程的、内存优先的键值存储
Redis的基因是“快”和“灵活”。它的所有设计都服务于一个目标:让开发者用最简代码实现最复杂的内存数据操作。我们看三个决定性特征:
第一,单线程模型是低延迟的基石,也是扩展性的天花板。Redis Server用一个主线程处理所有客户端请求(网络IO、命令执行、响应返回),避免了多线程锁竞争和上下文切换开销。实测:在4核8G机器上,执行GET key(key存在)平均延迟0.12ms,P99<0.3ms。但这也意味着:
- 所有耗时操作(如
KEYS *、HGETALL big_hash、LRANGE list 0 -1)会阻塞整个实例,导致后续请求排队; - 无法通过增加CPU核心数提升QPS,只能靠分片(Sharding)横向扩展。某社交App曾因一个定时任务执行
SCAN遍历千万级用户在线状态,导致Redis响应延迟飙升至2s,APP首页加载超时。
第二,数据结构即API,减少客户端计算。Redis不止是SET/GET,它提供5种核心数据结构:
- String:支持原子自增(
INCR)、位运算(BITCOUNT),适合计数器、布隆过滤器; - Hash:存储对象属性(如
HSET user:1001 name "张三" age 28),比JSON序列化节省50%内存; - List:实现轻量级队列(
LPUSH/RPOP),但注意:LPOP是O(1),LINDEX list 100000是O(N); - Set:去重与交集(
SINTER),适合好友共同关注、标签推荐; - Sorted Set:按分数排序(
ZADD zset 100 "item1"),实现排行榜、延时队列(分数=毫秒时间戳)。
注意:Redis的“内存数据库”定位常被误解。它支持RDB快照(fork子进程全量保存)和AOF日志(记录每条写命令),但AOF重写(
BGREWRITEAOF)同样会fork,大内存实例可能触发OOM Killer。某金融系统曾因AOF文件达20GB,重写时fork失败,Redis进程退出——解决方案是关闭AOF,改用RDB+主从复制保障可用性。
第三,过期策略是精度与性能的妥协。Redis用两种机制处理过期Key:
- 惰性删除:每次访问Key时检查是否过期,过期则删除。优点是CPU友好,缺点是内存可能长期占用已过期Key;
- 定期删除:后台线程每100ms随机抽样20个Key检查,若过期则删除。但抽样率有限,大量Key在同一时间过期时,可能出现“过期风暴”,CPU飙升。某直播平台设置100万个弹幕Key统一过期,结果Redis CPU瞬间打满,弹幕服务雪崩。根治方案是:过期时间加随机扰动(如
EXPIRE key 3600 + RANDOM(300)),把压力摊平。
2.3 能力对比表:用场景语言回答“该用谁”
下表不是参数罗列,而是把技术特性翻译成业务影响。每一行都对应一个真实决策点:
| 决策维度 | Kafka适用场景(打钩✓) | Redis适用场景(打钩✓) | 关键原因解析 |
|---|---|---|---|
| 消息不丢失 | ✓ 订单创建、支付回调、风控审计等强一致要求 | ✗(除非开启AOF+everysec且主从同步) | Kafka的ISR机制+ACK确认是分布式系统公认的强一致方案;Redis AOF虽持久化,但主从同步有延迟,网络分区时可能丢数据。 |
| 消息顺序性 | ✓ 同一用户行为流(如登录→浏览→下单→支付) | ✗(List可保序但无消费组、无ACK、易丢) | Kafka Partition内严格有序,且Consumer Group支持多实例负载均衡;Redis List的RPOP无ACK,消费者崩溃即丢失未处理消息。 |
| 消息重放 | ✓ 需要回溯历史数据(如BI报表补数、算法模型重训) | ✗(过期即删,无历史追溯能力) | Kafka日志按时间保留,Offset可任意跳转;Redis Key过期后彻底消失,无时间维度索引。 |
| 低延迟响应 | ✗(端到端P99通常>10ms) | ✓ 实时推荐、会话管理、秒杀库存扣减 | Redis内存操作+单线程无锁,天然适合亚毫秒级响应;Kafka的批量、压缩、网络传输链路必然引入延迟。 |
| 高并发写入 | ✓ 日志采集、IoT设备上报(百万TPS) | ✗(单实例QPS上限约10万,分片后运维复杂) | Kafka通过分区+批量写入+顺序IO,轻松支撑百万级写入;Redis单线程模型在高并发写时,网络IO和命令解析成为瓶颈。 |
| 复杂数据查询 | ✗(仅支持按Offset或Timestamp查找) | ✓ 用户画像标签匹配、地理位置围栏、实时排行榜 | Redis的Sorted Set、Geo、Bitmap等结构,让内存计算替代数据库JOIN;Kafka需导出到Flink/ES才能做多维分析。 |
| 运维复杂度 | ✗(需管理ZooKeeper/KRaft、监控ISR、调优JVM堆) | ✓ 单机部署5分钟启动,主从哨兵模式成熟稳定 | Kafka集群涉及协调服务、副本同步、磁盘IO调度等多层抽象;Redis部署包小(<2MB),配置项少(核心<10个),中小团队可快速掌控。 |
这个表格的潜台词是:没有“通用消息中间件”,只有“场景适配的工具”。某内容平台曾用Redis List做评论流,初期很爽——发布评论LPUSH comment:post123 "xxx",前端LRANGE comment:post123 0 19拉取最新20条。但当单篇文章评论破10万,LRANGE从头扫描耗时飙升,且无法按时间范围筛选(如“只查今天评论”)。换成Kafka后,评论写入comment-topic,Flink实时聚合热评,ES存储全文检索——这才是各司其职。
3. 六大典型场景深度拆解:从需求描述到配置参数,一步到位
3.1 场景一:用户行为埋点日志收集(日均10亿条)
需求描述:APP端采集用户点击、曝光、停留时长等事件,需实时流入数仓做分析,同时供实时风控模型使用。要求:不丢消息、可重放、支持多消费方(BI、风控、推荐)。
为什么Kafka是唯一解:
- 埋点数据天然无Key(或Key为设备ID,但分析需全局聚合),Kafka的分区并行写入完美匹配高吞吐;
- BI部门需要重跑昨日数据,Kafka的Offset回溯功能省去ETL重传逻辑;
- 风控模型需消费全量事件流,Kafka Consumer Group天然支持多组独立消费,互不影响。
实操配置要点:
- Topic设计:
topic=app-behavior,partitions=32(按预估峰值QPS / 3000计算,3000是单Partition安全吞吐);replication.factor=3(跨机房部署,防单点故障); - Producer参数:
acks=all(确保ISR全部写入)、retries=2147483647(无限重试,配合retry.backoff.ms=100)、batch.size=16384(16KB批量,平衡延迟与吞吐)、linger.ms=5(最多等5ms凑满batch); - Consumer参数:
enable.auto.commit=false(手动提交Offset,确保处理成功后再确认)、auto.offset.reset=latest(新Consumer默认从最新开始,避免积压干扰); - Broker调优:
log.retention.hours=168(保留7天,满足多数重放需求)、num.network.threads=8(网卡多队列匹配)、num.io.threads=16(SSD IOPS高,需更多IO线程)。
实操心得:某次线上事故源于
batch.size设为1MB。大促期间单条埋点消息含图片Base64,平均200KB,一个batch只能装5条,导致Producer频繁等待linger.ms超时才发送,端到端延迟从20ms升至200ms。教训:batch.size必须结合平均消息大小和目标延迟反推,公式:batch.size ≈ 平均消息大小 × (目标延迟ms / linger.ms)。
3.2 场景二:商品详情页缓存(QPS 5万,缓存击穿风险高)
需求描述:电商首页商品卡片点击进入详情页,需展示价格、库存、规格等。数据库扛不住瞬时流量,且库存变更需强一致性。
为什么Redis是黄金搭档:
- 详情页数据结构清晰(Hash存储商品属性),
HGETALL一次获取全部字段,减少数据库多次查询; - 库存扣减用
DECRBY stock:1001 1原子操作,避免超卖; SET product:1001 {json} EX 3600设置1小时过期,配合主动更新(数据库变更时DEL product:1001)。
实操配置要点:
- 数据结构选择:商品基础信息用
Hash(HSET product:1001 price 99.9 stock 100),避免JSON序列化开销;库存单独用String(SET stock:1001 100),便于DECRBY原子操作; - 缓存穿透防护:对
product:1001不存在的情况,写入空对象SET product:1001 "{}" EX 60(缓存60秒),防止恶意ID攻击; - 缓存雪崩防护:所有商品缓存过期时间加随机值,
EX 3600 + RANDOM(600),避免整点集体失效; - Redis部署:采用Redis Cluster模式,16个分片(Shard),每个分片1主2从。
cluster-require-full-coverage no(允许部分分片故障时继续服务)。
注意:某次大促前,运维误将
maxmemory-policy从allkeys-lru改为noeviction,导致内存满后写入失败,所有商品详情页返回500。紧急回滚后发现:INFO memory显示mem_allocator:jemalloc,但used_memory_human=15.2G已超maxmemory=16G,evicted_keys=0证实驱逐策略失效。根治方案:监控evicted_keys指标,突增即告警。
3.3 场景三:实时排行榜(TOP 100,每秒更新1000次)
需求描述:直播打赏榜、游戏积分榜,需实时显示前100名用户及分数,分数变更延迟<500ms。
为什么Redis Sorted Set是王者:
ZADD rank:live123 15000 "user_789"插入或更新分数,O(log N)复杂度;ZREVRANGE rank:live123 0 99 WITHSCORES拉取Top100,O(log N + M);ZCARD rank:live123获取总人数,O(1);- 完全内存操作,无网络IO瓶颈。
实操配置要点:
- 内存优化:启用
ziplist编码(hash-max-ziplist-entries 512),当成员数<512且单个成员<64字节时,Sorted Set用紧凑数组存储,比跳表节省50%内存; - 范围裁剪:定时任务(每分钟)执行
ZREMRANGEBYRANK rank:live123 100 -1,只保留Top100,避免冷数据堆积; - 分布式锁:多实例更新同一榜单时,用
SET lock:rank:live123 "1" NX EX 10加锁,防止并发覆盖。
实操心得:某游戏公司用Kafka+ES做排行榜,流程是“打赏事件→Kafka→Flink计算→ES写入→前端查ES”。结果ES写入延迟波动大(P95 800ms),且ES分页查询Top100需
from=0,size=100,当总人数超千万时,from值巨大导致深分页慢。换成Redis后,延迟稳定在10ms内,运维成本直降——技术选型的第一法则是:能用内存解决的,绝不走磁盘和网络。
3.4 场景四:分布式锁(秒杀库存扣减)
需求描述:限量100台iPhone,10万人同时抢,需保证库存不超卖,且锁持有时间<1s。
为什么Redis比Kafka更合适:
- Kafka无原子性锁机制,需自己实现(如用Topic分区模拟锁),复杂度高且易出错;
- Redis的
SET key value NX EX seconds是原子命令,天然支持锁的获取与过期; EVAL脚本可实现“校验+扣减+设置过期”三步原子操作。
实操配置要点:
- 锁命令:
SET lock:stock:1001 "client_abc" NX EX 10(获取锁,10秒过期); - 释放锁:用Lua脚本确保“只有锁的拥有者才能删除”,避免误删:
if redis.call("GET", KEYS[1]) == ARGV[1] then return redis.call("DEL", KEYS[1]) else return 0 end- 锁续期:业务处理超时(如数据库慢查询),用独立线程调用
PEXPIRE lock:stock:1001 10000延长过期时间。
注意:某电商用Redis单实例做分布式锁,大促时主节点宕机,哨兵切换期间,旧锁未释放,新主节点无锁状态,导致超卖。解决方案:改用Redlock算法(5个独立Redis实例,获取超半数节点锁才算成功),或直接上ZooKeeper(CP强一致)。
3.5 场景五:异步任务队列(邮件发送、短信通知)
需求描述:用户注册后需异步发欢迎邮件,要求任务不丢失、支持重试、可监控积压。
为什么Kafka比Redis List更健壮:
- Redis List无ACK机制,消费者崩溃即丢任务;Kafka Consumer手动提交Offset,确保“至少一次”;
- Kafka支持死信队列(DLQ):消费失败的任务重定向到
email-dlq-topic,人工排查; - Kafka Manager可直观查看每个Partition积压量(Lag),实时监控任务健康度。
实操配置要点:
- Topic设计:
topic=email-task,partitions=8(邮件服务部署8个实例,一一对应); - Consumer逻辑:
- 拉取消息(
poll(100)); - 调用邮件API(带超时和重试);
- 成功则
commitSync()提交Offset;失败则send(topic="email-dlq", value=msg)发往DLQ;
- 拉取消息(
- 监控告警:Prometheus采集
kafka_consumer_lag指标,Lag > 1000时触发企业微信告警。
实操心得:某SaaS平台用Redis List做任务队列,
BRPOP task-list 0阻塞获取。某次邮件网关故障,任务不断重试,List长度突破500万,LLEN task-list命令阻塞Redis主线程,导致所有缓存请求超时。换成Kafka后,积压消息存于磁盘,不影响实时服务,且可通过调整Consumer数量弹性伸缩。
3.6 场景六:会话共享(Web集群Session存储)
需求描述:Nginx负载均衡到5台Tomcat,用户登录态需全局共享,要求读写延迟<5ms,支持自动过期。
为什么Redis是事实标准:
- Session数据小(<10KB)、读多写少,Redis内存特性完美匹配;
SET session:abc123 "{json}" EX 1800设置30分钟过期,Redis自动清理;- Spring Session无缝集成,代码零改造。
实操配置要点:
- 序列化:禁用Java原生序列化(体积大、慢),改用Jackson JSON;
- 连接池:
JedisPoolConfig设置maxTotal=200(连接数)、maxIdle=50(空闲连接)、minEvictableIdleTimeMillis=60000(空闲1分钟回收); - 高可用:部署Redis Sentinel,3个Sentinel节点+1主2从,
spring.redis.sentinel.master=master1自动发现主节点。
注意:某教育平台将用户完整Profile存入Session(含头像Base64),单Session超2MB。Redis内存暴涨,GC频繁。整改方案:Session只存
userId,用户信息由业务服务按需查询,内存下降90%。
4. 混合架构实战:当Kafka和Redis必须共存
4.1 经典组合模式:Kafka做“数据管道”,Redis做“实时视图”
真实业务极少非此即彼。某外卖平台订单系统是教科书级混合架构:
- 数据入口:用户下单事件写入Kafka
order-created-topic(强一致、可重放); - 实时处理:Flink消费该Topic,实时计算“商家当前接单量”,结果写入Redis
hash:merchant_orders; - 业务查询:APP端调用API,API直接
HGETALL merchant_orders:2001获取商家实时订单列表(<5ms); - 离线分析:Kafka日志同步到HDFS,Hive做T+1统计。
这个架构里,Kafka和Redis各守其位:Kafka是数据源头的保险箱,保证事件不丢、不错、可追溯;Redis是业务查询的加速器,把计算结果固化为低延迟视图。两者通过Flink桥接,形成“流批一体”闭环。
关键配置验证:
- Flink Job设置
checkpointInterval=60000(1分钟检查点),状态后端用RocksDB(本地磁盘),避免内存溢出; - Redis写入用Pipeline批量(
pipeline.hset("merchant_orders:2001", Map.of("order_1","..."))),将QPS从2000提升至15000; - 监控双链路:Kafka Lag < 100,Redis
used_memory_rss增长平稳(无内存泄漏)。
4.2 避坑指南:混合使用时的三大雷区
雷区一:用Redis缓存Kafka消费位点(Offset)
错误做法:Consumer不提交Offset到Kafka,而是SET offset:group1:topic1 12345存Redis。后果:
- Redis故障时,Offset丢失,Consumer重启后重复消费或跳过消息;
- Kafka的Offset管理是分布式协调服务(ZooKeeper/KRaft)保障的,Redis无法提供同等可靠性。
✅ 正确做法:始终用Kafka内置Offset管理,Redis只存业务结果。
雷区二:Kafka Producer同步刷盘+Redis同步写
为追求“绝对不丢”,设置Kafkalog.flush.interval.messages=1(每条刷盘)和Redisappendfsync always。结果:
- Kafka写入延迟从20ms升至200ms,Producer超时重试;
- Redis AOF fsync阻塞主线程,P99延迟破100ms。
✅ 正确做法:接受“最多一次”(at-least-once)语义,用业务幂等性兜底(如订单号去重)。
雷区三:Redis作为Kafka Consumer的唯一状态存储
Flink Job状态只存Redis,不启用Checkpoint。后果:
- Redis宕机,Flink无法恢复状态,计算结果错乱;
- 无状态容错,Job重启等于重头计算。
✅ 正确做法:Flink状态后端用RocksDB(本地磁盘),Checkpoint存HDFS/S3,Redis仅作结果输出。
4.3 性能压测对比:同一场景下的真实数据
我们用JMeter对两个方案做对比测试(硬件:4核8G云服务器,网络同机房):
- 场景:模拟1000用户并发下单,每秒100个订单事件;
- 方案A:订单写Kafka → Flink实时计算 → 结果写Redis → API查Redis;
- 方案B:订单直接写Redis Hash(
HSET order:1001 status "paid");
| 指标 | 方案A(Kafka+Flink+Redis) | 方案B(纯Redis) | 分析说明 |
|---|---|---|---|
| 端到端延迟(P95) | 128ms | 3.2ms | 方案B赢在路径短;但方案A的128ms包含Flink计算(如风控规则引擎),业务价值更高。 |
| 消息不丢失率 | 100% | 99.92% | 方案B在Redis主从同步延迟期间,主节点宕机导致未同步数据丢失;方案A的ISR机制保障100%。 |
| 峰值QPS | 12000 | 8500 | Kafka分区并行写入优势明显;Redis单线程在高并发写时出现命令排队。 |
| 运维复杂度 | 高(需维护Kafka/Flink/Redis三套) | 低(仅Redis) | 方案A需监控Kafka Lag、Flink Checkpoint、Redis内存;方案B只需看Redis CPU和内存。 |
| 扩展性 | 横向扩展强(加Kafka分区/Flink TaskManager/Redis分片) | 中(Redis分片后一致性难保障) | 方案A各组件可独立扩容;方案B分片后,跨分片事务(如转账)需客户端协调,复杂度陡增。 |
结论:没有银弹,只有权衡。如果你的业务核心是“快”,且能容忍极低概率丢数据(如实时弹幕),选Redis;如果核心是“稳”,且需复杂流式计算,选Kafka+Redis组合。
5. 常见问题与排查技巧实录:来自三次线上事故的血泪总结
5.1 Kafka篇:那些让你凌晨三点爬起来的故障
问题1:Consumer Group消费停滞,Lag持续上涨
- 现象:Kafka Manager显示
consumer_group=order-consumer的Lag从0飙升至50万,且不再下降; - 排查步骤:
kafka-consumer-groups.sh --bootstrap-server x.x.x.x:9092 --group order-consumer --describe查看各Partition的Current Offset和Log End Offset;- 发现
PARTITION 5的Current Offset卡在123456,而Log End Offset是123999,差距443; - 检查Consumer日志,发现
ERROR [Consumer clientId=consumer-1, groupId=order-consumer] Offset commit failed; - 进一步查
max.poll.interval.ms=300000(5分钟),但业务处理单条消息耗时超6分钟(数据库慢查询),触发Rebalance,Consumer被踢出Group。
- 根治方案:
- 优化数据库查询(加索引、改SQL);
- 调大
max.poll.interval.ms=600000; - 或拆分Consumer逻辑:快速消费写入本地队列,另起线程池异步处理。
问题2:Producer发送超时,大量TimeoutException
- 现象:Producer日志疯狂打印
org.apache.kafka.common.errors.TimeoutException: Expiring 20 record(s) for topic-partition; - 排查步骤:
kafka-topics.sh --bootstrap-server x.x.x.x:9092 --describe --topic order-topic查看Partition Leader分布;- 发现
PARTITION 0的Leader在Broker 3,而Broker 3的NetworkProcessorAvgIdlePercent指标低于20%(网卡打满); - 登录Broker 3,
iftop -P 9092确认是其他服务占满带宽。
- 根治方案:
- 网络隔离:Kafka Broker独占网卡;
- 调优
socket.send.buffer.bytes=1048576(1MB缓冲区); - Producer端启用
compression.type=lz4(比snappy压缩率更高,CPU消耗略增)。
问题3:Topic数据莫名消失,Retention未生效
- 现象:
log.retention.hours=168,但某Topic数据只保留24小时; - 排查步骤:
kafka-configs.sh --bootstrap-server x.x.x.x:9092 --entity-type topics --entity-name order-topic --describe查看Topic级别配置;- 发现
retention.ms=86400000(24小时),覆盖了Broker全局配置; - 原因:之前执行过
kafka-configs.sh --alter ... --add-config retention.ms=86400000。
- 根治方案:
- 删除Topic级别配置:
kafka-configs.sh --alter --delete-config retention.ms; - 建立配置审计流程,所有
kafka-configs.sh --alter操作需经审批。
- 删除Topic级别配置:
5.2 Redis篇:那些你以为很简单却栽了跟头的坑
问题1:INFO memory显示used_memory_human=15.2G,但maxmemory=16G,为何OOM?
- 现象:Redis进程被OOM Killer杀死,系统日志
Out of memory: Kill process 12345 (redis-server); - 排查步骤:
INFO memory中used_memory_rss_human=18.5G(RSS实际占用18.5G),超maxmemory;mem_allocator=jemalloc,但used_memory_dataset_perc=92.5%(数据占比92.5%,正常);used_memory_overhead_human=1.3G(开销1.3G),合理;- 关键线索:
allocator_frag_ratio: 1.25(碎片率1.25),allocator_rss_ratio: 1.15(RSS比率1.15),说明内存碎片严重; redis-cli --bigkeys发现list:hot_comments有1000万元素,LLEN命令触发全量扫描,内存碎片加剧。
- 根治方案:
- 对大List分片:
list:hot_comments:1,list:hot_comments:2; - 启用
activedefrag yes(Redis 4.0+),后台自动整理碎片; - 监控
allocator_frag_ratio > 1.4时告警。
- 对大List分片:
问题2:SETNX分布式锁失效,出现超卖
- 现象:秒杀活动库存从100扣减到-5;
- 排查步骤:
- 查看锁逻辑:`SET lock:stock: