一、 数据库选型
【建议】首先判断业务类型是否必须使用Redis存储数据,能否使用传统关系性数据库解决。使用Redis提前做好容量规划,注意数据冷热分离,避免将全部数据加载到Redis中。例如:
l 根据业务类型,选择合适的最大内存及淘汰策略,设置好Key过期时间
二、 Key命名
Redis有两层(key-value)或三层(key-field-value)结构,通常良好的Key命名习惯会为日常的开发和运维工作带来极大的便利性。
2.1 可读性
【建议】可读性高的Key命名有助于排查线上问题、方便的进行批量处理。建议使用业务名称加冒号分割命名,"业务名/数据库名:表名:id"作为前缀,key的长度不超过100个字符。例如:
l 当前redis内存暴涨,通过高频key前缀可以轻易的区分出是哪个系统的哪个模块在频繁操作,快速定位问题。
l 当定位到线上问题时,可以通过模式匹配批量处理该类Key。
2.2 简洁性
【建议】因为Redis中存储的Key数量可能非常庞大,在保证可读性的前提下,可以适当缩短Key的长度,以减小内存开销。例如:
l 建议key命名在64字符以内,在越庞大的系统中效果越明显。
原Key: userid:{uid}:friends:messagesid:{mid} 缩短后的Key,至少降低10字节的空间: uid:{uid}:friends:mid:{mid} |
2.3 规范性
【强制】Key命名需强制遵守以下规范,例如:
l 禁止包含特殊字符。例如:空格、换行、单双引号以及其他转义字符
l 满足业务需要的情况下,尽量合理设置Key过期时间,建议过期时间打散,防止集中过期,并且越短越好
原Key: redis> SET "userid:1:name" "Tom" EX 90 redis> SET "userid:2:name" "Jack" EX 90 redis> SET "userid:3:name" "Bob" EX 90 优化过期时间后的Key: redis> SET "userid:1:name" "Tom" PX 60100 redis> SET "userid:2:name" "Jack" PX 60200 redis> SET "userid:3:name" "Bob" PX 60300 |
三、 Value设计
如果说Key规范命名极大的提高了开发运维的便利性,那么Value设计规范更大的增加了Redis运行的高性能和可靠性
3.1 数据类型
【建议】Redis相比其它内存型数据库具有更加丰富的数据类型可供应用选择。例如:
l Strings类型: 单个kv存储、适用于如简单计数等。
l Hash类型: 多个相关属性放到一个Hash中、适用于如存储对象。
l Set类型: 集合类型、适用于如归类对象等
l Sorted Set类型: 有序集合类型、适用于如榜单排行
l Lists类型: 队列类型、适用于如队列、粉丝/关注列表等
l 特殊的数据类型:Hyperloglog、Geo、Scripting,需要提前跟DBA沟通
3.2 Bigkey
【强制】禁止Redis中出现Bigkey,防止出现高并发下网络拥堵、阻塞超时发生切换、集群内存空间不均衡、过期删除、迁移困难及慢查询。例如:
l string类型控制在10KB以内,hash、list、set、zset元素个数不要超过5000(实际需要观察元素的字节数),建议压缩后存储
l 非字符串的bigkey,不要使用del删除,使用hscan、sscan、zscan方式渐进式删除
l 注意bigkey过期时间,过期后会自动触发del造成阻塞,并且该del不会记录到慢查询
3.3 定长更新
【建议】因为Redis内存使用具有预分配和惰性删除的特性,因此Value内容的长度频繁变化极易导致Redis内存碎片的产生。内存碎片风险如下:
l 当内存碎片较多时,会导致取少量数据扫描大量内存块,严重拖慢Redis的运行
l 目前Redis内存碎片回收方式较困难,基本需要重启Redis实例才能释放碎片
四、 Redis安全
4.1 运行安全
【强制】防止Redis运行期间发生阻塞、崩溃、被入侵
l Redis务必配置复杂度高的访问密码(requirepass、masterauth),64位以上,防止暴力破解
l 避免用root用户启动
l 禁止测试环境连接与生产环境混用
l 禁止压测生产环境
l 禁止存储图片、音频、视频、文件等大数据
l 禁止不同业务使用相同Redis实例
l 优先选择Redis 4.0.14版本,若对高版本功能有需要,也可选择Redis 5.0.5版本
l Redis单实例物理内存占用尽量保持在10G,最大不要超过20G
4.2 使用安全
l 高风险命令
【强制】数据清除:flushall、flushdb建议在Redis中禁用
【建议】Server运行:shutdown、monitor、config、save、bgsave、bgrewriteaof建议在Redis中rename-command
【建议】易阻塞:关注时间复杂度O(N)的命令:keys、smembers、lrange、hgetall、sinter等,使用时明确N的值。有遍历的需求可以使用hscan、sscan、zscan代替并在客户端进行去重。此外,del bigkey、flushdb/flushall删除大量数据时,也会造成Redis短时间阻塞。Redis 4.0版本推出后台异步删除的方式(UNLINK、flushdb/flushall async)来避免该情况
l 特性功能
【建议】select:Redis实例虽然支持多个库,但因为Redis是单线程架构,同时多个业务使用多个库仍然会相互干扰
【建议】批量操作提高效率:Redis原生支持mget、mset、hmset等命令批量操作,非原生批量操作可以使用pipline提高效率,注意一次批量操作的元素个数不要太多,最好在100以内,以实际元素字节数大小为准
n 原生命令为原子操作,pipline可以打包多个命令但为非原子操作
n pipline需要客户端于服务端同时支持
【建议】事务:Redis事务功能支持较弱,不建议过多使用
【建议】消息队列:Redis List常被用作消息队列服务。因为功能相对简单,不支持消息重传、持久化等功能,当消费者崩溃时可能导致数据丢失。因此对于要求消息可靠性高的场景,建议使用更加专业的MQ软件
【建议】Redis cluster限制:
n 只支持具有相同slot值的key执行批量操作
n 一次事务操作的Key必须在一个slot中,可以hash tag实现定向分片(当一个key包含 {} 的时候,就不对整个key做hash,而仅对{}包括的字符串做hash)。
n key是数据分区的最小粒度,因此不能将一个大的键值对象,如hash,list等映射到不同的节点上
n 不支持多数据库,只能使用默认的0号库
n 不能使用级联复制
五、 集群架构
【强制】Redis高可用相关规范
l 禁止将线下节点复制到线上主库
l 主从集群必须配置哨兵高可用
l 线上业务禁止使用级联架构
l Redis Cluster集群架构至少三个分片
l 主从节点版本必须保持一致
六、 客户端
【建议】Redis客户端相关规范
l 使用带有连接池的客户端控制连接,提高通信效率。常用客户端比如Jedis、lettuce、Redisson
l 对于特别重要的数据、连接相关的操作需要保证捕获异常,防止错误被淹没、数据操作状态不确定
l 高并发下建议客户端添加熔断功能