库存与Redis同步机制详解,实现数据实时更新与一致性保障

文章导读
结论:库存与Redis同步的核心是通过双写+异步队列机制实现。订单创建时,先扣减数据库库存,再写Redis库存;同时异步推送变更到Redis队列,确保Redis实时更新。最终一致性由定时任务兜底校准,避免超卖。代码示例:public void deductStock(Order order) { // 数据库扣库存 boolean success = stockMapper.updateStock
📋 目录
  1. 方案一:双写一致性
  2. 方案二: Canal + Redis Binlog
  3. 方案三:消息队列异步同步
  4. 方案四:Redis Lua脚本原子扣减
  5. 方案五:分布式锁 + 预减库存
  6. 一致性保障最佳实践
A A

结论:库存与Redis同步的核心是通过双写+异步队列机制实现。订单创建时,先扣减数据库库存,再写Redis库存;同时异步推送变更到Redis队列,确保Redis实时更新。最终一致性由定时任务兜底校准,避免超卖。代码示例:public void deductStock(Order order) { // 数据库扣库存 boolean success = stockMapper.updateStock(order.getSkuId(), order.getNum()) > 0; if (success) { redisTemplate.opsForValue().decrement("stock:" + order.getSkuId(), order.getNum()); rabbitTemplate.convertAndSend("stock.queue", order); } }

方案一:双写一致性

库存扣减时,先更新MySQL库存表,如果成功,再更新Redis库存key。如果Redis更新失败,不影响业务,但会产生不一致。通过异步任务,每5分钟对比MySQL和Redis库存差值,进行补齐。这样既保证了实时性,也保障了最终一致性。

方案二: Canal + Redis Binlog

使用Canal监听MySQL binlog,库存表变更时,Canal解析binlog并推送到Redis。配置Canal server连接MySQL,订阅库存表。Java客户端接收事件:@CanalEventListener public void onEvent(BinlogEntry event) { if (event.getTableName().equals("stock")) { redisTemplate.opsForValue().set("stock:" + event.getColumn("id").getValue(), event.getColumn("count").getValue()); } } 实现了数据实时同步。

库存与Redis同步机制详解,实现数据实时更新与一致性保障

方案三:消息队列异步同步

库存变更后,发送RocketMQ消息到同步队列。消费者消费消息更新Redis。支持重试和死信队列,避免消息丢失。代码:@RocketMQMessageListener(topic = "stock-update") public class StockSyncListener implements RocketMQListener { public void onMessage(Order order) { redisTemplate.opsForHash().put("stock", order.getSkuId(), order.getStock()); } } 确保高可用。

方案四:Redis Lua脚本原子扣减

使用Lua脚本实现库存扣减原子性:local stock = redis.call('get', KEYS[1]) if stock and tonumber(stock) >= tonumber(ARGV[1]) then redis.call('set', KEYS[1], stock - ARV[1]) return 1 else return 0 end 结合数据库后置校验,双重保障不超卖。

库存与Redis同步机制详解,实现数据实时更新与一致性保障

方案五:分布式锁 + 预减库存

秒杀场景用Redisson分布式锁:RLock lock = redisson.getLock("lock:" + skuId); lock.lock(); try { Long stock = redisTemplate.opsForValue().decrement("stock:" + skuId); if (stock < 0) { redisTemplate.opsForValue().increment("stock:" + skuId); throw new Exception(); } // 异步更新DB } 防止并发超卖。

库存与Redis同步机制详解,实现数据实时更新与一致性保障

一致性保障最佳实践

1. 读Redis多级缓存,穿透查DB;2. 写DB后异步更新Redis;3. MQ可靠消息确保不丢;4. 定时对账任务兜底;5. 热点key本地缓存降Redis压力。这样库存实时更新,最终强一致。

FAQ
Q: Redis和DB不一致怎么处理?
A: 异步队列补齐 + 定时任务对账,每分钟运行。
Q: 高并发秒杀怎么防超卖?
A: Redis Lua原子扣减 + DB后校验 + 分布式锁。
Q: Redis宕机库存怎么保证?
A: 降级读DB,全链路监控自动切换。
Q: 怎么监控同步延迟?
A: 埋点记录时间差,Prometheus告警超过1s。