江西企业网站建设费用/怎么样在百度上免费推广
在 Redis 的实际部署应用中,有一个非常严重的问题,那就是 Redis 突然变慢了。一旦出现这个问题,不仅会直接影响用户的使用体验,还可能会影响到“旁人”,也就是和 Redis 在同一个业务系统中的其他系统,比如说数据库。举个小例子,在秒杀场景下,一旦 Redis 变慢了,大量的用户下单请求就会被拖慢,也就是说,用户提交了下单申请,却没有收到任何响应,这会给用户带来非常糟糕的使用体验,甚至可能会导致用户流失。
那么Redis突然变慢之后,一般出现的的原因有什么,以及我们应该怎么解决呢?
- 使用复杂度过高的命令
(例如SORT/SUION/ZUNIONSTORE/KEYS),或一次查询全量数据(例如LRANGE key 0 N,但N很大)
分析:a) 查看slowlog是否存在这些命令
b) Redis进程CPU使用率是否飙升(聚合运算命令导致)
解决:a) 不使用复杂度过高的命令,或用其他方式代替实现(放在客户端做)
b) 数据尽量分批查询(LRANGE key 0 N,建议 N<=100,查询全量数据建议使HSCAN/SSCAN/ZSCAN) - 是否对过期 key 设置了相同的过期时间?
对于批量删除的 key,可以在每个 key 的过期时间上加一个随机数,避免同时删除。
分析:a) 业务使用EXPIREAT/PEXPIREAT命令
b) Redis info中的expired_keys指标短期突增
解决:a) 优化业务,过期增加随机时间,把时间打散,减轻删除过期key的压力
b) 运维层面,监控expired_keys指标,有短期突增及时报警排查 - 是否存在 bigkey?
对于 bigkey 的删除操作,如果你的 Redis 是 4.0 及以上的版本,可以直接利用异步线程机制减少主线程阻塞;如果是 Redis 4.0 以前的版本,可以使用 SCAN 命令迭代删除;对于 bigkey 的集合查询和聚合操作,可以使用 SCAN 命令在客户端完成。
分析:a) slowlog出现很多SET/DELETE变慢命令(bigkey分配内存和释放内存变慢)
b) 使用redis-cli -h $host -p $port --bigkeys扫描出很多bigkey
c) 使用redis-rdb-tools 工具分析,不影响redis使用
解决:a) 优化业务,避免存储bigkey
b) Redis 4.0+可开启lazy-free机制 - Redis AOF 配置级别
业务层面是否的确需要这一可靠性级别?如果我们需要高性能,同时也允许数据丢失,可以将配置项 no-appendfsync-on-rewrite 设置为 yes,避免 AOF 重写和 fsync 竞争磁盘 IO 资源,导致 Redis 延迟增加。当然, 如果既需要高性能又需要高可靠性,最好使用高速固态盘作为 AOF 日志的写入盘。 - Redis 实例的内存使用是否过大
查看发生 swap 了,如果是的话,就增加机器内存,或者是使用 Redis 集群,分摊单机 Redis 的键值对数量和内存压力。同时,要避免出现 Redis 和其他内存需求大的应用共享机器的情况。
分析:a) 实例内存达到maxmemory,且写入量大,淘汰key压力变大
b) Redis info中的evicted_keys指标短期突增
解决:a) 业务层面,根据情况调整淘汰策略(随机比LRU快)
b) 运维层面,监控evicted_keys指标,有短期突增及时报警
c) 集群扩容,多个实例减轻淘汰key的压力 - 在 Redis 实例的运行环境中,是否启用了透明大页机制
如果是的话,直接关闭内存大页机制就行了。 - 是否运行了 Redis 主从集群
如果是的话,把主库实例的数据量大小控制在 2~4GB,以免主从复制时,从库因加载大的 RDB 文件而阻塞。 - 是否使用了多核 CPU 或 NUMA 架构的机器运行 Redis 实例
使用多核 CPU 时,可以给 Redis 实例绑定物理核;使用 NUMA 架构时,注意把 Redis 实例和网络中断处理程序运行在同一个 CPU Socket 上。 - 生成RDB和AOF重写fork耗时严重
分析:a) Redis变慢只发生在生成RDB和AOF重写期间
b) 实例占用内存越大,fork拷贝内存页表越久
c) Redis info中latest_fork_usec耗时变长
解决:a) 实例尽量小
b) Redis尽量部署在物理机上
c) 优化备份策略(例如低峰期备份)
d) 合理配置repl-backlog和slave client-output-buffer-limit,避免主从全量同步 e) 视情况考虑关闭AOF f) 监控latest_fork_usec耗时是否变长 - 进程绑定CPU不合理
分析:a) Redis进程只绑定一个CPU逻辑核 b) NUMA架构下,网络中断处理程序和Redis进程没有绑定在同一个Socket下
解决:a) Redis进程绑定多个CPU逻辑核
b) 网络中断处理程序和Redis进程绑定在同一个Socket下