潍坊恒信建设集团网站,网站切图规范,在线做春节网站,shopify不如wordpress本文是 Redis 键值设计的 14 个核心规范与最佳实践#xff0c;按重要程度分层说明#xff1a; 一、通用数据类型选择
这里我们先给出常规的选择路径图。 以下是对每个步骤的分析#xff1a;
是否需要排序#xff1f;#xff1a; zset#xff08;有序集合#xff09;用… 本文是 Redis 键值设计的 14 个核心规范与最佳实践按重要程度分层说明 一、通用数据类型选择
这里我们先给出常规的选择路径图。 以下是对每个步骤的分析
是否需要排序 zset有序集合用于排序的唯一值而list用于排序的重复值。 数据是否唯一 set用于存储唯一的值。 是否需要存储对象 Hash适合存储对象或具有多个字段的结构。 考虑操作频率 String和Hash都是Redis中最常用的数据类型适用于高频读写操作。 数据大小和内存占用大 Bitmap适合存储大量数据同时占用较少的内存。 消息队列 stream是Redis用于实现消息队列的数据类型。 原子操作和数据过期 lua脚本可以用于实现原子操作而Redis的过期机制可以用于数据过期。 二、键设计规范Key Design 命名规范 格式业务模块:数据维度:唯一标识例user:profile:10001强制要求禁止包含空格、换行符、不可见字符建议长度控制在 100 字节以内内存敏感场景 大Key规避 单Key值大小限制 String 类型 ≤ 10KBHash/List/Set/Zset 元素数 ≤ 5000 超标处理方案 数据分片例user:10001:cart_page1启用压缩客户端压缩 LZF Redis压缩 过期策略 必须设置过期时间包括持久化数据建议 30 天兜底不同过期时间策略-- 使用随机过期时间避免批量过期导致的毛刺
local expire_time 86400 math.random(0, 3600)
redis.call(EXPIRE, KEYS[1], expire_time)三、值设计规范Value Design 数据结构选择原则 按使用频率选择高频读写 → String/Hash
范围查询 → ZSET
去重计算 → Set/HLL
关系查询 → RedisGraph需 4.0禁止将 Redis 当关系型数据库使用避免复杂关联查询 JSON序列化陷阱 推荐方案 高频字段拆解为 Hash 字段保留完整 JSON 作为 fallback 方案 优化案例HMSET user:10001 name John age 30
SET user:10001:full {...} EX 3600计数器设计 必须使用 INCR/DECR 代替 GETSET集群环境推荐使用 INCRBY float 代替整数运算 三、高级优化策略 内存优化技巧 Hash 使用 ziplist 编码redis.conf 配置
hash-max-ziplist-entries 512
hash-max-ziplist-value 64使用 SSCAN/ZSCAN 替代 SMEMBERS/ZRANGE 热点Key治理 检测方法redis-cli --hotkeys解决方案 本地缓存 异步刷新Key 分片例hotkey_v1 → hotkey:{shard_id}:v1 事务与管道 管道(pipeline)批量操作控制在 100 命令/批次Watch 事务中避免包含耗时操作 四、集群与持久化 集群规范 单个分片内存 ≤ 10GBAWS 内存优化型实例跨槽操作使用 Hash Tag 需满足 相关Key必须使用相同{}内容示例{user10001}.orders, {user10001}.profile 持久化策略 AOF 配置appendfsync everysec
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mbRDB 快照周期 ≥ 15 分钟 五、避坑指南 危险命令禁用 rename-command FLUSHALL
rename-command KEYS internal_KEYS慢查询防御 设置超时阈值slowlog-log-slower-than 5000 # 5ms定期分析SLOWLOG GET 50 连接池配置 // Jedis 最佳配置示例
JedisPoolConfig config new JedisPoolConfig();
config.setMaxTotal(500); // 最大连接数
config.setMaxIdle(100); // 最大空闲连接
config.setMinIdle(20); // 最小空闲连接
config.setMaxWaitMillis(2000); // 最大等待时间六、案例
以下通过 6个高频场景的对比案例 说明 Redis 键值设计的核心规范帮助直观理解 案例1用户信息存储设计
❌ 错误做法
# 大JSON直接存储String类型无过期时间
SET user_10001 {name:John,age:30,address:...20个字段...,lastLogin:...}问题
Key无业务含义易冲突Value超10KB违反大Key规范高频读取时需全量解析JSON
✅ 正确方案
# 模块化Key命名 Hash分字段存储 过期时间
HMSET user:profile:10001 name John age 30 address ... lastLogin 1717040000
EXPIRE user:profile:10001 2592000 # 30天过期优化点
键结构清晰业务模块:数据维度:ID高频字段独立存取减少网络传输兜底过期避免数据堆积 案例2电商购物车设计
❌ 错误做法
# 用List存储所有商品ID可能产生大Key
LPUSH cart:10001 sku_123:5 sku_456:3 ...(5000商品)问题
超出5000元素的大Key阈值分页查询困难
✅ 正确方案
# Hash分片存储 计数器
HMSET cart:10001:page1 sku_123 5 sku_456 3
HMSET cart:10001:page2 sku_789 2 ...# 获取商品数量原子操作
HINCRBY cart:10001:page1 sku_123 1 优化点
分片控制单个Key元素数量利用Hash字段的原子计数特性 案例3秒杀库存热点Key
❌ 错误做法
# 集中式库存计数器产生热点Key
SET stock:sku_8888 1000
DECR stock:sku_8888 # 所有请求集中访问此Key问题
单Key承受极高QPS集群模式下无法分散压力
✅ 正确方案
# 库存分片设计
SET stock:sku_8888:shard1 200
SET stock:sku_8888:shard2 200
...
SET stock:sku_8888:shard5 200# 客户端随机选择分片扣减
DECR stock:sku_8888:shard{random(1-5)}优化点
通过分片分散热点结合本地缓存减少Redis访问 案例4页面访问计数器
❌ 错误做法
# 非原子操作导致计数不准
count redis.GET(page_view:home)
redis.SET(page_view:home, count1)问题
并发场景下数据不一致频繁GET/SET产生大量请求
✅ 正确方案
# 使用INCR原子操作
INCR page_view:home# 按小时滚动存储避免单Key过大
INCR page_view:home:2024052715优化点
原子操作保证准确性时间分片控制Key规模 案例5用户消息通知列表
❌ 错误做法
# 用String存储JSON数组频繁全量读写
SET msg:10001 [{id:1,content:...}, {...1000条数据}]问题
大Value导致网络阻塞修改任意消息需全量更新
✅ 正确方案
# 使用ZSET按时间排序存储
ZADD msg:10001 1717040000 {id:1,content:...}
ZADD msg:10001 1717040001 {id:2,content:...}# 分页查询最新消息
ZREVRANGE msg:10001 0 9 WITHSCORES优化点
天然支持按时间排序和分页单个消息的增删不影响整体 案例6社交关系存储
❌ 错误做法
# 用String存储用户粉丝列表大JSON数组
SET followers:10001 [20001,20002,...50000个用户ID]问题
50000个ID超过大Key限制判断是否关注需全量扫描
✅ 正确方案
# 使用Set存储关系 分页控制
SADD following:10001 20001 20002 ... # 最多5000元素/Key
SADD following:10001:page2 20003 ... # 分片存储# 检查关注关系
SISMEMBER following:10001 20001优化点
分片规避大Key使用原生集合操作提升效率 总结技巧
Key设计三要素业务线明确user、数据类型清晰profile、标识唯一10001Value选择原则 优先使用 Hash 替代 String 存储对象需要排序用 ZSET去重用 Set队列用 List 性能压测公式# 模拟高并发场景
redis-benchmark -h 127.0.0.1 -p 6379 -n 100000 -c 100 -t set,get