一、Redis键值设计
1.优雅的key结构
(1)遵循基本格式:【业务】:【数据名】:【id】
(2)长度不超过44字节
(3)不包含特殊字符
2.拒绝BigKey
(1)BigKey就是数据量很大的key,它的value值有5MB以上应该就算一个BigKey了
(2)危害
-
网络阻塞
-
对BigKey执行读请求时,少量的QPS就可能导致带宽使用率被占满,导致Redis实例,乃至所在物理机变慢
-
-
数据倾斜
-
BigKey所在的Redis实例内存使用率远超其他实例,无法使数据分片的内存资源达到均衡
-
-
Redis阻塞
-
对元素较多的hash、list、zset等做运算会耗时较旧,使主线程被阻塞
-
-
CPU压力
-
对BigKey的数据序列化和反序列化会导致CPU的使用率飙升,影响Redis实例和本机其它应用
-
(3)发现BigKey
- redis-cli --bigkeys
- scan扫描
- 第三方工具
- 网络监控
(4)删除BigKey
- 在Redis3.0版本之前,集合类型,遍历BigKey元素,先逐个删除子元素,最后删除BigKey
- Redis在4.0以后提供了异步删除的命令:unlink
3.恰当的数据类型
- json字符串:实现简单;但不灵活
- 字段打散(对象数据):可以访问对象任意字段;但占用空间大、没办法做统一控制
- hash:底层使用ziplist,空间占用小,可以灵活访问对象的任意字段
4.总结
-
Key的最佳实践
-
固定格式:[业务名]:[数据名]:[id]
-
足够简短:不超过44字节
-
不包含特殊字符
-
-
Value的最佳实践:
-
合理的拆分数据,拒绝BigKey
-
选择合适数据结构
-
Hash结构的entry数量不要超过1000
-
设置合理的超时时间
-
二、批处理优化
对一次性处理多条指令的优化
1.Redis批量处理命令
- mset
- hmset
2.Pipeline
MSET虽然可以批处理,但是却只能操作部分数据类型,因此如果有对复杂数据类型的批处理需要,建议使用Pipeline
3.集群下的批处理
(1)问题
如MSET或Pipeline这样的批处理需要在一次请求中携带多条命令,而此时如果Redis是一个集群,那批处理命令的多个key必须落在一个插槽中,否则就会导致执行失败。大家可以想一想这样的要求其实很难实现,因为我们在批处理时,可能一次要插入很多条数据,这些数据很有可能不会都落在相同的节点上,这就会导致报错了
(2)方案
第一种方案:串行执行,所以这种方式没有什么意义,当然,执行起来就很简单了,缺点就是耗时过久。
第二种方案:串行slot,简单来说,就是执行前,客户端先计算一下对应的key的slot,一样slot的key就放到一个组里边,不同的,就放到不同的组里边,然后对每个组执行pipeline的批处理,他就能串行执行各个组的命令,这种做法比第一种方法耗时要少,但是缺点呢,相对来说复杂一点,所以这种方案还需要优化一下
第三种方案:并行slot,相较于第二种方案,在分组完成后串行执行,第三种方案,就变成了并行执行各个命令,所以他的耗时就非常短,但是实现呢,也更加复杂。
第四种:hash_tag,redis计算key的slot的时候,其实是根据key的有效部分来计算的,通过这种方式就能一次处理所有的key,这种方式耗时最短,实现也简单,但是如果通过操作key的有效部分,那么就会导致所有的key都落在一个节点上,产生数据倾斜的问题,所以我们推荐使用第三种方式。
三、服务器端优化
1.持久化配置
-
用来做缓存的Redis实例尽量不要开启持久化功能
-
建议关闭RDB持久化功能,使用AOF持久化
-
利用脚本定期在slave节点做RDB,实现数据备份
-
设置合理的rewrite阈值,避免频繁的bgrewrite
-
配置no-appendfsync-on-rewrite = yes,禁止在rewrite期间做aof,避免因AOF引起的阻塞
-
部署有关建议:
-
Redis实例的物理机要预留足够内存,应对fork和rewrite
-
单个Redis实例内存上限不要太大,例如4G或8G。可以加快fork的速度、减少主从同步、数据迁移压力
-
不要与CPU密集型应用部署在一起
-
不要与高硬盘负载应用一起部署。例如:数据库、消息队列
-
2.慢查询优化
(1)慢查询:在Redis执行时耗时超过某个阈值的命令,称为慢查询。
(2)危害:由于Redis是单线程的,所以当客户端发出指令后,他们都会进入到redis底层的queue来执行,如果此时有一些慢查询的数据,就会导致大量请求阻塞,从而引起报错,所以我们需要解决慢查询问题。
(3)配置
- slowlog-log-slower-than:慢查询阈值,单位是微秒。默认是10000,建议1000
- slowlog-max-len:慢查询日志(本质是一个队列)的长度。默认是128,建议1000
- 修改这两个配置可以使用:config set命令
(4)查看慢查询
-
slowlog len:查询慢查询日志长度
-
slowlog get [n]:读取n条慢查询日志
-
slowlog reset:清空慢查询列表
3.命令及安全配置
-
4.Redis一定要设置密码
-
禁止线上使用下面命令:keys、flushall、flushdb、config set等命令。可以利用rename-command禁用。
-
bind:限制网卡,禁止外网网卡访问
-
开启防火墙
-
不要使用Root账户启动Redis
-
尽量不是有默认的端口