什么是Redis的BigKey,如何处理BigKey?

news2024/11/26 12:32:49

一、什么是BigKey

BigKey通常以Key的大小和Key中成员的数量来综合判定,例如:

  • Key本身的数据量过大:一个String类型的Key,它的值为5 MB。
  • Key中的成员数过多:一个ZSET类型的Key,它的成员数量为10,000个。
  • Key中成员的数据量过大:一个Hash类型的Key,它的成员数量虽然只有1,000个但这些成员的Value(值)总大小为100 MB。

那么如何判断元素的大小呢?redis也给我们提供了命令

在这里插入图片描述
推荐值:

  • 单个key的value小于10KB
  • 对于集合类型的key,建议元素数量小于1000

二、BigKey的危害

  • 网络阻塞
    • 对BigKey执行读请求时,少量的QPS就可能导致带宽使用率被占满,导致Redis实例,乃至所在物理机变慢
  • 数据倾斜
    • BigKey所在的Redis实例内存使用率远超其他实例,无法使数据分片的内存资源达到均衡
  • Redis阻塞
    • 对元素较多的hash、list、zset等做运算会耗时较旧,使主线程被阻塞
  • CPU压力
    • 对BigKey的数据序列化和反序列化会导致CPU的使用率飙升,影响Redis实例和本机其它应用

三、如何发现BigKey

1. redis-cli --bigkeys

利用redis-cli提供的–bigkeys参数,可以遍历分析所有key,并返回Key的整体统计信息与每个数据的Top1的big key

命令:redis-cli -a 密码 --bigkeys
在这里插入图片描述

2. scan扫描

自己编程,利用scan扫描Redis中的所有key,利用strlen、hlen等命令判断key的长度(此处不建议使用MEMORY USAGE)
在这里插入图片描述
scan 命令调用完后每次会返回2个元素,第一个是下一次迭代的光标,第一次光标会设置为0,当最后一次scan 返回的光标等于0时,表示整个scan遍历结束了,第二个返回的是List,一个匹配的key的数组

public class JedisTest {
    private Jedis jedis;

    @BeforeEach
    void setUp() {
        // 1.建立连接
        // jedis = new Jedis("192.168.150.101", 6379);
        jedis = JedisConnectionFactory.getJedis();
        // 2.设置密码
        jedis.auth("123321");
        // 3.选择库
        jedis.select(0);
    }

    final static int STR_MAX_LEN = 10 * 1024;
    final static int HASH_MAX_LEN = 500;

    @Test
    void testScan() {
        int maxLen = 0;
        long len = 0;

        String cursor = "0";
        do {
            // 扫描并获取一部分key
            ScanResult<String> result = jedis.scan(cursor);
            // 记录cursor
            cursor = result.getCursor();
            List<String> list = result.getResult();
            if (list == null || list.isEmpty()) {
                break;
            }
            // 遍历
            for (String key : list) {
                // 判断key的类型
                String type = jedis.type(key);
                switch (type) {
                    case "string":
                        len = jedis.strlen(key);
                        maxLen = STR_MAX_LEN;
                        break;
                    case "hash":
                        len = jedis.hlen(key);
                        maxLen = HASH_MAX_LEN;
                        break;
                    case "list":
                        len = jedis.llen(key);
                        maxLen = HASH_MAX_LEN;
                        break;
                    case "set":
                        len = jedis.scard(key);
                        maxLen = HASH_MAX_LEN;
                        break;
                    case "zset":
                        len = jedis.zcard(key);
                        maxLen = HASH_MAX_LEN;
                        break;
                    default:
                        break;
                }
                if (len >= maxLen) {
                    System.out.printf("Found big key : %s, type: %s, length or size: %d %n", key, type, len);
                }
            }
        } while (!cursor.equals("0"));
    }
    
    @AfterEach
    void tearDown() {
        if (jedis != null) {
            jedis.close();
        }
    }

}
3. 第三方工具
  • 利用第三方工具,如 Redis-Rdb-Tools 分析RDB快照文件,全面分析内存使用情况
  • https://github.com/sripathikrishnan/redis-rdb-tools
4. 网络监控
  • 自定义工具,监控进出Redis的网络数据,超出预警值时主动告警
  • 一般阿里云搭建的云服务器就有相关监控页面
  • 在这里插入图片描述

四、如何删除BigKey

BigKey内存占用较多,即便时删除这样的key也需要耗费很长时间,导致Redis主线程阻塞,引发一系列问题。

  • redis 3.0 及以下版本

    • 如果是集合类型,则遍历BigKey的元素,先逐个删除子元素,最后删除BigKey
  • Redis 4.0以后

    • Redis在4.0后提供了异步删除的命令:unlink

五、设计优雅的key结构

Redis的Key虽然可以自定义,但最好遵循下面的几个最佳实践约定:

  • 遵循基本格式:[业务名称]:[数据名]:[id]
  • 长度不超过44字节
  • 不包含特殊字符

例如:我们的登录业务,保存用户信息,其key可以设计成如下格式:
在这里插入图片描述
这样设计的好处:

  • 可读性强
  • 避免key冲突
  • 方便管理
  • 更节省内存: key是string类型,底层编码包含int、embstr和raw三种。embstr在小于44字节使用,采用连续内存空间,内存占用更小。当字节数大于44字节时,会转为raw模式存储,在raw模式下,内存空间不是连续的,而是采用一个指针指向了另外一段内存空间,在这段空间里存储SDS内容,这样空间不连续,访问的时候性能也就会收到影响,还有可能产生内存碎片

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux之多线程(下)——线程控制

文章目录 前言一、POSIX线程库1.概念2.pthread线程库是应用层的原生线程库3.错误的检查 二、线程控制1.创建线程——pthread_createpthread_create函数例子创建一个新线程主线程创建一批新线程 2.获取线程ID——pthread_self3.线程等待——pthread_join4.线程终止——return、p…

SSH服务器详解

文章目录 文字接口连接服务器&#xff1a;SSH服务器连接加密技术简介启动SSH服务SSH客户端连接程序SSH&#xff1a;直接登录远程主机的指令使用案例 服务器公钥记录文件&#xff1a;~/.ssh/known_hosts报错解决 模拟FTP的文件传输方式&#xff1a;SFTP使用案例 文件异地直接复制…

Python主要应用的10大领域你是否感兴趣

原文&#xff1a; Python主要应用的10大领域你是否感兴趣 Python 是一门快速发展的编程语言&#xff0c;其在各个领域的应用也在不断增加。根据 TIOBE 编程语言排行榜&#xff0c;Python 在 2021 年排名第 3&#xff0c;仅次于 Java 和 C。根据 Stack Overflow 的开发者调查报…

圆的基本性质

如何确定一个圆&#xff1f; 两个点&#xff1a; 无法确定一个圆&#xff0c;因为只要到这两个点距离相等的点都可以作为圆心&#xff08;在两个点连线的垂直平分线上&#xff09;&#xff0c;因此可以确定无数个圆 三个点&#xff08;且这三个点不能在同一个直线上&#xf…

【MySQL数据库】事务

事务 一、事务1.1事务的概念 二 、事务的ACID特点2.1原子性2.2一致性&#xff08;Consistency&#xff09;2.3隔离性2.4持久性 三、脏读、不可重复读、幻读、丢失更新3.1脏读3.2不可重复读3.3幻读3.4丢失更新 四、事务的隔离级别 一、事务 1.1事务的概念 事务是一种机制、一个…

二叉堆(大顶堆、小顶堆)学习(使用java手写)

二叉堆 我们现在有一个需求&#xff0c;用来存放整数&#xff0c;要求需要提供三个接口 添加元素获取最大值删除最大值 我们可以用我们熟悉的数据结构去解决这些问题 获取最大值删除最大值添加元素描述动态数组/双向链表O(n)O(n)O(1)O(n) 复杂度太高了&#xff08;有序&#x…

redis -- 持久化存储方案

前言 一般情况下&#xff0c;我们存储到redis的数据&#xff0c;是存储到内存中&#xff0c;再存储到硬盘中(这是基于reb方案来实现)因此一旦强制关机,就直接over了。 硬存和内存的区别和联系&#xff1a; 我们用文本编辑器&#xff0c;里面写入一段话&#xff0c;未保存&am…

检测PPG信号的心跳

基于大佬的代码。 PPG信号靠心率 (HR) 进行估计&#xff0c;主要取决于收缩压峰值检测的准确性。与 ECG 不同&#xff0c;PPG 信号形式简单和特定点 少。低振幅 PPG 信号更容易受到噪声污染和其他不良影响的影响&#xff0c;例如baseline drift和wandering。这是由于信号强度与…

从零开始理解Linux中断架构(3)--Armv8体系架构

首先让我们带着问题进入到armv8架构的学习中。linux中断代码分为两部分entry.S @arch\arm64\kernel\entry.S汇编部分和C代码后续处理。汇编代码中处理最为低级的部分,设置硬件中断向量表,保持当前上下文,切换中断堆栈等任务,这是就如我们嵌入式系统看到那样。 @arch\arm64…

Vue3中div自由拖拽宽度和高度。

Vue3中我们会遇到自由拖拽宽度和高度的页面需求&#xff0c;查看很多方法都无法满足当前需求。下面是我们Vue3版本的代码&#xff0c;非常简单主要构想说粗发拖拽方法&#xff0c;把所需要的div的高宽进行拖拽位置进行监听来加减自身div的px值。直接复制粘贴就可以实现效果。根…

20230615整理(字符设备驱动的内部实现)

1.1 字符设备&#xff1a; 以字节流的形式进行访问&#xff0c;而且只能顺序访问的设备叫做字符设备(比如键盘、鼠标) (块设备&#xff1a;有固定访问大小&#xff0c;可以不按顺序访问的设备&#xff0c;比如U盘、硬盘) 针对字符设备编写的驱动叫做字符设备驱动 1.2 当设备驱…

AI实战营:通用视觉框架OpenMMLab底层视觉与MMEditing

目录 图像超分辨率 Super Resolution ​​​ 深度学习时代的超分辨率算法 卷积网络模型SRCNN FSRCNN SRResNet Super-Resolution CNN, SRCNN, 2014 Fast SRCNN 2016 SRResNet 2016 对抗生成网络介绍Ganerative Adversarial Network 基于GAN的模型SRGAN与ESRGAN S…

vite+vue3+ts 报错和解决办法汇总

1. import path from path 时 ts 报错&#xff1a;模块 ""path"" 只能在使用 "allowSyntheticDefaultImports" 标志时进行默认导入。 在 tsconfig.node.json 文件的 compilerOptions 添加配置 "allowSyntheticDefaultImports": true …

【Python】Django 基础知识 一

系列文章目录 提示&#xff1a;阅读本章之前&#xff0c;请先阅读目录 文章目录 系列文章目录前言安装启动项目查看所有子命令主要文件setting 配置项URL 请求路径path 转换器HttpResponse 输出中文乱码 前言 安装 django-admin startproject xxx项目名启动项目 python manag…

ffmpeg 3.4 windows编译安装

准备工作: msys2安装 官网 MSYS2 下载完成后一直下一步即可&#xff0c;安装完成后windows搜索 MSYS2 启动MSYS2 MINGW64 打开窗口后运行以下命令 下载一些编译需要的东西 #修改源 sed -i "s#mirror.msys2.org/#mirrors.ustc.edu.cn/msys2/#g" /etc/pacman.d/mirr…

拔剑四顾心茫然,绿源直呼“行路难”

老牌两轮电动车品牌绿源上市之旅“多歧路”。 6月7日&#xff0c;北京市市场监督管理局公布北京市电动自行车产品质量监督抽查结果&#xff0c;绿源两款电动自行车因存在问题被点名&#xff0c;充电器和蓄电池、整车质量、控制系统等不符合标准。 而就在一周多以前&#xff0c…

指针(四)

文章内容&#xff1a; 1. 数组参数、指针参数 2. 函数指针 3. 函数指针数组 4. 指向函数指针数组的指针 5. 回调函数 文章内容 1. 数组参数、指针参数 地址需要指针接收&#xff0c;指针的地址需要二级指针接受,以此类推...... 1.1 一维数组传参 #include <stdio.…

【思考】技术人该如何准备晋升答辩?

文章目录 前言一、争取获得答辩机会二、准备答辩素材三、根据素材&#xff0c;编写答辩 PPT四、晋升答辩素材 PPT 的一些建议五、要写答辩稿并加以练习六、调整答辩心态总结 前言 今天跟大家聊下关于技术人该如何准备晋升答辩的话题。 每到年中或者年底&#xff0c;都会有一波…

微前端探秘:初始微前端、现有方案和未来趋势

初识微前端 微前端是什么 概念&#xff1a; 微前端是指存在于浏览器中的微服务。 微前端是一种类似于微服务的架构&#xff0c;它将微服务的理念应用于浏览器端&#xff0c;即将单页面前端应用由单一的单体应用转变为把多个小型前端应用聚合为一体的应用。这就意味着前端应用…

OpenMMLab-AI实战营第二期——6-1. 底层视觉与MMEditing

文章目录 1. 图像超分辨率&#xff08;Super Resolution&#xff09;1.1 概念1.2 目标1.3 应用1.4 分类1.4-2 单图超分的解决思路1.5 ill-posed problem和算子 2. 经典超分辨率算法&#xff08;稀疏编码Sparse Coding&#xff09;2.1 基本概念2.2 基本流程2.3 缺点 3. 深度学习…