redis缓存设计规范

一、键值设计

1、key名设计

        a.(建议)可读性和可管理性:以业务名(或数据库名)为前缀,用冒号分隔

e.g. 业务名:表名:id    trade:order:1

        b.(建议)简洁性:保证语义的情况下,控制key的长度

e.g. user:{uid}:friends:messages:{mid}  简化为 u:{uid}:fr:m:{mid}

        c.(强制)不要包含特殊字符

不要包含空格、换行、单双引号及其他转义字符

2、value设计

        a.(强制)不允许使用bigkey(防止网卡流量、慢查询)

Redis中,一个字符串最大512MB,一个二级结构(hash、list、set、zset)可以存储大约40亿个(2^32 -1)元素,实际情况中以下两种情况,就可以认为它是bigkey:

                1、字符串:单个value值很大,超过10kb;

                2、非字符串:hash、list、set、zset,元素个数超过5000;

        bigkey的危害:

                1、导致redis阻塞

                2、网络阻塞

                3、过期删除,如果没有采用redis4.0的过期异步删除,就会造成阻塞;

        例子:

                社交类:粉丝列表,明细大V

                统计类:按天存储用户集合

                缓存类:将数据库数据load出来序列化放入redis

        如何优化bigkey:

                拆:将数据分段存储

3、(推荐)控制key的生命周期,redis不是垃圾桶,设置过期时间(条件允许打散过期时间)

二、命令使用

1、(推荐)O(N)命令关注N的数量:hgetall、lrange、smembers、zrange等的使用需要明确N的值,有遍历的需求可以使用hscan、scan、zscan替代

2、(推荐)禁用命令:禁止线上使用keys、flushall、flushdb等,通过redis的rename机制禁掉命令,或者使用scan的方式渐进式处理。

3、(推荐)合适使用select:redis的多数据库较弱,使用数字进行区分,很多客户端支持较差,同时多业务用多数据库实际还是单线程处理,会有干扰。

4、(推荐)使用批量操作提高效率:原生批量命令有mget、mset,非原生批量命令有pipeline,但要注意控制一次批量操作元素的个数。

三、客户端使用

1、避免多个应用使用一个redis实例

2、使用带有连接池的数据库

连接池配置含义,maxTotal:最大连接数;maxIdle:最大空闲连接数;maxWaitMillis:当连接池连接用尽后,调用者的最大等待时间(ms);

3、高并发下客户端添加熔断功能

4、设置合理的密码,如有必要使用SSL加密

5、过期键的清除策略

Redis对于过期键有三种清除策略

        1、被动删除:当读/写一个已经过期的key时,会触发惰性删除策略,直接删除这个过期key;

        2、主动删除:Redis会定期主动淘汰一批已过期的key;

        3、当已用内存超过maxmemory限定时,触发主动清理策略;

主动清理策略在redis 4.0之前有6中实现,4.0之后,又增加了2中策略;

默认是不处理,拒绝所有写入操作并返回报错信息“OOM”,只响应读操作;

常用volatile-lru:使用LRU算法筛选设置了过期时间的键值对删除

LRU(Least Recently Used):最近最少使用,以最近一次访问时间作为参考

LFU(Least Frequently Used):最不经常使用,以最近访问次数,频率为参考

Redis建议设置最大内存,如果不设置,当Redis内存超出物理内存限制时,内存的数据会开始和磁盘产生频繁的交换(swap),会让Redis的性能急剧下降;

Redis主从模式下,只有主节点才会执行过期策略,然后把删除操作同步到从节点;

<think>好的,我现在需要回答用户关于Redis缓存键设计的最佳实践与规范方案的问题。首先,我得回顾用户提供的引用内容,特别是引用[1]、[2]和[3],这些部分提到了键值设计、避免bigkey、数据类型选择等要点。 用户的问题主要集中在键设计的规范和最佳实践上。根据引用[1]中的内容,键名设计需要具备可读性和可管理性,通常以业务名为前缀,用冒号分隔。同时要控制键的长度,避免特殊字符。引用[2]补充了关于处理缓存不一致的情况,但用户主要关注的是键设计,这部分可能需要暂时忽略。引用[3]提到了String和Hash类型的使用场景,这也是键值设计的一部分。 接下来,我需要组织这些信息,确保结构清晰。首先,键名设计的规范包括前缀、分隔符、简洁性等。然后是值设计的注意事项,如避免bigkey,选择合适的数据类型。接着是其他相关规范,比如过期时间设置、分布式锁的使用,以及监控和维护的重要性。 还要注意用户提到的系统级指令,比如使用正确的中文回答,生成相关问题,以及引用标识。需要检查是否有遗漏的要点,例如数据类型的选择是否覆盖了所有情况,比如zset、list、set等的适用场景是否在回答中提及。 最后,生成相关问题时要确保问题与主题相关,能够引导用户进一步探索。例如,如何处理键冲突,如何选择数据类型,如何优化内存占用等。需要确保每个部分都参考了提供的引用,并在适当的位置添加引用标识,如[^1]、[^2]等。</think>### Redis缓存设计规范与最佳实践方案 #### 一、键名设计规范 1. **层级化命名** 使用业务名或数据库名为前缀,通过冒号分隔层级,增强可读性和管理性。 示例:$trade:order:1$(业务名:表名:id)[^1]。 2. **控制键长度** 在保证语义清晰的前提下简化键名,减少内存占用。 示例:$user:{uid}:friends:messages:{mid}$ 可简化为 $u:{uid}:fr:m:{mid}$。 3. **避免特殊字符** 键名中禁止包含空格、换行、引号等特殊字符,防止解析错误。 4. **固定格式与版本控制** 对于可能变更的数据结构,可在键名中加入版本标识,如 $cache:v2:user_profile:{uid}$。 --- #### 二、值设计规范 1. **避免BigKey** - Value大小限制:String类型 ≤10KB,集合类型(Hash/List/Set/ZSet)元素数 ≤1万[^2]。 - 危害:BigKey会导致网络阻塞、慢查询、集群数据倾斜。 2. **选择合适数据类型** - 需要排序 → 选择 $zset$(唯一值排序)或 $list$(重复值排序)[^1]。 - 唯一性要求 → 使用 $set$[^1]。 - 存储对象 → 优先用 $hash$(字段级读写),而非String序列化[^3]。 - 高频读写 → 选择 $String$ 或 $hash$[^1]。 3. **二进制安全** Redis的String类型可存储任意二进制数据(如图片),但需注意序列化/反序列化成本[^3]。 --- #### 三、其他关键规范 1. **设置合理过期时间** - 对一致性要求低的数据,通过过期时间触发被动更新[^2]。 - 结合业务场景设置不同TTL,避免大规模缓存同时失效。 2. **分布式锁控制** 对高并发写操作,使用Redis分布式锁(如RedLock算法)保证一致性[^2]。 3. **冷热数据分离** 高频访问数据与低频数据分开存储,例如使用不同前缀或数据库分片。 4. **监控与维护** - 定期使用 `SCAN` 命令检测BigKey。 - 通过 `MEMORY USAGE` 分析内存占用。 - 禁用危险命令(如 `KEYS *`),改用 `SCAN` 迭代查询[^2]。 --- #### 四、实践示例 ```python # 使用Hash存储用户对象 user_data = { "uid:1001": {"name": "张三", "age": 28}, "uid:1002": {"name": "李四", "age": 32} } redis.hset("users:profile", mapping=user_data) # 使用ZSet实现排行榜 redis.zadd("game:leaderboard", {"player:A": 95, "player:B": 87}) ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值