Redis 第7章之开发注意事项
文章目录
设计
1.冷热数据分离,不要将所有数据全部都放到Redis中
虽然Redis支持持久化,但是Redis的数据存储全部都是在内存中的,成本昂贵。建议根据业务只将高频热数据存储到Redis中【QPS大于5000】,对于低频冷数据可以使用MySQL/ElasticSearch/MongoDB等基于磁盘的存储方式,不仅节省内存成本,而且数据量小在操作时速度更快、效率更高!
2.不同的业务数据要分开存储
不要将不相关的业务数据都放到一个Redis实例中,建议新业务申请新的单独实例。因为Redis为单线程处理,独立存储会减少不同业务相互操作的影响,提高请求响应速度;同时也避免单个实例内存数据量膨胀过大,在出现异常情况时可以更快恢复服务!
3.规范Key的格式
“平台缩写“+“:”+“项目名”+“:”+“业务含义”
例如:GW:TRADE:USERID
GW是新网关,TRADE是交易项目,USERID为业务ID。
":"作为key分隔符,方便客户端工具作为目录分级
注:集群模式下批量操作要求在同一个槽点下。(SKU:{hello}:123与SKU:{hello}:456 在同一个hash槽内)。
# 计算hash槽值的伪代码
def key_hash_slot(key):
int keylen = key.length();
for (s = 0; s < keylen; s++):
if (key[s] == '{'):
break;
if (s == keylen) return crc16(key,keylen) & 16383;
for (e = s+1; e < keylen; e++):
if (key[e] == '}') break;
if (e == keylen || e == s+1) return crc16(key,keylen) & 16383;
/* 使用{和}之间的有效部分计算槽 */
return crc16(key+s+1,e-s-1) & 16383;
4.拒绝bigkey
防止网卡流量、慢查询,string类型控制在10KB以内,hash、list、set、zset元素个数不要超过5000。
反例:一个包含200万个元素的list。
非字符串的bigkey,不要使用del删除,使用hscan、sscan、zscan方式渐进式删除,同时要注意防止bigkey过期时间自动删除问题(例如一个200万的zset设置1小时过期,会触发del操作,造成阻塞,而且该操作不会不出现在慢查询中(latency可查)
5.建议控制key的生命周期
redis不是垃圾桶,建议使用expire设置过期时间(条件允许可以打散过期时间,防止集中过期)
开发
1.O(N)命令关注N的数量
例如hgetall、lrange、smembers、zrange、sinter等并非不能使用,但是需要明确N的值。有遍历的需求可以使用hscan、sscan、zscan代替。
2.禁用命令
禁止线上使用keys、flushall、flushdb等,通过redis的rename机制禁掉命令,或者使用scan的方式渐进式处理。
3.合理使用select
redis的多数据库较弱,使用数字进行区分,很多客户端支持较差,同时多业务用多数据库实际还是单线程处理,会有干扰。
4.使用批量提高操作效率
- mset、mget等命令
- pipeline
- lua脚本(复杂耗时操作不建议)