文章目录

  • 缓存全景图
  • Pre
  • 背景与目标说明
  • 缓存原则与设计思路
  • 缓存体系架构
  • 缓存预热与缓存预加载
  • 库存操作与缓存结合
  • 防刷、限流与缓存
  • 缓存一致性与失效
  • 异步落地与消息队列
  • 监控与指标
  • 容灾与扩展
  • 示例
  • 小结

在这里插入图片描述


缓存全景图

在这里插入图片描述


Pre

分布式缓存:缓存设计三大核心思想

分布式缓存:缓存的三种读写模式及分类

分布式缓存:缓存架构设计的“四步走”方法

分布式缓存:缓存设计中的 7 大经典问题_缓存失效、缓存穿透、缓存雪崩

分布式缓存:缓存设计中的 7 大经典问题_数据不一致与数据并发竞争

分布式缓存:缓存设计中的 7 大经典问题_Hot Key和Big Key

分布式缓存:三万字详解Redis

分布式缓存:ZSET → MGET 跨槽(cross‐slot)/ 并发 GET解决思路

分布式缓存:CAP 理论在实践中的误区与思考

分布式缓存:BASE理论实践指南


每日一博 - 闲聊“突发流量”的应对之道

背景与目标说明

短时间内流量剧增,后端需应对大量无效请求并快速响应成功请求。核心思路是:将绝大多数请求在上游拦截或由缓存处理,不让每个请求直击后端数据库和核心服务,同时保证库存操作原子、正确。缓存体系是关键环节,可极大提高查询速度、减轻数据库压力、提升用户体验。


缓存原则与设计思路

  • 上游过滤、预处理优先:在到达核心库存/下单逻辑前,用缓存快速判断活动状态、库存是否售罄、用户是否有资格、是否已下单等,避免无效请求流向下游。
  • 缓存优先、后端降级:常见数据(商品详情、秒杀配置信息)使用缓存读取;若缓存不可用或命中率低,再访问后端,并在适当时机补回缓存。
  • 分层缓存设计:结合 CDN、应用本地缓存(如 Guava Cache、Caffeine)、分布式缓存(如 Redis)形成分层架构,提升不同层次的访问性能、减少网络开销。
  • 预热与主动加载:在秒杀开始前将核心数据全部加载到缓存,避免高并发时缓存穿透或缓存击穿。
  • 缓存与业务逻辑深度结合:库存变更、下单流程、限流防刷等都需要依赖缓存进行快速决策与计数。
  • 异步落地与最终一致性:核心数据更新(库存、订单记录)不能全部同步写数据库,而是借助消息队列异步落地,以防 DB 冲击;同时需要设计保证最终一致性方案。

缓存体系架构

  1. CDN 静态资源缓存

    • 将秒杀页面的静态内容(HTML 静态化、CSS/JS、商品图片等)放到 CDN,用户直接访问静态页面或静态接口,减轻 Web 层压力。
    • 对动态接口(数据接口)可采用前端灰度控制:活动未开始状态下按钮置灰,不显示接口入口。
  2. 应用层本地缓存

    • 对热点数据(如秒杀开关、限流阈值、少量黑名单白名单)放在进程内缓存(Caffeine/Guava Cache)。读取极快,减少对 Redis 的调用次数。
    • 需要注意:本地缓存容量有限,适合少量常变配置或短期内不频繁更新的数据。更新时通过消息或主动失效机制通知各实例。
  3. 分布式缓存(Redis)

    • 商品信息缓存:秒杀商品详情,包含商品ID、名称、秒杀价格、开始/结束时间等。通常在秒杀前预加载到 Redis HASH 或简单 Key-Value。
    • 库存缓存:核心的秒杀库存计数,通常以单个 Key 记录剩余库存(整数)。
    • 访问记录缓存:记录 IP、用户请求次数、是否已下单等,用于防刷、限流、判重。
    • 布隆过滤器:保存所有合法秒杀商品 ID,防止恶意请求或错误 ID 访问穿透到 DB。可借助 RedisBloom、Guava Bloom 结合本地缓存等。
    • 黑名单/白名单缓存:提前识别可疑用户或优先用户。
    • 限流令牌/计数器:分布式限流时用 Redis 计数快速判断单用户或全局并发量。

缓存预热与缓存预加载

  • 商品信息预热

    • 在秒杀开始前,调度服务将所有秒杀商品信息加载到 Redis,例如:SET seckill:product:ID:info JSON(...)HSET seckill:products ID JSON
    • 本地缓存也可加载少量配置数据,如活动时间和阈值。
  • 库存预热

    • 将秒杀商品原始库存值加载到 Redis:SET seckill:product:ID:stock N。或使用 DECR 初始化前,使用 SECKILL_STOCK_ID = initialStock
  • 布隆过滤器预热

    • 构建合法商品 ID 的布隆过滤器,加载到 Redis 或应用本地,保证高并发检查时快速拒绝非法 ID 请求。
  • 访问记录/黑名单预热

    • 从历史数据中分析疑似刷单用户,将其 ID 缓存到 Redis SET 或本地缓存,在秒杀开始时即限制。

库存操作与缓存结合

  • 原子库存扣减

    • 使用 Redis 原子操作:DECRDECRBY。但需避免库存变为负数:可在 Lua 脚本中判断并扣减:

      local stock = tonumber(redis.call('GET', KEYS[1]))
      if not stock or stock <= 0 thenreturn -1
      end
      redis.call('DECR', KEYS[1])
      return stock - 1
      
    • 该脚本可确保库存不会被超卖。

  • 本地内存计数优化

    • 若多实例并发压力极高,可在应用内维护一个本地剩余库存近似值,一旦 Redis 扣减失败,再走拒绝;本地计数可减少对 Redis 的访问,但需定期校正。
  • 预减库存思路

    • 在确认用户请求合法、限流通过后,先在缓存中原子预减库存,再异步将下单请求消息入队列供后续落地。
    • 若预减成功,则返回给用户“抢购成功,排队中”;若失败,立即返回“库存不足”。
  • 库存回滚

    • 在队列消费并落地时,如果因为用户超时未支付或其它原因需要回滚,应再 Redis 上执行原子增库存操作;需谨慎设计,避免与高并发预减冲突。
  • 可靠性保障

    • 结合消息队列确保预减库存与后续落地事务最终一致:如消费者处理失败时,要发送回滚消息或补偿。

防刷、限流与缓存

  • 布隆过滤器

    • 拦截非法商品 ID。
  • 访问记录缓存

    • Redis 中维护用户或 IP 的请求次数计数器(如每秒/每分钟请求数),超过阈值则拒绝;可用 Redis INCR + EXPIRE 实现滑动窗口近似限流。
  • 令牌桶/漏桶

    • 对全局或单用户并发请求总量限流,使用 Redis 简单计数或者更复杂的分布式令牌桶实现。
  • 用户状态缓存

    • 记录用户是否已成功下单,若已下单则直接拒绝重复请求。
  • 黑名单/白名单

    • 在秒杀前通过历史行为或风控系统导入可疑用户 ID 到 Redis SET,秒杀期间立即拒绝或降级处理。
  • 验证码或人机验证

    • 在热点时刻加验证码或滑动验证,缓存验证结果并短时记录,减少自动化脚本。

缓存一致性与失效

  • 缓存更新策略

    • 商品信息、配置类数据更新相对较少,可采用直接更新 Redis,并通过消息通知或发布-订阅让各实例清理本地缓存。
  • 库存缓存

    • 库存只在预热时加载且通过 Redis 原子操作变更,不需额外读取 DB 做强一致。要保证 Redis 不宕机:使用 Redis 集群或哨兵,保证高可用。
  • 延迟双删

    • 若需要同步更新 DB 或外部系统(如活动配额调整),在更新 DB 后删除缓存,再等待短暂时间后再次删除,防止并发更新时读到旧缓存。
  • 异步同步

    • 一般秒杀库存变更由缓存为主,DB 更新通过消息异步落地;若需要强一致性校验,可在流量低峰期做全量对账。
  • 缓存失效时间

    • 对于商品信息和活动配置可以设置较长 TTL 或使用永久缓存并在更新时主动更新,对限流计数器、访问记录计数器则使用短 TTL(如秒级或分钟级)。

异步落地与消息队列

  • 削峰填谷

    • 预减库存后,将下单请求封装成消息发送到消息队列(如 RocketMQ、Kafka、RabbitMQ)。消费者逐条消费处理:验证库存(可再次检查)、创建订单、写入数据库、调用支付等。
  • 失败重试与回滚

    • 消费失败:发送到死信队列或重新入队;若业务判断需回滚库存,发布回滚消息。
  • 最终一致性

    • 因异步,可能存在短暂不一致,但可借助定期对账、补偿机制保证库存数据和订单数据最终一致。
  • 监控消息积压

    • 实时监控队列堆积长度,若积压过多,可能需要临时扩容消费者或降级限流,防止积压过大导致超时。

监控与指标

  • 缓存相关指标

    • Redis 命中率、特定 Key 访问 QPS、内存使用、慢查询日志。
    • 本地缓存命中率、失效次数、缓存清理频次。
  • 限流与防刷指标

    • 拒绝请求数、限流触发率、异常请求来源统计。
  • 队列与落地

    • 队列长度、消费者处理速率、失败重试次数。
  • 业务质量指标

    • 成功下单率、支付转化率、库存扣减与订单创建比对、超卖事件监控。
  • 自动告警

    • 当 Redis 使用接近阈值、本地缓存异常、消息队列积压或消费者宕机时,及时告警并启动预案。

容灾与扩展

  • Redis 高可用

    • 使用 Redis 集群或主从 + 哨兵,保证单点故障可自动切换;多 AZ 部署。
  • 读写分离

    • 对某些只读查询场景(非核心秒杀流程)可以走只读节点,核心库存操作必须走主节点。
  • 本地缓存降级

    • 若 Redis 不可用,应用层需检测并降级:可返回系统繁忙提示或依靠本地缓存提供部分信息,避免直接崩溃。
  • 熔断和退避

    • 当下游(如数据库或消息队列)压力过大时,熔断部分非核心功能,优先保证秒杀核心流程;可动态调整限流策略。
  • 弹性扩缩容

    • 秒杀前预估容量,提前扩容实例和缓存集群;秒杀后快速缩容。

示例

伪代码示例(以 Java + SpringBoot + Lettuce/Jedis 为例):

  1. 库存预热:

    @Component
    public class SeckillPreload {@Autowiredprivate StringRedisTemplate redisTemplate;@PostConstructpublic void preload() {List<Product> products = fetchSeckillProductsFromDB();for (Product p : products) {String keyInfo = "seckill:product:" + p.getId() + ":info";redisTemplate.opsForValue().set(keyInfo, toJson(p));String keyStock = "seckill:product:" + p.getId() + ":stock";redisTemplate.opsForValue().set(keyStock, String.valueOf(p.getStock()));// 可设置TTL为活动结束后一段时间自动过期redisTemplate.expire(keyInfo, Duration.ofHours(2));redisTemplate.expire(keyStock, Duration.ofHours(2));}// 布隆过滤器预热略}
    }
    
  2. 预减库存 Lua 脚本:

    String lua = "local stock = tonumber(redis.call('GET', KEYS[1]));"+ " if not stock or stock <= 0 then return -1; end;"+ " redis.call('DECR', KEYS[1]);"+ " return stock - 1;";
    // 执行时通过 RedisScript
    
  3. 下单接口(简化流程):

    @RestController
    public class SeckillController {@Autowired private StringRedisTemplate redisTemplate;@Autowired private RedisScript<Long> stockLuaScript;@Autowired private MessageQueueProducer mqProducer;@PostMapping("/seckill/{productId}")public ResponseEntity<?> seckill(@PathVariable Long productId, @RequestParam Long userId) {// 1. 活动时间检查(本地缓存或Redis)if (!isInSeckillTime(productId)) {return ResponseEntity.badRequest().body("活动未开始或已结束");}// 2. 布隆过滤器检查:略// 3. 防刷检查:检查用户请求频次、本地或Redis限流if (isUserBlacklisted(userId)) {return ResponseEntity.status(429).body("请求过于频繁");}// 4. 是否已下单检查String orderFlagKey = "seckill:order:flag:" + productId + ":" + userId;if (redisTemplate.hasKey(orderFlagKey)) {return ResponseEntity.badRequest().body("已参与过秒杀");}// 5. 预减库存String stockKey = "seckill:product:" + productId + ":stock";Long stockResult = redisTemplate.execute(stockLuaScript, Collections.singletonList(stockKey));if (stockResult == null || stockResult < 0) {return ResponseEntity.ok("秒杀已售罄");}// 6. 设置用户已下单标志(短期内有效,防重复)redisTemplate.opsForValue().set(orderFlagKey, "1", Duration.ofHours(1));// 7. 发送异步下单消息SeckillMessage msg = new SeckillMessage(userId, productId, System.currentTimeMillis());mqProducer.send(msg);// 8. 返回“排队中”或“已抢到,处理中”return ResponseEntity.ok("抢购成功,排队处理中");}
    }
    
  4. 消息消费者示例:

    @Component
    public class SeckillConsumer {@Autowired private OrderService orderService;@Autowired private InventoryService inventoryService;@Autowired private StringRedisTemplate redisTemplate;@RabbitListener(queues = "seckillQueue")public void process(SeckillMessage msg) {Long userId = msg.getUserId();Long productId = msg.getProductId();// 双重库存校验(可选)if (!inventoryService.checkStock(productId)) {// 回滚:增加 Redis 库存redisTemplate.opsForValue().increment("seckill:product:" + productId + ":stock");return;}// 创建订单、写 DBOrder order = orderService.createOrder(userId, productId);// 支付等后续可异步}
    }
    
  5. 限流与防刷示例:

    • 使用 Redis INCR + EXPIRE 记录每个用户/IP 在短时间窗口内请求次数;超过阈值则拒绝。
    • 可结合本地缓存维护黑白名单及配置。

仅为思路演示,生产环境需考虑更全面的异常处理、超时、幂等、日志、追踪、分布式事务或补偿流程等。


小结

  • 秒杀前准备:评估流量峰值,扩容 Redis/应用实例、消息队列;完成缓存预热并压力测试;准备监控告警;风控名单预加载。
  • 秒杀中运行:实时监控缓存、队列、后端服务状态;动态调整限流策略;快速响应异常。
  • 秒杀后收尾:回顾队列积压与处理情况,对账库存与订单;清理临时缓存;总结经验。
  • 持续演进:基于日志和监控数据优化缓存策略、防刷算法、扩容策略;升级组件版本;优化运维自动化。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/87647.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/87647.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/87647.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

华为云Flexus+DeepSeek征文|CCE容器高可用部署搭建Dify-LLM平台部署AI Agent

华为云FlexusDeepSeek征文&#xff5c;CCE容器高可用部署搭建Dify-LLM平台部署AI Agent 前言 Dify是一款开源的大语言模型应用开发平台&#xff0c;融合了后端即服务和LLMOps的理念&#xff0c;使开发者可以快速搭建生产级的生成式AI应用&#xff0c;本文将详细介绍如何使用华…

Postman 的 Jenkins 管理 - 手动构建

目录 一、准备工作 二、postman 项目脚本准备并导出 1. 打开已完成并测试无误的 postman 项目脚本。 再次执行测试。 ​编辑2. 导出&#xff08; 测试用例集、环境变量 两个文件&#xff09;**“不 支 持 中 文”** —— 全部改成英文&#xff01; ​编辑3. 文件所在目录…

音视频之H.264/AVC解码器的原理和实现

系列文章&#xff1a; 1、音视频之视频压缩技术及数字视频综述 2、音视频之视频压缩编码的基本原理 3、音视频之H.264/AVC编码器原理 4、音视频之H.264的句法和语义 5、音视频之H.264/AVC解码器的原理和实现 6、音视频之H.264视频编码传输及其在移动通信中的应用 7、音视…

【智能安全帽新升级】搭载VTX316TTS语音合成芯片,让安全“听得见”!

在工地轰鸣的机械声中&#xff0c;一句清晰的指令可能比任何文字都更有力量。 当智能安全帽遇上VTX316语音合成芯片&#xff0c;安全防护从“被动响应”进化为“主动交互”&#xff0c;为高危行业戴上了一顶“会说话的智慧大脑”&#xff01; 传统安全帽的“沉默”危机 在建筑…

【目标检测】非极大值抑制(NMS)的原理与实现

&#x1f9d1; 博主简介&#xff1a;曾任某智慧城市类企业算法总监&#xff0c;目前在美国市场的物流公司从事高级算法工程师一职&#xff0c;深耕人工智能领域&#xff0c;精通python数据挖掘、可视化、机器学习等&#xff0c;发表过AI相关的专利并多次在AI类比赛中获奖。CSDN…

DB-GPT启动提示please install by running `pip install cryptography`

DB-GPT项目需要 cryptography 库来处理加密功能&#xff0c;但环境中没有安装它。cryptography 是一个用于安全和加密操作的Python库&#xff0c;许多项目&#xff08;包括DB-GPT&#xff09;依赖它来处理敏感数据的加密存储。 解决方案 1. 安装 cryptography 库 在激活的环…

局域网文件共享及检索系统

标题:局域网文件共享及检索系统 内容:1.摘要 随着信息技术的飞速发展&#xff0c;局域网在企业、学校等场景中得到广泛应用&#xff0c;大量文件在局域网内存储和流转。然而&#xff0c;目前局域网内文件共享与检索存在效率低、管理困难等问题。本文旨在设计并实现一个高效的局…

Spring Boot医疗系统高并发难题:达梦数据库死锁排查与优化实战

Spring Boot医疗系统高并发难题:达梦数据库死锁排查与优化实战 引言:医疗系统中的并发挑战 在现代医疗系统中,检查申请处理是关键业务场景之一,每天需要处理数以万计的检查记录。当多个操作同时更新同一患者的申请状态时,数据库层面的死锁问题成为高并发环境下的典型痛点…

Go语言中的文件与IO:bufio 和 scanner

Go 标准库中的 bufio 包提供了带缓冲的读写功能&#xff0c;可以显著提高文件和数据处理效率。而 bufio.Scanner 则是读取文本文件中每一行的利器&#xff0c;常用于日志、配置等文本处理场景。 一、为什么使用 bufio&#xff1f; 直接对文件进行 os.File.Read() 或 os.File.W…

ABP微服务架构中网关层NullReferenceException问题解析与HTTP配置优化

ABP微服务架构中网关层NullReferenceException问题解析与HTTP配置优化 一、网关层System.NullReferenceException问题解析 1.1 问题现象与原因分析 在ABP微服务架构开发过程中&#xff0c;网关层启动后调用微服务接口时出现以下异常&#xff1a; System.NullReferenceExcep…

啊啊啊啊啊啊啊啊code

前序遍历和中序遍历构建二叉树 /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) { this.val val; }* TreeNode(int val, TreeNode left, TreeNod…

【算法 day06】LeetCode 454.四数相加II | 15. 三数之和 | 18. 四数之和

454.四数相加II 题目链接 | 文档讲解 |视频讲解 : 链接 1.思路&#xff1a; 0.定义一个count&#xff0c;计算最终出现的次数 1.先遍历nums1和nums2,求出两者的和&#xff0c;map的key是和&#xff0c;value是出现的次数 2.再遍历nums3和nums4&#xff0c;求出0-两者的和 3…

【项目实训】【项目博客#09】HarmonySmartCodingSystem系统后端智能API检索与代码助手实现(6.2-6.15)

【项目实训】【项目博客#09】HarmonySmartCodingSystem系统后端智能API检索与代码助手实现&#xff08;6.2-6.15&#xff09; 文章目录 【项目实训】【项目博客#09】HarmonySmartCodingSystem系统后端智能API检索与代码助手实现&#xff08;6.2-6.15&#xff09;项目博客概述一…

【JVM】- 类加载与字节码结构3

类加载阶段 1. 加载 加载&#xff1a;将类的字节码载入方法区中&#xff0c;内部采用C的instanceKlass描述java类。如果这个类的父类还没加载&#xff0c;则先加载父类加载和链接可能是交替运行的 通过全限定名获取字节码 从文件系统&#xff08;.class 文件&#xff09;、JA…

Qt蓝图式技能编辑器状态机模块设计与实现

设计概述 这个模块是一个基于Qt的蓝图式技能编辑器状态机&#xff0c;主要用于游戏开发中的技能状态管理。核心功能包括&#xff1a; 状态节点&#xff08;开始、结束、普通状态&#xff09;的可视化 状态间连线的绘制与管理 状态转换逻辑的可视化编辑 动作选择与配置 核…

Unity AR识别物体的内容语音读取+使用说明功能

因之前一直在开发项目&#xff0c;断断续续写了一点博客&#xff0c;最后统一写了一下博客记录学习内容。 可以看到我的工作一直在进行。 目录 一、识别内容语音读取 二、点击齿轮按钮弹出使用说明界面 开发步骤 1. 创建齿轮按钮 UI 2. 创建使用说明面板 UI 3. 编写控制…

Unable to start embedded Tomcat

通常是由于xml文件配置错误导致 1. mapper 指向错误 <resultMap id"Waybill" type"c.Waybill"> 2. 字段类型错误 <result column"wstatus" property"stus" javaType"TINYINT"/>TINYINT 是数据库类型<resu…

Mac电脑 充电限制保护工具 AlDente Pro

AlDente Pro一款充电限制保护工具&#xff0c;是可以限制最大充电百分比来保护电池的工具。 锂离子和聚合物电池&#xff08;如 MacBook 中的电池&#xff09;在40&#xff05; 至 80&#xff05; 之间运行时&#xff0c;使用寿命最长。 始终将电池电量保持在 100&#xff05…

KungfuBot——基于物理约束和自适应运动追踪的人形全身控制PBHC,用于学习打拳或跳舞(即RL下的动作模仿和运控)

前言 昨天618&#xff0c;我司「七月在线」同事朝阳为主力&#xff0c;我打杂&#xff0c;折腾了整整一天&#xff0c;终于可以通过VR摇操宇树G1了——当然&#xff0c;摇操是为了做训练数据的采集&#xff0c;从而方便 下一步的模型(策略)训练&#xff0c;最终实现机器人自主…

Kafka多副本机制

副本和副本因子 Kafka 会为每个 Partition 创建多个副本。这些副本分布在不同的 Broker 上。副本确保了数据的冗余存储&#xff0c;即使某个 Broker 宕机或失效&#xff0c;其他副本可以继续提供服务。 副本因子指的是每个 Partition 有多少个副本。副本因子的设置决定了一个…