优雅的Key结构
Key实践约定:
- 遵循基本格式:[业务名称]:[数据名]:id
- 例:login:user:10
- 长度步超过44字节(版本不同,上限不同)
- 不包含特殊字符
优点:
- 可读性强
- 避免key冲突
- 方便管理
- 节省内存(key是string类型,底层编码包含int、embstr、raw三种。在小于44个字节时使用embstr,embstr采用连续内存空间,内存占用更小。如果超过44个字节,底层编码使用raw)
BigKey
BigKey通常以key的大小和key中成员的数量来综合判定,例如:
- Key本身的数据量过大:String类型的Key,它的值的大小是5M
- Key中的成员数过多:一个ZSET类型的Key,它的成员数量为10000个
- Key中成员的数据量过大:一个HASH类型的Key,它的成员数量虽然只有10000个,但这些成员的value总大小超过100M
推荐值:
- 单个Key的value值小于10kb
- 集合类型的key,建议元素数量小于1000
BigKey的危害:
- 网络阻塞:对BigKey执行读请求时,少量的QPS就可能导致带宽使用率被沾满,从而导致网络阻塞
- 数据倾斜:BigKey所在的Redis实例内存使用率远超其他实例,无法使用数据分片的内存资源达到均衡
- Redis阻塞:对元素较多的hash、list、zset等做运算会耗时较久,使主线程阻塞
- CPU压力:对BigKey的数据序列化和反序列化会导致CPU的使用率上升,影响Redis
持久化配置
- 用来做缓存的Redis实例尽量不要开启持久化功能
- 建议关闭RDB持久化功能,使用AOF持久化
- 利用脚本定期在slave节点做RDB,实现数据备份
- 使用AOF持久化,设置合理的rewrite阈值,避免频繁的bgrewrite
- 配置no-appendfsyns-on-rewrite = yes ,禁止在rewrite期间做aof,避免因AOF引起的阻塞(追求性能可以配置)
部署建议:
- Redis实例的物理机要预留足够内存,应对fork和rewrite
- 单个Redis实例内存上限不要太大,例如4G或8G。可以加快fork的速度、减少主从同步、数据迁移压力
- 不要与CPU密集型应用部署在一起
- 不要与高硬盘负载应用部署在一起。例如:数据库、消息队列
慢查询
Redis在执行时耗时超过某个阈值的命令,称为慢查询
慢查询的阈值可以通过配置指定:
- slowlog-log-slower-than:慢查询阈值,单位是微妙。默认是10000,建议1000
慢查询会被放入慢查询日志中,日志长度有上限。
- slowlog-max-len:慢查询日志(本质是一个队列)的长度。默认是128,建议1000
# 动态配置,重启失效,可在配置文件中永久配置
# 获取配置信息
config get slowlog-log-slower-than
config get slowlog-max-len
# 设置配置信息
config set slowlog-log-slower-than 1000
config set slowlog-max-len 1000
命令及安全配置
- Redis设置复杂密码
- 禁止线上使用以下命令:keys、flushall、flushdb、config、set等命令。可以利用 rename-command 禁用
- bind:限制网卡,禁止外网网卡访问
- 开启防火墙
- 禁止使用Root账号启动Redis
- 尽量不要使用默认的端口
内存配置
当Redis内存不足时,可能导致Key频繁被删除、响应时间变长、QPS不稳定等问题。当内存使用率达到90%以上时就需要警惕,并快速定位到内存占用的原因。
内存占用 | 说明 |
---|---|
数据内存 | 是Redis最主要的部分,存储Redis的键值信息。主要问题是BigKey问题,内存碎片问题(内存碎片,可直接重启Redis解决) |
进程内存 | Redis主进程本身运行需要占用内存;这部分大约在几兆,在大多数生产环境中与Redis数据占用的内存相比,可以忽略 |
缓冲区内存 | 一般包括客户端缓冲区、AOF缓冲区、复制缓冲区等。客户端缓冲区又包括输入缓冲区与输出缓冲区两种。这部分内存占用波动较大,不当使用BigKey,可能导致内存溢出 |
Redis查看内存分配状态,命令如下:
# 查看Redis内存相关信息
info memory
# 查看某个模块的内存信息
memory xxx
内存缓冲区常见三种:
- 复制缓冲区:主从复制的repl_backlog_buf,如果太小可能导致频繁的全量复制,影响性能。通过repl_backlog_buf来设置,默认是1mb
- AOF缓冲区:AOF刷盘之前的缓存区域,AOF执行rewire的缓冲区。无法设置容量上限
- 客户端缓冲区:分为输入流和输出流缓冲区,输入缓冲区最大1G且不能设置。输出缓冲区可以设置,如下图:
集群最佳实践
集群完整性问题:
# 默认配置,该配置表明,如果发现任意一个插槽不可用,则整个集群都会停止对外服务
cluster-require-full-coverage yes
# 因此,为了保证高可用特性,把默认配置改成 no
cluster-require-full-coverage no
集群带宽问题:
集群之间会不断的互相Ping来确定集群中其他节点的状态。每次Ping都会携带的信息至少包括:插槽信息、集群状态信息,集群中节点越多,集群状态信息数据量越大,10个节点的相关信息可能达到1kb,此时每次集群互通需要的带宽会非常高。
解决途径:
- 避免大集群,集群节点数不要太多,最好少于1000,如果业务庞大,建议多个集群
- 避免在单个物理机中运行太多Redis实例,建议10个以内
- 配置合适的cluster-node-timeout值