第七章 Redis的噩梦:阻塞
2019-08-12 本文已影响0人
super_pcm
Redis是典型的单线程架构,所有的读写操作都是在一条主线程中完成的。当Redis用于高并发场景时,这条线程就变成了它的生命线。如果出现阻塞,哪怕是很短时间,对于我们的应用来说都是噩梦。导致阻塞问题的场景大致分为内在原因和外在原因:
- 内在原因包括:不合理地使用API或数据结构、CPU饱和、持久化阻塞等。
- 外在原因包括:CPU竞争、内存交换、网络问题等。
本章我们聚焦于Redis阻塞问题,通过学习本章可掌握快速定位和解决Redis阻塞的思路和技巧。
7.1 发现阻塞
当Redis服务发生阻塞时,最先感应到的就是线上业务了,这时候应该会出现大量的异常消息。这时候我们可以在应用方加入异常统计并通过告警来处理,这个需要开发和运维的共同协助处理。
7.2 内在原因
定位到具体的Redis节点异常后,首先应该排查是否是Redis自身原因导致,围绕以下几个方面排查:
- API或数据结构使用不合理。
API数据的不合理很有可能是使用了不合理的数据类型,或者说是执行了算法复杂度高的命令,比如keys *。这个时候我们通过检查慢查询信息来找到引起阻塞的命令,然后进行对应的优化,优化的办法包括使用低算法度的命令以及调整大对象。 - CPU饱和的问题。
单线程的Redis处理命令时只能使用一个CPU。而CPU饱和是指Redis把单核CPU使用率跑到接近100%。使用top命令很容易识别出对应Redis进程的CPU使用率。CPU饱和是非常危险的,将导致Redis无法处理更多的命令,严重影响吞吐量和应用方的稳定性。对于这种情况,首先判断当前Redis的并发量是否达到极限,建议使用统计命令redis-cli -h{ip} -p{port} --stat获取当前Redis使用情况,该命令每秒输出一行统计信息。
通常情况下CPU饱和的问题都是由于请求处理过于频繁造成的性能瓶颈,这种情况下应该考虑集群来分摊OPS的压力;如果是由于使用了算法复杂度高的命令造成的,请减少使用;过度放宽ziplist的使用条件也会造成CPU的使用过高,需要在CPU和内存之间做好平衡。
- 持久化相关的阻塞。
持久化引起主线程阻塞的操作主要有:fork阻塞、AOF刷盘阻塞、HugePage写操作阻塞。这些在前面的知识点上都有介绍了。
7.3 外在原因
排查Redis自身原因引起的阻塞原因之后,如果还没有定位问题,需要排查是否由外部原因引起。围绕以下三个方面进行排查:
- CPU竞争
Redis和其他的CPU密集型的应用部署在同一台机器上会容易引起Redis的CPU竞争问题;此外,如果Redis做了绑定CPU的操作也可能会造成激烈的CPU竞争(做持久化的时候) - 内存交换
内存不足造成使用了SWAP,这时候需要保证机器有充足的内存,还需要配置Redis实例可用的最大内存(maxmemory) - 网络问题
网络不稳定造成的阻塞;Redis的连接数到了maxclients的限制造成的阻塞;Linux文件最大可打开数目造成的阻塞;backlog队列溢出造成的阻塞。