🏆本文收录于「滚雪球学SpringBoot」(全网一个名)专栏,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
🎬 前言:数据一致性,真不是那么难!
作为一名全栈开发,我一直在想一个问题------如何让分布式系统又快又稳,尤其是在高并发场景下,保证数据一致性? 。思来想去想了很久,最终发现最靠谱的方案就是通过 Redis 和 Kafka 来搭建最终一致性消息链路。它们像两位"得力助手",帮我解决了好多常见的架构问题------缓存穿透、消息丢失、重复消费等,这些让我乃至大家都头疼的问题,它们都能轻松搞定,不信你可以采访下身边的大佬。
这篇文章是我心得总结所撰,希望能给大家带来一些启发。如果你也有类似的系统设计需求,或者对 Redis 和 Kafka 的结合感兴趣,往下看,我会用我的亲身经验告诉你,如何将这两个"神器"搭配起来,让你的项目分布式架构更加可靠。
🧩 一、分布式架构中的三大一致性挑战
在我们搭建分布式系统时,常常要面临三个关键问题,那三个?
1. 缓存穿透
你肯定知道,缓存是用来减轻数据库压力的。可是当请求的数据不在缓存里时,它就直接查询数据库。很多无效的请求会导致数据库压力增大,尤其是在流量高峰期,简直就是毁灭性的打击,我就遇到过,那时候还是刚接触到一个电商平台,为了迭代才发现项目中存在这个性能压力。
我怎么做的呢?
通过 Redis,我设置了"空值缓存"------当缓存没有数据时,我会把"没有数据"的标志缓存起来。这样,当其他相同请求过来时,就不会再打到数据库了,而是直接从缓存中得到数据返回给前端。是不是挺巧妙的?没错,这也是后来延伸为面试八股文之一!基本都会被拿来问,还伴随其他两问,缓存击穿跟缓存雪崩,此次我就不一一展开讲解了,感兴趣的小伙伴可以私下学习。
2. 消息丢失
其次,对于分布式系统中,消息的传递至关重要。有时候因为网络问题或者系统崩溃,消息很有可能就会丢失。消息丢了,数据就不一致了,这个问题不能小觑,也是非常令人头疼的问题之一。
我怎么做的呢?
通过 消息中间件Kafka ,我可以保证即使消息丢失了,也能从上次的位置重新开始消费。Kafka 的 消息持久化特性就像给每条消息上了"保险",让它不怕丢失。即使系统宕机重启,也能无缝恢复。
3. 重复消费
有时候,消费者可能会重复消费同一条消息,导致重复操作或者数据错误。这会导致很多麻烦,比如订单被重复创建、支付被重复扣费,大家一定都不想看到这种情况。
我怎么做的呢?
每条消息我都会赋予一个 唯一的标识符,然后用 Redis 来记录哪些消息已经处理过。如果消息已经处理过了,就直接跳过,避免重复处理。虽然还有很多其他方式,但是思路就是这么个思路,怎么实现都不要紧,关键是你要有这个解题思路。
🧱 二、Redis:让缓存更加"聪明"
✅ 1. 缓存穿透的聪明解决方案
以前我一直觉得缓存就是用来存数据的,直到有一天,我发现一个问题------如果缓存里找不到数据,怎么办? 难道就直接去数据库查吗?那不就白白增加数据库的压力?
于是我想到了一个方案,缓存空值 !如果查不到数据,我就把"查不到数据"的标记存入缓存,让后续相同的请求直接返回空值,避免频繁查询数据库。
代码示例:缓存穿透
java
public Product getProduct(String productId) {
String key = "product:" + productId;
String cacheResult = redisTemplate.opsForValue().get(key);
if (cacheResult != null) {
if ("NULL".equals(cacheResult)) {
return null; // 如果缓存为NULL,返回空
}
return JSON.parseObject(cacheResult, Product.class); // 从缓存中取数据
}
Product product = productRepository.findById(productId);
if (product != null) {
redisTemplate.opsForValue().set(key, JSON.toJSONString(product), 300, TimeUnit.SECONDS); // 缓存正常数据
} else {
redisTemplate.opsForValue().set(key, "NULL", 60, TimeUnit.SECONDS); // 缓存空值,避免后续查数据库
}
return product;
}
这个方法不仅避免了数据库的重复查询,还能提升系统的性能,效果杠杠的!
✅ 2. 幂等性:防止重复消费
在一些关键操作中,比如 订单处理 ,我们不希望一个消息被重复处理两次。重复操作不仅会造成资源浪费,还可能导致数据不一致。
我的做法是:每条消息都会有一个唯一的 ID,处理完消息之后,我会用 Redis 来记录这个 ID,下次再遇到相同的消息时,就跳过不再处理。
代码示例:防止重复消费
java
public void processOrder(OrderMessage message) {
String redisKey = "order:" + message.getId();
Boolean exists = redisTemplate.hasKey(redisKey);
if (Boolean.TRUE.equals(exists)) {
System.out.println("重复消息,跳过处理");
return; // 如果已经处理过,就跳过
}
// 处理订单
orderService.saveOrder(message);
// 设置标记,表示消息已经处理过
redisTemplate.opsForValue().set(redisKey, "processed", 1, TimeUnit.HOURS);
}
幂等性保证 :通过这种方式,我确保了 即使消息被多次消费,也不会出问题。这是我在实际项目中用过的一个很简单但非常有效的技巧,分享给大家。
🚀 三、Kafka:消息的"保障"
✅ 1. Kafka 保证消息的可靠传递
想象一下,假设我们有一个 订单处理系统 ,用户下单时,我们需要把订单信息传递给其他服务。万一消息丢了,整个订单流程就乱套了!这个问题对我们来说至关重要。
Kafka 是一个高可靠的消息队列,它保证了消息 持久化 和 不丢失 。即使某个消费者失败,消息仍然保留在 Kafka 中,我们可以通过 offset 重新消费消息。
代码示例:Kafka 消费
java
@KafkaListener(topics = "user_behavior", groupId = "analyze_group")
public void consume(ConsumerRecord<String, String> record, Acknowledgment ack) {
try {
UserBehaviorEvent event = JSON.parseObject(record.value(), UserBehaviorEvent.class);
userBehaviorService.process(event); // 处理业务逻辑
ack.acknowledge(); // 手动提交 offset
} catch (Exception e) {
log.error("消费失败,将进行重试", e);
// 不提交 offset,Kafka 会重新投递消息
}
}
这里的 ack.acknowledge() 让我们手动控制消息的消费状态,确保消费完毕才能提交,保证消息不丢失。
🧩 四、最终一致性链路架构设计
结合 Redis 和 Kafka ,我们可以创建一个既高效又可靠的 最终一致性消息链路,处理高并发、高可用场景下的复杂需求。
场景示例:用户下单 ➜ 异步发货 ➜ 推送通知
- 用户下单:订单服务将订单写入数据库。
- Kafka 通知 :写入 Kafka
order_created
主题,通知其他服务。 - 发货服务:监听 Kafka,处理发货。
- 通知服务:监听 Kafka,推送消息给用户。
- Redis 幂等:通过 Redis 防止重复消费。
架构图:最终一致性链路
这里我们将整个链路通过流程图的形式,给大家演示下,以辅助大家理解。

✅ 链路中的容错机制:
-
Kafka 提供消息持久化 ➜ 防丢失
-
Redis 记录处理状态 ➜ 防重复
-
幂等逻辑处理 ➜ 防数据错误
-
Offset 控制 ➜ 可重播 ➜ 自恢复

🎯 五、总结:Redis + Kafka,强强联手
我们通过结合 Redis 和 Kafka ,就能够轻松解决 缓存穿透 、消息丢失 、消费幂等性 等常见问题,实现系统的高可用和高可靠性。
从我个人的经验来说,这两个中间件的结合,不仅可以提升系统的稳定性,还能极大地简化我们处理分布式数据一致性时的复杂度。
希望这篇文章对大家有所帮助!如果你们在设计自己的系统时遇到类似问题,试试 Redis + Kafka 这两组合吧,你会发现它们真的是非常强大的搭档。
如果你有任何问题,随时跟我交流,我们一起探讨更好的解决方案!
📣 关于我
我是bug菌,CSDN | 掘金 | InfoQ | 51CTO | 华为云 | 阿里云 | 腾讯云 等社区博客专家,C站博客之星Top30,华为云多年度十佳博主&最具价值贡献奖,掘金多年度人气作者Top40,掘金等各大社区平台签约作者,51CTO年度博主Top12,掘金/InfoQ/51CTO等社区优质创作者;全网粉丝合计 30w+ ;硬核微信公众号「猿圈奇妙屋」,欢迎你的加入!免费白嫖最新BAT互联网公司面试真题、4000G PDF电子书籍、简历模板等海量资料,你想要的我都有,关键是你不来拿。
-End-