
String类型:单Value > 10KB。 Hash/Set/Sorted Set:元素数量 > 5000。 List类型:元素数量 > 10000。 Stream类型:消息数量 > 5000。

业务场景需求:如购物车场景中,一个用户可能会添加多个商品到购物车,若将所有商品信息存储在一个 key 中,随着商品数量的增加,key 的大小也会不断增长。 数据结构选择不当:比如用 List 存储重复元素或冗余数据,用 String 存储长文本或大文件元数据。 缺乏过期策略:日志数据未设置 TTL 持续累积。 业务规模增长:未预判数据量级导致结构臃肿。
用户购物车Hash结构存储了12000+商品项。 单个Key体积达到8.2MB。 每次hgetall操作平均耗时127ms。 导致集群出现连锁超时故障。


redis-cli --bigkeys:快速定位内存占用 TOP Key。 MEMORY USAGE key:精确查询单个 Key 内存(复杂结构为近似值)。 OBJECT encoding key:分析 Key 编码类型(如 raw/embstr)。但这些命令在生产环境中使用需谨慎,因为它们可能会对 Redis 的稳定性产生影响。
# 原生大Key扫描(生产慎用)redis-cli --bigkeys --memkeys 10
redis-rdb-tools:解析 RDB 文件生成内存分布报告。 RedisInsight:可视化监控 Key 大小与内存使用。
# 内存分析工具redis-rdb-tools -c memory data/dump.rdb --bytes 10240 --type string
def scan_big_keys(host, port, threshold):cursor = 0r = redis.StrictRedis(host=host, port=port)while True:cursor, keys = r.scan(cursor, count=100)for key in keys:key_type = r.type(key)size = 0if key_type == b'string':size = r.memory_usage(key)elif key_type in [b'hash', b'list', b'set', b'zset']:size = r.memory_usage(key, samples=0)if size > threshold:yield key.decode(), key_type.decode(), sizeif cursor == 0:break
redis_key_size{type="string"} 1024000redis_key_element_count{type="hash"} 15000redis_memory_fragmentation_ratio 1.8


public class KeySharder {private static final int SHARD_COUNT = 16;private static final CRC32 crc32 = new CRC32();public static String getShardKey(String baseKey, String data) {crc32.reset();crc32.update(data.getBytes());return baseKey + ":" + (crc32.getValue() % SHARD_COUNT);}}
# 原始大KeyHSET user:1001:cart sku1 "{...}" sku2 "{...}" ... skuN "{...}"# 拆分后结构HMSET user:1001:cart:0 sku1 "{...}" sku2 "{...}"HMSET user:1001:cart:1 sku3 "{...}" sku4 "{...}"SADD user:1001:cart:index 0 1
-- KEYS[1] 原始列表key-- ARGV[1] 分页大小-- ARGV[2] 最后游标local new_cursor = tonumber(ARGV[2]) or 0local elements = redis.call('LRANGE', KEYS[1], new_cursor, new_cursor + tonumber(ARGV[1]) - 1)new_cursor = new_cursor + #elementsreturn {new_cursor, elements}


在处理 Excel 数据导入时,可以将大 key 拆分成多个 key-value 对,每个 key 包含部分数据。
def update_cart(user_id, sku, data):# 旧结构写入redis.hset(f"user:{user_id}:cart", sku, data)# 新结构写入shard = crc32(sku) % 16redis.hset(f"user:{user_id}:cart:{shard}", sku, data)
./redis-migrate --source redis://old:6379 --target redis://new:6380 \--filter "user:*:cart" --transform "sharded_cart_key" --threads 8
SELECTCOUNT(DISTINCT sku) AS original_count,SUM(shard_count) AS new_countFROM (SELECT COUNT(*) AS shard_count FROM new_cart_shardsUNION ALLSELECT HLEN('user:1001:cart') FROM redis_snapshot);
location /cart {redis_pass $upstream;set $shard_key '';access_by_lua_file /etc/nginx/lua/cart_router.lua;}
rules:- name: BigKeyProtectionthreshold: 100msduration: 10sminRequests: 5ratio: 0.5action: circuitBreak

自动化拆分系统:基于机器学习的动态分片策略。 协议层优化:RESP3协议支持分片元数据。 存储引擎改进:原生支持自动分片功能。 混合存储方案:冷热数据分层存储。

文章转载自老王两点中,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




