缓存与Redis总结

本文探讨秒杀场景下的系统设计原则,包括高可用性、数据一致性和高性能要求。介绍了预热、限制、削峰、隔离及业务兜底方案,如预扣库存、lua脚本实现库存扣减,以及分布式锁的实现细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

秒杀场景

整体要求

  1. 保证系统的高可用和正确性
  2. 一致性:保证秒杀减库存中的数据一致性。
  3. 高性能:涉及大量并发读写,需要支持高并发,从动静分离、热点发现与隔离、请求削峰与分层过滤、服务端极致优化来介绍。

数据预热(预加载)

  1. 将秒杀商品提前加入到缓存系统入ES、Redis等,防止商品超卖和缓存穿透甚至雪崩。

限制

  1. 通过网络代理层、SLB负载均衡层、程序阻流组件与算法(如Guava限流)、前端逻辑过滤等多种手段,防止大流量而造成服务拒绝或阻塞。

削峰

  1. 通过异步通信的设计与解决方案如RPC、MQ等具体实现

隔离

  1. 通过部署隔离方案,在网络拓扑将秒杀系统独立部署、即使异常或宕机,至少不会导致主营业务系统受损或瘫痪,库表分区。

业务兜底方案

一般这种,宁可少卖不可多卖,扣减库存的方式:

  1. 下单减库存
    实现:下单操作绑定减库存操作
    优点:一定不会出现超卖
  2. 付款减库存
    实现:付款时,再扣减库存
    优点:并发高,买家下完单却付不了款
  3. 预扣库存
    实现:下单后,库存保留一段时间,超过时间自动释放,释放后其他买家就可以自己购买了,买家付款前,会校验该订单的库存是否还有保留,如有保留再次尝试预扣。如果预扣失败,则返回失败,预扣成功则付款成功并实际减少库存。
    redis 实现:lua脚本实现 检查库存+扣减库存+返回结果
    mysql 事务实现:
    update 新数量=原数量-购买数量 where 原数量>购买数量 and 商品id = xxx

库存放入缓存中的方法

  1. 多个redis 分别存储部分商品库存。用户请求随机到其中一个redis上,能获取到就获取,不能就返回失败(哪怕另外几个redis中库存存在)
    在这里插入图片描述

分布式锁场景

分布式锁的一般要求

  1. 分布式环境下的一致性
  2. 可重入锁
  3. 尽量阻塞锁
  4. 尽量公平锁
  5. 高可用
  6. 快,性能好

redis中遇到过的问题总结

  1. 主从复制:主从复制的异步复制,从尚未同步完主数据,主挂了,发生主从切换会导致数据的一致性问题。
  2. setnx 成功 expire 设置失败时,会出现key无限存在的问题。使用redis实现分布式锁中,那么会造成死锁。
    解决方案1:set 命令 set key value [EX seconds] [PX milliseconds] [NX|XX}
    EX seconds:失效时长 (s)
    PX milliseconds:失效时长 (ms)
    NX:key不存在时设置value,成功返回OK,失败返回nul
    XX:key存在时设置value,成功返回OK,失败返回nil
    解决方案2:lua脚本实现setnx 与 expire 原子性
  3. key的续约机制
    业务线程需要定期刷新key的有效期,直到使用完毕key过期
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值