Redis 扫描 bigKey

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: Redis 扫描 bigKey

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


  • Key本身的数据量过大:一个String类型的Key,它的值为5 MB


  • Key中的成员数过多:一个ZSET类型的Key,它的成员数量为10,000个


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


BigKey的危害


  • 网络阻塞


  • 对BigKey执行读请求时,少量的QPS就可能导致带宽使用率被占满,导致Redis实例,乃至所在物理机变慢


  • 数据倾斜


  • BigKey所在的Redis实例内存使用率远超其他实例,无法使数据分片的内存资源达到均衡


  • Redis阻塞


  • 对元素较多的hash、list、zset等做运算会耗时较旧,使主线程被阻塞


  • CPU压力


  • 对BigKey的数据序列化和反序列化会导致CPU的使用率飙升,影响Redis实例和本机其它应用


工具类扫描出 bigKey


package com.icsomserver.business.test;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.ScanResult;
import java.util.List;
public class JedisTest {
    private Jedis jedis;
    @BeforeEach
    void setUp() {
        // 1.建立连接
        jedis = new Jedis("127.0.0.1", 6379);
        // 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;
        int 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 != 0);
    }
    @AfterEach
    void tearDown() {
        if (jedis != null) {
            jedis.close();
        }
    }
}


需要引入的 pom


<!--单元测试-->
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter</artifactId>
    <version>5.7.1</version>
</dependency>


如何删除 BigKey


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


  • redis 3.0 及以下版本


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


  • Redis 4.0以后


  • Redis在4.0后提供了异步删除的命令:unlink
相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
2月前
|
消息中间件 缓存 NoSQL
大数据-49 Redis 缓存问题中 穿透、雪崩、击穿、数据不一致、HotKey、BigKey
大数据-49 Redis 缓存问题中 穿透、雪崩、击穿、数据不一致、HotKey、BigKey
66 2
|
4月前
|
缓存 NoSQL 安全
【Azure Redis 缓存】Azure Redis 4.0 被扫描到漏洞,如何修补呢?
【Azure Redis 缓存】Azure Redis 4.0 被扫描到漏洞,如何修补呢?
|
5月前
|
NoSQL Redis 容器
Redis性能优化问题之如何判断 Redis 实例是否写入了 bigkey
Redis性能优化问题之如何判断 Redis 实例是否写入了 bigkey
|
4月前
|
NoSQL Go Redis
Go语言中如何扫描Redis中大量的key
在Redis中,遍历大量键时直接使用`KEYS`命令会导致性能瓶颈,因为它会一次性返回所有匹配的键,可能阻塞Redis并影响服务稳定性。为解决此问题,Redis提供了`SCAN`命令来分批迭代键,避免一次性加载过多数据。本文通过两个Go语言示例演示如何使用`SCAN`命令:第一个示例展示了基本的手动迭代方式;第二个示例则利用`Iterator`简化迭代过程。这两种方法均有效地避免了`KEYS`命令的性能问题,并提高了遍历Redis键的效率。
64 0
|
7月前
|
存储 缓存 NoSQL
Redis经典问题:BigKey问题
BigKey问题常困扰着Redis用户,其影响不容忽视。本文将深入探讨BigKey问题的本质及解决方案,帮助你优化Redis性能,提升系统稳定性。
569 2
|
存储 NoSQL 算法
Redis中的BigKey问题:排查与解决思路
Redis中的BigKey问题:排查与解决思路
596 0
|
7月前
|
NoSQL Redis
Redis入门到通关之扫描 bigKey
Redis入门到通关之扫描 bigKey
69 0
|
7月前
|
机器学习/深度学习 监控 NoSQL
Redis进阶-如何发现和优雅的处理BigKey一二事
Redis进阶-如何发现和优雅的处理BigKey一二事
92 0
|
7月前
|
存储 缓存 NoSQL
Redis进阶-Redis键值设计及BigKey问题
Redis进阶-Redis键值设计及BigKey问题
90 0
|
存储 NoSQL Redis
Redis之bigkey问题解读
Redis之bigkey问题解读