Redis开发规范
key设计
- 不要包含特殊字符:不包含空格、换行、单双引号以及其他转义字符
- 可读性和可管理性:多重语义使用冒号分割分割,减少冲突方便管理(其他符号也是可以的,官方风格是冒号)
- 简洁性:保证语义的情况下,控制key的长度,3.0版本中少于39字节(4.0版本中少于44字节)的字符串会用embstr编码格式进行存储(与value是连续的空间)更加节省空间
value设计
不使用bigkey
- 原因:可能会导致网络阻塞,Redis阻塞,集群节点不均匀,频繁序列化导致应用服务器CPU消耗以及内存消耗
- 阿里云官方标准:string类型在10KB以上的key和hash、list、set、zset元素个数超过5000个的key都是bigkey
- 排查bigkey方式:
- 客户端连接超时,有可能是bigkey阻塞造成的
- 使用
redis-cli --bigkeys
可以扫描Redis中是否存在bigkey,但是无法定制化参数
- 使用
debug object
指定key可以查看key的具体信息,但是只能查看到序列化后的长度,不是具体长度
- 对redis进行实时监控,当输出流量超过预期时,可能出现了bigkey
- 删除bigkey:bigKey删除会非常慢,会对redis发生阻塞
- 隐形删除:过期和重命名等,隐形删除不会记录在慢查询中(从节点同步时会记录在慢查询中)
- Redis4.0提供了懒删除,即
unlink
命令,可以做到后台删除,不会阻塞掉主进程
选择合适的数据结构
- 避免出现数据松散,可以使用hash结构
- 使用hash时,小hash会采用ziplist,更节省内存,ziplist编码采用的是不同属性使用连续的空间,但是在增加删除元素时性能差,但是属性个数少的情况下影响不大
- 使用
hash-max-ziplist-entries
配置参数进行配置超过属性时使用ziplist编码,支持动态配置,默认值是512
- 使用
hash-max-ziplist-value
配置参数进行配置属性值长度超过多少时使用ziplist编码,支持动态配置,默认值是64,单位字节
- 避免不了大hash情况下可采用分段hash,进而避免bigkey,将大hash转化为小hash,根据属性个数进行取模,得到不同下标,对应segment:0、segment:1...
- 对于统计信息合适的选择
- 若需要返回具体哪些用户访问过系统,使用set存储
- 若无需返回具体哪些用户访问过系统,并且不允许存在误差值,那么可以对每个用户ID对应到bitmap中存储
- 若无需返回具体哪些用户访问过系统,并且允许存在误差值,则可以使用HyperLogLog存储
过期设计
- 周期数据应该设置过期时间,使用
object idletime
指定key来查看key的闲置时间
- 过期时间不宜集中,容易出现缓存穿透和雪崩等问题
命令使用
- 谨慎使用复杂度为O(n)复杂度的命令,要清楚n是多少,比如hgetall、lrange、smembers、zrange、sinter等
- 禁止线上使用keys、flushall、flushdb等,配置文件中
rename-command
配置项将命令重命名为空字符串,进而禁用命令
- 合理使用select切换数据库命令,多数据库实际还是单线程处理,单个数据库阻塞时整个redis会阻塞掉
- 不使用Redis的事务处理,因为不支持回滚
- 可短时间使用
monitor
命令进行对Redis的监控,在高并发的情况下,长时间使用可能会将当前客户端的输出缓冲区撑爆,导致使用该命令的客户端崩溃,该命令类似发布订阅模式,等待其他客户端执行的命令并打印
客户端优化
- 避免多个应用使用同一个Redis:不相干的业务拆分,公共数据做服务化
- 合理配置连接池
- 最大连接数和最大空闲连接数应该一样,避免再接近期间反复创建和释放连接
- 最大连接数估计:期望的并发量∗命令执行平均耗时=连接数,这只是理论值,在根据具体使用情况适当的增大或缩小即可
- 连接池中连接耗尽时,不要死等,应该设置等待超时时间,避免客户端不好的体验
- 开启周期性的空闲连接检测
- 标准的使用连接池
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
} catch (Exception e) {
} finally {
if (null != jedis) {
jedis.close();
}
}
Comments NOTHING