Redis大Key如何拆分存储_将BigString或BigHash拆分为多个小Key

陌磊君_7334

陌磊君_7334

2026-04-07

832人浏览

原创

redis单个string超10mb必须拆分,建议512kb内切片并用getrange/setrange操作;bighash应按访问频次和语义拆为小hash,禁用hgetall;一致性靠lua脚本或状态字段+重试保障。

redis大key如何拆分存储_将bigstring或bighash拆分为多个小key

BigString 超过 10MB 就该拆,别硬扛

Redis 单个 STRING 值超过 10MB 时,GET/SET 延迟明显上升,主从同步卡顿、AOF rewrite 阻塞、RDB fork 失败风险陡增。这不是“建议优化”,是实际运行中会触发 OOM command not allowed when used memory > 'maxmemory'Timeout waiting for response from master 的临界点。

拆法很简单:按固定长度切片,加序号后缀存成多个 key:

SET user:1001:profile:0 "{'name':'Alice','bio':'..."  
SET user:1001:profile:1 "...','avatar':'https://...'}"

关键点:

  • 切片长度建议控制在 512KB 以内(避开 Redis 网络缓冲区默认大小)
  • 必须用 GETRANGE/SETRANGE 配合业务逻辑做读写,不能直接 GET 全量再拼接——否则又回到大 Key 场景
  • 删除时得用 DEL user:1001:profile:0 user:1001:profile:1 ...,别漏掉;推荐用 Lua 脚本原子执行
  • 如果业务需要原子读全量,不要在客户端拼,改用服务端 Lua + redis.call('GET', ...) 拼接并返回,避免网络多次往返

Hash 拆分不能只靠 hscan,得重设计键结构

一个 HASH 有 50 万个 field,HGETALL 基本不可用,HSCAN 游标也可能超时或返回不完整。这时不是“加个游标参数就能解决”,而是原始建模出了问题。

正确做法是把“单个大 Hash”转为“多个语义化小 Hash”,例如:

HSET user:1001:profile:name "Alice"  
HSET user:1001:profile:contact "{'email':'a@b.c','phone':'138...'}"  
HSET user:1001:settings:notify "{'mail':true,'sms':false}"

要点:

  • 拆分依据是访问频次和聚合粒度——高频读写的字段单独成 Hash,低频/大体积字段(如 JSON blob)单独切片
  • 避免用 user:1001:profile:0user:1001:profile:1 这种无意义编号,后续维护和 debug 成本极高
  • HLENHEXISTS 在拆分后依然有效,但 HGETALL 必须变成多次 HGET 或批量 HMGET,别指望兼容旧接口
  • 如果原来依赖 HINCRBY 做计数,拆分后需确保计数字段落在同一子 Hash 内,否则无法原子更新

拆分后一致性怎么保?别信“先删后写”

BigString 或 BigHash 拆成多 key 后,写入不再是原子操作。比如更新用户资料,要同时写 user:1001:profile:nameuser:1001:profile:contactuser:1001:settings:notify —— 中间失败会导致数据不一致。

可靠方案只有两个:

  • 用 Lua 脚本封装全部写操作,通过 EVAL 保证原子性(注意脚本总执行时间别超 100ms,否则阻塞其他命令)
  • 业务层引入状态字段 + 重试机制:先写新 key,再设 user:1001:profile:statusupdating,全部成功后改为 active;读取时若遇 updating,回退到旧 key 或等待重试
  • 绝对不要用 DEL 所有旧 key 再 SET 新 key —— 删除和写入之间存在明显窗口期,缓存穿透风险极高

如何发现还没拆但已经危险的大 Key?别只看 info memory

INFO memory 只告诉你用了多少内存,看不出哪个 key 是罪魁祸首。真正有用的是:

  • redis-cli --bigkeys:扫描样本,报告 top 5 大 key 类型和 size,但只采样,可能漏掉冷 key
  • redis-cli --hotkeys:识别高访问 key,但不反映体积
  • 更准的做法是开启 CONFIG SET notify-keyspace-events KEA,配合监听 __keyevent@0__:set 事件,在应用写入时记录 key 大小(用 STRLEN/HLEN/SCARD 等),上报到监控系统
  • 线上禁止用 MEMORY USAGE 全量扫 key —— 它会阻塞主线程,尤其对大 key 本身就会卡住几秒

最常被忽略的一点:拆分不是一劳永逸。当业务增长使某个子 key 再次膨胀(比如 user:1001:logs 每天追加,半年后又成 BigString),得有自动检测 + 动态再切分的机制,而不是等报警才人工介入。

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
json数据格式
json数据格式

JSON是一种轻量级的数据交换格式。本专题为大家带来json数据格式相关文章,帮助大家解决问题。

2023.08.07

1955

5

json是什么
json是什么

JSON是一种轻量级的数据交换格式,具有简洁、易读、跨平台和语言的特点,JSON数据是通过键值对的方式进行组织,其中键是字符串,值可以是字符串、数值、布尔值、数组、对象或者null,在Web开发、数据交换和配置文件等方面得到广泛应用。本专题为大家提供json相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.23

2562

1

jquery怎么操作json
jquery怎么操作json

操作的方法有:1、“$.parseJSON(jsonString)”2、“$.getJSON(url, data, success)”;3、“$.each(obj, callback)”;4、“$.ajax()”。更多jquery怎么操作json的详细内容,可以访问本专题下面的文章。

2023.10.13

896

3

go语言处理json数据方法
go语言处理json数据方法

本专题整合了go语言中处理json数据方法,阅读专题下面的文章了解更多详细内容。

2025.09.10

2859

7

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.02

5019

3

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

2023.10.19

3028

3

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

2025.10.17

4169

12

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2025.12.29

3649

9

java接口相关教程
java接口相关教程

本专题整合了java接口相关内容,阅读专题下面的文章了解更多详细内容。

2026.01.19

366

15

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
phpStudy极速入门视频教程
phpStudy极速入门视频教程

共6课时 | 54.6万人学习

独孤九贱(4)_PHP视频教程
独孤九贱(4)_PHP视频教程

共89课时 | 133.1万人学习