使用redis搭建分布式系统时如何处理网络延迟和网络异常?

1. 使用复杂度高的命令

定义

  如果你的服务请求量并不大,但Redis实例的CPU使用率很高,很有可能是使用了复杂度高的命令导致的。

解决方案

  不使用这些复杂度高的命令, 并且一次不要获取太多的数据, 每次尽量操作少量的数据, 让Redis可以及时处理返回

2. 存储bigkey

定义

  一个key写入的数据非常大,Redis在分配内存时也会比较耗时。同样的,当删除这个key的数据时,释放内存也会耗时比较久。

解决方案

  lazy-free机制, 用于异步存放bigkey的内存, 降低对Redis性能的影响

3. 集中过期

定义

  在使用Redis时没有延时比较大的情况,但在某个时间点突然出现一波延时,而且报慢的时间点很有规律,例如某个整点,或者间隔多久就会发生一次。

解决方案

  1. 在集中过期时增加一个随机时间, 把这些需要过期的key的时间打散, 这样Redis在处理过期时,不会因为集中删除key导致压力过大,阻塞主线程。

  2. 做法是我们需要把Redis的各项运行数据监控起来,执行info可以拿到所有的运行数据,在这里我们需要重点关注expired_keys这一项,它代表整个实例到目前为止,累计删除过期key的数量。

4. 实例内存达到上限

定义

  有时我们把Redis当做纯缓存使用,就会给实例设置一个内存上限maxmemory,然后开启LRU淘汰策略。

  当实例的内存达到了maxmemory后,你会发现之后的每次写入新的数据,有可能变慢了。

  导致变慢的原因是,当Redis内存达到maxmemory后,每次写入新的数据之前,必须先踢出一部分数据,让内存维持在maxmemory之下。

解决方案

  可以考虑拆分实例的方法来缓解,拆分实例可以把一个实例淘汰key的压力分摊到多个实例上,可以在一定程度降低延迟。

5. fork耗时严重

定义

  如果你的Redis开启了自动生成RDB和AOF重写功能,那么有可能在后台生成RDB和AOF重写时导致Redis的访问延迟增大,而等这些任务执行完毕后,延迟情况消失。

解决方案

  要想避免这种情况,我们需要规划好数据备份的周期,建议在从节点上执行备份,而且最好放在低峰期执行。如果对于丢失数据不敏感的业务,那么不建议开启AOF和AOF重写功能。

6. 不要绑定CPU

  在部署Redis进程时,如果需要开启RDB和AOF重写机制,一定不能进行CPU绑定操作!

7. 合理分配AOF机制

  开启AOF后,Redis会把写入的命令实时写入到文件中,但写入文件的过程是先写入内存,等内存中的数据超过一定阈值或达到一定时间后,内存中的内容才会被真正写入到磁盘中。

8. 停止使用Swap

  如果你发现Redis突然变得非常慢,每次访问的耗时都达到了几百毫秒甚至秒级,那此时就检查Redis是否使用到了Swap,这种情况下Redis基本上已经无法提供高性能的服务。

9. 网卡负载过高

定义

  网卡负载过高,在网络层和TCP层就会出现数据发送延迟、数据丢包等情况。Redis的高性能除了内存之外,就在于网络IO,请求量突增会导致网卡负载变高。

解决方案

  你需要排查这个机器上的哪个Redis实例的流量过大占满了网络带宽,然后确认流量突增是否属于业务正常情况,如果属于那就需要及时扩容或迁移实例,避免这个机器的其他实例受到影响。

  运维层面,我们需要对机器的各项指标增加监控,包括网络流量,在达到阈值时提前报警,及时与业务确认并扩容。