【JAVA架构师成长之路】【Redis】第17集:Redis热点Key问题分析与解决方案

30分钟自学教程:Redis热点Key问题分析与解决方案

目标

  1. 理解热点Key的定义、危害及成因。
  2. 掌握本地缓存、分片、读写分离等核心解决策略。
  3. 能够通过代码实现热点Key的读写优化。
  4. 学会熔断降级、自动探测等应急方案。

教程内容

0~2分钟:热点Key的定义与核心影响
  • 定义:某个或少数Key被极端高频访问(如百万QPS),导致Redis单节点负载过高。
  • 典型场景
    • 秒杀商品详情页的库存Key。
    • 热门微博、新闻的评论列表Key。
  • 危害
    • Redis单节点CPU/网络过载,引发性能抖动。
    • 集群模式下数据倾斜,部分节点压力过大。

2~5分钟:代码模拟热点Key场景(Java示例)
// 模拟高频访问热点Key(Java示例)  
@GetMapping("/product/{id}")  
public Product getProduct(@PathVariable String id) {  String key = "product:" + id;  Product product = redisTemplate.opsForValue().get(key);  if (product == null) {  product = productService.loadFromDB(id);  redisTemplate.opsForValue().set(key, product, 1, TimeUnit.HOURS);  }  return product;  
}  // 使用JMeter模拟1000线程并发访问id=1001的接口  

问题复现

  • Redis监控显示product:1001的QPS飙升,单节点CPU占用超过90%。

5~12分钟:解决方案1——本地缓存(Caffeine)
  • 原理:在应用层缓存热点数据,减少对Redis的直接访问。
  • 代码实现(Spring Boot集成Caffeine)
// 配置Caffeine本地缓存  
@Bean  
public CacheManager cacheManager() {  CaffeineCacheManager cacheManager = new CaffeineCacheManager();  cacheManager.setCaffeine(Caffeine.newBuilder()  .expireAfterWrite(10, TimeUnit.SECONDS) // 短暂过期,防止数据不一致  .maximumSize(1000));  return cacheManager;  
}  // 使用本地缓存  
@Cacheable(value = "productCache", key = "#id")  
public Product getProductWithLocalCache(String id) {  return redisTemplate.opsForValue().get("product:" + id);  
}  
  • 优势
    • 将99%的请求拦截在应用层,极大降低Redis压力。
    • 适合读多写少且容忍短暂不一致的场景。

12~20分钟:解决方案2——Key分片(Sharding)
  • 原理:将热点Key拆分为多个子Key,分散访问压力。
  • 代码实现(动态分片)
// 写入时随机分片  
public void setProductShard(Product product, int shardCount) {  String baseKey = "product:" + product.getId();  for (int i = 0; i < shardCount; i++) {  String shardKey = baseKey + ":shard_" + i;  redisTemplate.opsForValue().set(shardKey, product, 1, TimeUnit.HOURS);  }  
}  // 读取时随机选择一个分片  
public Product getProductShard(String id, int shardCount) {  int shardIndex = new Random().nextInt(shardCount);  String shardKey = "product:" + id + ":shard_" + shardIndex;  return redisTemplate.opsForValue().get(shardKey);  
}  
  • 扩展
    • 分片数量可根据并发量动态调整(如QPS每增加1万,分片数+1)。

20~25分钟:解决方案3——读写分离与代理中间件
  • 原理:通过读写分离或代理层(如Twemproxy、Codis)分散请求。
  • 代码实现(读写分离)
// 配置读写分离数据源(Spring Boot示例)  
@Configuration  
public class RedisConfig {  @Bean  public RedisConnectionFactory writeConnectionFactory() {  // 主节点配置  RedisStandaloneConfiguration config = new RedisStandaloneConfiguration("master-host", 6379);  return new LettuceConnectionFactory(config);  }  @Bean  public RedisConnectionFactory readConnectionFactory() {  // 从节点配置  RedisStandaloneConfiguration config = new RedisStandaloneConfiguration("slave-host", 6379);  return new LettuceConnectionFactory(config);  }  @Bean  public RedisTemplate<String, Object> redisTemplate(  @Qualifier("writeConnectionFactory") RedisConnectionFactory writeFactory,  @Qualifier("readConnectionFactory") RedisConnectionFactory readFactory  ) {  RedisTemplate<String, Object> template = new RedisTemplate<>();  template.setConnectionFactory(writeFactory); // 默认写主  template.setDefaultSerializer(new StringRedisSerializer());  return template;  }  
}  // 读操作手动切换至从节点  
public Product getProductFromSlave(String id) {  RedisTemplate slaveTemplate = createSlaveRedisTemplate(); // 从从节点获取连接  return slaveTemplate.opsForValue().get("product:" + id);  
}  

25~28分钟:应急处理方案
  1. 熔断降级(Sentinel熔断示例)
@SentinelResource(value = "getProduct", blockHandler = "handleBlock")  
public Product getProduct(String id) {  // 正常业务逻辑...  
}  public Product handleBlock(String id, BlockException ex) {  return new Product("默认商品", 0.0); // 返回兜底数据  
}  
  1. 动态热点探测与自动扩容
// 热点Key监控器(伪代码)  
public class HotKeyDetector {  private ConcurrentHashMap<String, AtomicLong> counter = new ConcurrentHashMap<>();  @Scheduled(fixedRate = 1000)  public void detectHotKeys() {  counter.entrySet().removeIf(entry -> {  if (entry.getValue().get() > 10000) { // QPS超过1万判定为热点  expandSharding(entry.getKey()); // 触发分片扩容  return true;  }  return false;  });  }  private void expandSharding(String key) {  // 动态增加分片数量并迁移数据  }  
}  

28~30分钟:总结与优化方向
  • 核心原则:分散请求、就近缓存、动态调整。
  • 高级优化
    • 使用Redis Cluster自动分片。
    • 结合一致性哈希算法优化分片策略。
    • 通过监控系统(如Prometheus)实时预警热点Key。

练习与拓展

练习

  1. 使用Caffeine实现一个本地缓存,拦截高频访问的product:1001请求。
  2. 修改分片代码,支持根据Key的QPS动态调整分片数量。

推荐拓展

  1. 研究阿里开源的Tair对热点Key的优化方案。
  2. 学习Redis Cluster的Gossip协议与数据迁移机制。
  3. 探索代理中间件(如Twemproxy)的源码实现。

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

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

相关文章

mysql下载与安装、关系数据库和表的创建

一、mysql下载&#xff1a; MySQL获取&#xff1a; 官网&#xff1a;www.mysql.com 也可以从Oracle官方进入&#xff1a;https://www.oracle.com/ 下载地址&#xff1a;https://downloads.mysql.com/archives/community/ 选择对应的版本和对应的操作系统&#xff…

(数据结构)双向链表

(数据结构)带头双向循环链表 前言 前面链表部分&#xff0c;咱们着重讲解了不带头单向不循环链表&#xff0c;简称单链表。那么链表其实也分很多种类适用于各种各样的场景。通过单链表的学习&#xff0c;其实我们已经大致了解了链表的绝大多数的内容&#xff0c;所以接下来我通…

考研英语语法全攻略:从基础到长难句剖析​

引言 在考研英语的备考之旅中,语法犹如一座灯塔,为我们在浩瀚的英语知识海洋中指引方向。无论是阅读理解中复杂长难句的解读,还是写作时准确流畅表达的需求,扎实的语法基础都起着至关重要的作用。本文将结合有道考研语法基础入门课的相关内容,为大家全面梳理考研英语语法…

【计算机网络入门】应用层

目录 1.网络应用模型 1.1 C/S模型&#xff08;客户端服务器模型&#xff09; 1.2 P2P模型&#xff08;对等模型&#xff09; 2. DNS系统 2.1 域名 2.2 域名解析流程 3. FTP文件传输协议 4. 电子邮件系统 4.1 SMTP协议 4.2 pop3协议 4.3 IMAP协议 4.4 基于万维网的电…

【GoTeams】-3:构建api、重构错误码

本文目录 1. 构建api梳理调用关系api包的作用路由梳理注册Register代码语法 2. 重构错误码 1. 构建api 首先复制project-user&#xff0c;改名为project-api&#xff0c;放在总的路径下&#xff0c;然后在工作区中进行导入。 运行命令go work use .\project-api\新建工作区之…

游戏引擎学习第145天

仓库:https://gitee.com/mrxiao_com/2d_game_3 今天的计划 目前&#xff0c;我们正在完成遗留的工作。当时我们已经将声音混合器&#xff08;sound mixer&#xff09;集成到了 SIMD 中&#xff0c;但由于一个小插曲&#xff0c;没有及时完成循环内部的部分。这个小插曲主要是…

Qt 实现绘图板(支持橡皮擦与 Ctrl+Z 撤销功能)[特殊字符]

作业&#xff1a; 1&#xff1a;实现绘图的时候&#xff0c;颜色的随时调整 2&#xff1a;追加橡皮擦功能 3&#xff1a;配合键盘事件&#xff0c;实现功能 当键盘按 ctrlz的时候&#xff0c;撤销最后一次绘图 头文件.h #ifndef WIDGET_H #define WIDGET_H#include <QWidge…

打造智能聊天体验:前端集成 DeepSeek AI 助你快速上手

DeepSeek AI 聊天助手集成指南 先看完整效果&#xff1a; PixPin_2025-02-19_09-15-59 效果图&#xff1a; 目录 项目概述功能特点环境准备项目结构组件详解 ChatContainerChatInputMessageBubbleTypeWriter 核心代码示例使用指南常见问题 项目概述 基于 Vue 3 TypeScrip…

JPA编程,去重查询ES索引中的字段,对已有数据的去重过滤,而非全部字典数据

一、背景 课程管理界面&#xff0c;查询前&#xff0c;需要把查询元数据给出。 学科列表、学段列表和分类列表&#xff0c;我们把它定义为查询元数据。 一般的业务需求是&#xff1a; 系统维护好多个字典&#xff0c;比如学科、学段等等&#xff0c;相当于属性库。 但是&…

MySQL语法总结

本篇博客说明&#xff1a; &#xff01;&#xff01;&#xff01;.注意此系列都用的是MySQL语句&#xff0c;和SQLServer&#xff0c;PostgreSQL有些细节上的差别&#xff01;&#xff01;&#xff01; 1.每个操作都是先展示出语法格式 2.然后是具体例子 3.本篇注脚与文本顺讯息…

C++ Primer 交换操作

欢迎阅读我的 【CPrimer】专栏 专栏简介&#xff1a;本专栏主要面向C初学者&#xff0c;解释C的一些基本概念和基础语言特性&#xff0c;涉及C标准库的用法&#xff0c;面向对象特性&#xff0c;泛型特性高级用法。通过使用标准库中定义的抽象设施&#xff0c;使你更加适应高级…

go切片定义和初始化

1.简介 切片是数组的一个引用&#xff0c;因此切片是引用类型&#xff0c;在进行传递时&#xff0c;遵守引用传递的机制。切片的使用和数组类似&#xff0c;遍历切片、访问切片的元素和切片的长度都一样。。切片的长度是可以变化的&#xff0c;因此切片是一个可以动态变化的数…

huggingface镜像站hf-mirror的各大AI模型文件下载

一、说明 huggingface地址&#xff1a;https://huggingface.co 但是由于需要国外网络&#xff0c;国内网络延迟较大或无法下载&#xff0c;所以使用国内镜像站&#xff1a; hf-mirror地址&#xff1a;https://hf-mirror.com/ 二、下载方法 1.本机安装了GIT 2.打开HF-Mirro…

Unity Shader 学习15:可交互式雪地流程

本质是 利用顶点变换实现的&#xff1a; 通过一个俯视整个场地的正交摄像机&#xff0c;根据绑定在移动物体身上的粒子系统&#xff0c;来获取物体移动过的位置&#xff0c;记录到一张RenderTexture上作为轨迹图&#xff0c;再通过这张图来对雪地做顶点变换。 1. 由于顶点变换需…

自由学习记录(42)

可能会出现到后面没有教程可以看&#xff0c;走不动&#xff0c;&#xff0c;但还是尝试吧 过程远比想象的要多 那连Live2d的这些脚本怎么控制的都要了解一下 ------------ 文件类型和扩展名 | 编辑手册 | Live2D Manuals & Tutorials 全部导入之后 在这下载SDK Live2D…

LeetCode - 28 找出字符串中第一个匹配项的下标

题目来源 28. 找出字符串中第一个匹配项的下标 - 力扣&#xff08;LeetCode&#xff09; 题目解析 暴力解法 本题如果采用暴力解法的话&#xff0c;可以定义两个指针 i&#xff0c;j&#xff0c;其中 i 指针用于扫描 S&#xff08;haystack&#xff09;串&#xff0c;j 指针…

windows下使用msys2编译ffmpeg

三种方法&#xff1a; 1、在msys2中使用gcc编译 2、在msys2中使用visual studio编译&#xff08;有环境变量&#xff09; 3、在msys2中使用visual studio编译&#xff08;无环境变量&#xff09; 我的环境&#xff1a; 1、msys2-x86_64-20250221 2、vs2015 3、ffmpeg-7.1…

【Python 数据结构 9.树】

我装作漠视一切&#xff0c;其实我在乎的太多&#xff0c;但我知道抓得越紧越容易失去 —— 25.3.6 一、树的基本概念 1.树的定义 树是n个结点的有限集合&#xff0c;n0时为空树。当n大于0的时候&#xff0c;满足如下两个条件&#xff1a; ① 有且仅有一个特定的结点&#xff…

数据结构--AVL树

一、二叉搜索树&#xff08;Binary Search Tree, BST&#xff09; 基本性质 对于树中的每个节点&#xff0c;其左子树中的所有节点值均小于该节点值。其右子树中的所有节点值均大于该节点值。左右子树也分别是二叉搜索树。 极端场景 在极端情况下&#xff0c;如插入节点顺序…

C语言——链表

大神文献&#xff1a;https://blog.csdn.net/weixin_73588765/article/details/128356985 目录 一、链表概念 1. 什么是链表&#xff1f; 1.1 链表的构成 2. 链表和数组的区别 数组的特点&#xff1a; 链表的特点&#xff1a; 二者对比&#xff1a; 二…