Redis中大key处理的问题解决

 更新时间:2026年03月06日 09:54:33   作者:困知勉行1985  
本文主要介绍了Redis中大key处理的问题解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

Redis 处理大 Key 的主要方法可以分为预防、识别、处理和优化几个方面。下面我将详细说明每一步。

1.什么是大key

没有一个固定的数值可以定义所有场景下的大 Key。通常,我们可以将 String 类型超过 10 KB,集合类型元素超过 5000 作为大 Key 的参考阈值。但更重要的是,需要根据实际的业务场景、Redis 实例的配置和性能要求来定义适合自己的大 Key 阈值。

在不确定的情况下,建议进行性能测试,观察不同大小的 Key 对 Redis 操作延迟的影响,从而确定适合自己业务的大 Key 阈值。

实际案例中的建议

  • 阿里巴巴 Redis 开发规范:建议字符串类型控制在 10 KB 以内,集合元素数量不要超过 5000。
  • 腾讯云 Redis:建议字符串类型不超过 10 KB,集合元素数量不超过 4000。

大 Key 处理流程图

发现大 Key → 评估影响 → 选择策略
    ↓
预防为主 → 无法避免 → 渐进处理
    ↓
监控告警 → 异步删除 → 架构优化

预防大 Key

  • 在设计阶段,避免存储过大的数据。例如,对于存储集合类型的数据,可以拆分多个键来存储。
  • 使用合适的数据结构。例如,使用 HyperLogLog 代替集合进行基数统计,使用位图(bitmap)存储布尔值等。
  • 对数据进行压缩后再存储(但需要注意,压缩和解压会增加 CPU 开销,而且 Redis 本身不支持压缩,需要客户端处理)。

识别大 Key

  • 使用 Redis 自带的命令:例如 debug object key 可以查看某个 key 的序列化长度,但注意这个命令会影响性能,不建议在线使用。
  • 使用 redis-cli --bigkeys 命令可以扫描整个数据库,并统计出大 key。这个命令是通过扫描所有 key,然后统计它们的大小,注意这个过程会阻塞 Redis,最好在从节点上执行或者低峰期执行。
  • 使用 SCAN 命令编写脚本,逐步扫描所有 key,然后使用 strlenhlenllenscardzcard 等命令获取 key 的大小。这样不会阻塞 Redis,但需要自己编写脚本。

处理大 Key

  • 拆分大 Key:将一个大 key 拆分成多个小 key。例如,一个存储了百万个元素的哈希表,可以拆分成多个哈希表,每个哈希表存储一部分数据。然后通过分片的方式(例如使用固定的哈希策略)来访问。
    • 删除大 Key:如果大 Key 不再需要,删除它。但是直接删除一个大的 key 可能会阻塞 Redis(因为 Redis 是单线程的)。所以建议使用渐进式删除:
    • 对于哈希、列表、集合、有序集合,可以使用对应的命令进行渐进式删除。例如,对于哈希,可以使用 hscan 每次获取一部分字段,然后使用 hdel 删除。
  • 对于字符串,直接使用 del 命令,但如果是非常大的字符串,也会阻塞一段时间。可以考虑使用 unlink 命令(Redis 4.0 以上),它会在后台异步删除。
  • 对于集合类型,可以使用对应的扫描命令(如 sscanhscanzscan)来逐步删除。

优化大 Key 的使用

  • 对于读取,可以考虑使用分片的方式,将请求分散到多个 key 上,减少单个 key 的压力。
  • 对于写入,同样使用分片,避免对单个 key 频繁写入导致性能问题。
  • 考虑使用 Redis 集群,将数据分布到多个节点上,这样每个节点上的 key 就不会太大。

使用 Redis 4.0 的新特性

  • Redis 4.0 引入了异步删除(unlink 命令),可以用于删除大 key 而不阻塞主线程。
  • Redis 6.0 引入了多线程,可以在删除大 key 时使用后台线程处理,减少阻塞。

监控和告警

  • 定期监控 Redis 的内存使用情况,以及大 key 的情况。可以使用 INFO memory 命令查看内存使用情况。
  • 设置告警,当发现大 key 时及时处理。

下面是一个使用 SCAN 和 hscan 删除大哈希表的示例脚本(假设我们要删除一个名为 big_hash 的 key,它包含大量字段):每次扫描100个字段,然后删除它们(渐进式删除)

# 使用 hscan 每次扫描 100 个字段,然后删除它们
cursor=0
while true; do
    # 使用 hscan 命令,每次获取 100 个字段
    redis-cli hscan big_hash $cursor count 100 > /tmp/hscan_output.txt
    # 读取输出,第一行是下一个游标,第二行是字段列表
    cursor=$(head -1 /tmp/hscan_output.txt)
    fields=$(tail -1 /tmp/hscan_output.txt)
    # 将字段转换为数组,然后逐个删除
    # 注意:这里假设字段之间用空格分隔,但实际上 hscan 输出的字段是每行一个,所以需要根据实际情况调整
    # 以下是一个简单的处理方式,但可能不适用于所有情况
    for field in $fields; do
        redis-cli hdel big_hash $field
    done
    # 如果游标为0,表示扫描结束
    if [ $cursor -eq 0 ]; then
        break
    fi
done

注意:上面的脚本是一个简单的示例,实际使用时需要根据实际情况调整,比如处理 hscan 输出的格式,以及考虑网络连接和错误处理。

另外,也可以使用编程语言(如 Python、Java)来编写更复杂的脚本,利用相应 Redis 客户端的 SCAN 功能。

总结:处理大 Key 的核心思想是预防为主,及时发现并处理。在处理时,尽量避免阻塞 Redis 主线程,采用渐进式删除或异步删除。同时,通过拆分、分片等方式优化数据结构和访问模式。

Redis 处理大 Key 主要有以下几种方式:

1.预防措施(设计阶段)

数据结构优化

  • 拆分大 Key:将一个大的哈希/集合/列表拆分成多个小的 Key

# 原始大 Key
hset user:1_data field1 value1 ... field10000 value10000

# 拆分成多个 Key
hset user:1:part1 field1 value1 ... field1000 value1000
hset user:1:part2 field1001 value1001 ... field2000 value2000
————————————————
版权声明:本文为CSDN博主「困知勉行1985」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/wdquan19851029/article/details/156572934

使用合适的数据结构

  • HyperLogLog 替代大集合进行基数统计
  • Bitmaps 替代布尔值数组
  • 考虑使用其他存储(如关系数据库)存储大对象

2.识别大 Key

使用工具检测

# Redis 自带命令
redis-cli --bigkeys

# 扫描模式
redis-cli --bigkeys -i 0.1  # 每100毫秒扫描一次,减少对业务影响

# RDB 分析工具
redis-rdb-tools  # 分析 RDB 文件找出大 Key

使用 SCAN 命令

使用 SCAN 命令编写脚本,逐步扫描所有 key,然后使用 strlenhlenllenscardzcard 等命令获取 key 的大小。这样不会阻塞 Redis,但需要自己编写脚本。

# 编写脚本定期扫描
EVAL "
local cursor = 0
repeat
    local result = redis.call('SCAN', cursor, 'COUNT', 100)
    cursor = tonumber(result[1])
    local keys = result[2]
    
    for i, key in ipairs(keys) do
        local type = redis.call('TYPE', key)
        local size = 0
        
        if type == 'string' then
            size = redis.call('STRLEN', key)
        elseif type == 'hash' then
            size = redis.call('HLEN', key)
        elseif type == 'list' then
            size = redis.call('LLEN', key)
        elseif type == 'set' then
            size = redis.call('SCARD', key)
        elseif type == 'zset' then
            size = redis.call('ZCARD', key)
        end
        
        if size > 10000 then  -- 设置阈值
            print(key, type, size)
        end
    end
until cursor == 0
" 0

3.处理现有大 Key

渐进式删除

# 对于大 Hash - 使用 hscan + hdel
cursor=0
while true; do
    result=$(redis-cli HSCAN big_hash $cursor COUNT 100)
    cursor=$(echo "$result" | head -1)
    fields=$(echo "$result" | tail -n +2 | awk '{print $1}')
    
    for field in $fields; do
        redis-cli HDEL big_hash $field
    done
    
    if [[ $cursor -eq "0" ]]; then
        break
    fi
done

# 对于大 Set - 使用 sscan + srem
# 对于大 ZSet - 使用 zscan + zrem
# 对于大 List - 分批次 ltrim
redis-cli LTRIM big_list 0 99  # 保留前100个元素

异步删除(Redis 4.0+)

# 使用 UNLINK 替代 DEL(异步删除)
redis-cli UNLINK big_key

# 配置异步删除参数(redis.conf)
lazyfree-lazy-eviction yes
lazyfree-lazy-expire yes
lazyfree-lazy-server-del yes
replica-lazy-flush yes

4.配置优化

# 监控告警
# 设置内存使用阈值
maxmemory 4gb
maxmemory-policy allkeys-lru

# 客户端缓冲区限制
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit replica 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60

5.架构层面优化

使用集群模式

# 将数据分散到不同节点
# 大 Key 会自动分布到不同实例
redis-cli --cluster create node1:6379 node2:6379 ...

6.总结建议

  • 设计阶段避免大 Key:合理拆分数据
  • 定期扫描检测:建立监控体系
  • 使用渐进式操作:避免阻塞 Redis
  • 升级到 Redis 4.0+:利用异步删除特性
  • 考虑数据迁移:将大对象存储到其他存储系统
  • 容量规划:提前预估数据增长

记住:预防胜于治疗,良好的数据模型设计是避免大 Key 问题的根本。

到此这篇关于Redis中大key处理的问题解决的文章就介绍到这了,更多相关Redis 大key内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 浅谈一下如何保证Redis缓存与数据库的一致性

    浅谈一下如何保证Redis缓存与数据库的一致性

    这篇文章主要介绍了一下如何保证Redis缓存与数据库的一致性,今天这篇文章就带你详细了解一下四种同步策略,需要的朋友可以参考下
    2023-03-03
  • Redis主从复制的原理分析

    Redis主从复制的原理分析

    Redis主从复制通过将数据镜像到多个从节点,实现高可用性和扩展性,主从复制包括初次全量同步和增量同步两个阶段,为优化复制性能,可以采用AOF持久化、调整复制超时时间、优化网络带宽等措施,故障转移机制依赖于Sentinel或Cluster组件
    2025-01-01
  • Redis如何使用HyperLogLog的实现

    Redis如何使用HyperLogLog的实现

    本文主要介绍了Redis如何使用HyperLogLog的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-06-06
  • Redis主从复制搭建、哨兵搭建、集群搭建全过程

    Redis主从复制搭建、哨兵搭建、集群搭建全过程

    本文详细介绍了Redis主从复制和哨兵模式的搭建步骤、配置方法以及主从复制和哨兵模式的特点和应用,主从复制可以实现读写分离和性能扩展,同时提供了容灾和快速恢复功能,哨兵模式可以实现主节点的自动故障转移,提高系统的可用性和可靠性
    2026-03-03
  • Redis使用SETNX命令实现分布式锁

    Redis使用SETNX命令实现分布式锁

    分布式锁是一种用于在分布式系统中控制多个节点对共享资源进行访问的机制,本文主要为大家详细介绍了Redis如何使用SETNX命令实现分布式锁,需要的可以参考下
    2025-01-01
  • 通过实例解析布隆过滤器工作原理及实例

    通过实例解析布隆过滤器工作原理及实例

    这篇文章主要介绍了通过实例解析布隆过滤器工作原理及实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-11-11
  • Redis中RPOP、BRPOP、LPOP和BLPOP使用示例代码

    Redis中RPOP、BRPOP、LPOP和BLPOP使用示例代码

    这篇文章主要介绍了Redis中RPOP、BRPOP、LPOP和BLPOP使用的相关资料,解释了列表的方向,并详细说明了每个命令的功能、返回值、使用场景,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2026-05-05
  • 详解Redis缓存预热的实现方法

    详解Redis缓存预热的实现方法

    缓存预热是一种在程序启动或缓存失效之后,主动将热点数据加载到缓存中的策略,本文将给大家分享一下如何实现Redis的缓存预热,文中有详细的实现代码,需要的朋友可以参考下
    2023-10-10
  • redis cluster支持pipeline的实现思路

    redis cluster支持pipeline的实现思路

    本文给大家介绍redis cluster支持pipeline的实现思路,在 cluster 上执行 pipeline 可能会由于 redis 节点扩缩容 中途 redirection 切换连接导致结果丢失,具体细节问题请参考下本文
    2021-06-06
  • redis查询keys报错的实现

    redis查询keys报错的实现

    在Redis中使用KEYS命令来查询所有符合特定模式的键名是一个常见需求,本文主要介绍了redis查询keys报错的实现,具有一定的参考价值,感兴趣的可以了解一下
    2025-04-04

最新评论