问题过程

输入法业务于12月12日上线词库推送业务,根据用户uuid(uuid平台校验)进行词库推送,在12月17日早上8点多开始出现大量的php报错(Redis went away),报错导致了大量的链接积累,瞬间服务器的80端口堆积到了2w多导致了接收计费日志的接口全部返回超时,丢失了1小时的结费数据。

报错内容如下:

[17-Dec-2018 01:32:51 UTC] PHP Fatal error:  Uncaught exception 'RedisException' with message 'Redis server went away' in /opt/case/update.pinyin.2345.com/UuidForRedis.php:75
Stack trace:
#0 /opt/case/update.pinyin.2345.com/UuidForRedis.php(75): Redis->auth('KangDuiShiWei')
#1 /opt/case/update.pinyin.2345.com/UuidForRedis.php(59): UuidForRedis->connectRedis()
#2 /opt/case/update.pinyin.2345.com/pinyin/cloud_switch.php(160): UuidForRedis->__construct()
#3 /opt/case/update.pinyin.2345.com/cloud_config_new.php(187): include('/opt/case/updat...')
#4 {main}
 thrown in /opt/case/update.pinyin.2345.com/UuidForRedis.php on line 75

排查过程:

收到服务器的80端口报警后,查看php错误是Redis链接超时,因Redis链接的时候设置的超时是10s,导致大量的80端口堆积,造成该机组其他业务接口全部都出现了5xx的错误。

线上解决:

链接Redis的时候增加超时设置,并设置为1秒,当Redis有链接问题的时候不会操作请求接口等待超时,上线后解决。

疑问:

那么现在你可能就有疑问了,redis为什么会时不时的就出现了Redis went away的错误呢?并且在并发高的时候越发明显,是不是redis并发扛不住了?

Redis排查过程

日志收集

1、 该Redis是一个公共uuid平台,确认线上所有链接是否都加了超时,没有全部加上并设置为1秒,并上线

2、挑选3个业务对Redis链接增加try catch捕获并将异常日志记录到文本一边后续分析

错误部分摘要:

2018-12-20 08:00:06 Redis server went away
2018-12-20 08:00:06 Redis server went away
2018-12-20 08:00:06 Redis server went away
2018-12-20 08:00:06 Redis server went away
2018-12-20 08:00:06 Redis server went away
2018-12-20 08:05:06 Redis server went away
2018-12-20 08:05:06 Redis server went away
2018-12-20 08:05:06 Redis server went away
2018-12-20 08:05:06 Redis server went away
2018-12-20 08:05:06 Redis server went away
2018-12-20 08:05:06 Redis server went away
2018-12-20 08:05:06 Redis server went away
2018-12-20 08:05:06 Redis server went away
2018-12-20 08:05:06 Redis server went away
2018-12-20 08:10:06 Redis server went away
2018-12-20 08:10:06 Redis server went away
2018-12-20 08:10:06 Redis server went away
2018-12-20 08:10:06 Redis server went away
2018-12-20 08:10:06 Redis server went away
2018-12-20 08:10:06 Redis server went away
2018-12-20 08:10:06 Redis server went away
2018-12-20 08:10:06 Redis server went away
2018-12-20 08:10:06 Redis server went away
2018-12-20 08:10:06 Redis server went away
2018-12-20 08:10:06 Redis server went away
2018-12-20 08:10:06 Redis server went away
2018-12-20 08:10:06 Redis server went away
2018-12-20 08:10:06 Redis server went away
2018-12-20 08:10:06 Redis server went away
2018-12-20 08:10:06 Redis server went away
2018-12-20 08:10:06 Redis server went away
2018-12-20 08:10:06 Redis server went away
2018-12-20 08:10:06 Redis server went away
2018-12-20 08:10:06 Redis server went away
2018-12-20 08:10:06 Redis server went away
2018-12-20 08:10:06 Redis server went away
2018-12-20 08:10:06 Redis server went away
2018-12-20 08:10:06 Redis server went away
2018-12-20 08:10:06 Redis server went away
2018-12-20 08:10:06 Redis server went away
2018-12-20 08:10:06 Redis server went away
2018-12-20 08:10:06 Redis server went away
2018-12-20 08:10:06 Redis server went away
2018-12-20 08:10:06 Redis server went away
2018-12-20 08:10:06 Redis server went away
2018-12-20 08:10:06 Redis server went away
2018-12-20 08:10:06 Redis server went away
2018-12-20 08:10:06 Redis server went away
2018-12-20 08:10:06 Redis server went away
2018-12-20 08:10:06 Redis server went away
2018-12-20 08:10:06 Redis server went away
2018-12-20 08:10:06 Redis server went away
2018-12-20 08:10:06 Redis server went away
2018-12-20 08:15:06 Redis server went away

排查过程

联系运维,先考虑从以下步骤依次排查问题的原因:

  • 内网网络问题

  • redis错误日志

  • redis的慢日志

  • 防火墙的配置

  • 系统错误日志

  • 持久化配置

第一步:内网网络问题猜测

该问题实际不好测试重现,通过实际测试代码测试和业务日志情况分析,排除该问题

第二步:查看Redis错误日志

Redis错误日志在redis.conf中的logfile配置中,查看确认后无异常

第三步:查看redis的慢日志

通过链接redis-cli 输入slowlog get查看最近128条的慢日志信息,从慢日志上分析除了有keys的异常命令外其他都表现正常,可以再排除,继续往下排查

部分信息如下:
27.0.0.1:6379> SLOWLOG get
1) 1) (integer) 52
  2) (integer) 1545183329
  3) (integer) 58086
  4) 1) "KEYS"
      2) ""
  5) "172.16.30.154:40135"
  6) ""
2) 1) (integer) 51
  2) (integer) 1545182639
  3) (integer) 68437
  4) 1) "KEYS"
      2) ""
  5) "172.16.30.154:28131"
  6) ""

Redis的慢日志为啥会有keys命令,通过排查发现所有的请求是通过在线Redis平台过去的,因为Redis是单进程单线程的,经过评估觉得该操作还是有一定风险,所以我们暂时关闭了所有在线redis平台的查看权限

第四步:查看防火墙的配置

当前这里所说的防火墙不是防火墙配置错了,那种错误是所有的链接都会被拒绝,现在的问题是时不时的会出现Redis went away错误,据某业务数据统计,1小时55万请求里约有300多请求出现了该问题。

检查iptables是否打开了nat转发模块,iptables在高并发连接时丢包,可能导致连接超时ip_conntrack: table full, dropping packet,与运维确认后未开启该模块,排查了该点。

具体参考该网页关于iptables的说明:https://zhangxugg-163-com.iteye.com/blog/2404170

第五步:查看系统错误日志

运维登录该Redis机器,查看系统message里var/log/message是否有相关的错误信息,排查后错误信息正常。

第六步:redis的持久化配置

排查到这里还有一个重要的配置不能错过,redis的持久化配置rdb和aof都有可能导致阻塞给客户端链接操作了链接超时的情况。

先排查默认的持久化配置,通过命令和配置文件查看redis的rdb配置如下,aof未开启可忽略

save 900 1 // 900内,有1条写入,则产生快照
save 300 1000 // 如果300秒内有1000次写入,则产生快照
save 60 10000 // 如果60秒内有10000次写入,则产生快照

先关闭持久化配置,并观察线上的错误信息是否有变化

config set save ""

关闭后观察了1小时未有特别明显的变化,继续排查

第七步:排查是否phpredis扩展的版本

备注:php机器的版本是5.3,redis扩展的版本为xxx,线上Redis的版本是4.0

这个其实不好下定论,但是凑巧该业务还连接了另一台Redis机器,该Redis的版本也是4.0版本,但从收集的错误日志来看未出现任何错误信息,所以反向推论可以得出Redis扩展的版本并无问题。

继续思考,排查ing...

但从最近收集到的错误日志来看,有一个有规律的特征,每隔5分钟的05秒左右就会规律性的出现错误,这个点的数据应该引起警觉,有规律每隔5分钟出现一次,是不是有crontab再定时做持久化rdb呢?

联系运维再验证一下:

通过redis-cli monitor将最近5分钟的监控日志全部dump到文本文件中,然后对文本文件的命令进行分析,未发现异常的命令情况。

后续补充:redis的save和bgsave并不会在monitor监控列表里出现(4.x),但从其他方面验证了没有业务使用命令行进行了定时的save或bgsave操作

第八步:查看crontab配置

是不是crontab有5分钟一次的相关配置,的确找到了一条,这个大家一下就会比较熟悉,公司所有机器都会有定时同步时间的:

*/5 * * * *  /usr/sbin/ntpdate -s monitor.50bang.org || /usr/bin/rdate -s monitor.50bang.org; /sbin/hwclock -w

这个应该不会有问题了,但是该排查的都排查了,先去掉再看看情况:

5min

5min

5min

...

再查看3个业务线上的错误日志,日志全部变少了,从有规律的5分钟出错10来条,变成了1小时只有几条错误,另两个业务无错误了。

你可能也会一下就会联想就是这个问题了,但是为什么更新时间会影响redis操作呢,这个理论上都关联不上了,我们在反向验证一下,把crontab再打开再观察错误情况,如果错误又回来了那肯定就是这玩意导致的了。

继续分析crontab的命令,把定时关掉,手动执行命令再观察业务机器是否有报错信息:

① 执行ntpdate命令,走的是udp协议,机房封了该协议,该命令返回是失败的,执行并无影响排除

② 执行rdate命令,业务机器未发现错误,排除

③执行/sbin/hwclock -w命令,业务机器发现错误!!!发现错误!!!稳定重现!!!

看到这里,那么你关心的结果来了:

/sbin/hwclock -w在执行的过程中会导致Redis的客户端链接出现Redis Went away现象。

但使用相同方法在测试环境未能重现现象

结论

/sbin/hwclock -w命令在执行的过程中会导致php客户端连接Redis服务器出现一定机率的Redis Went away错误,该命令一般执行时间约1-2秒,所以就出现了之前每隔5分钟就定时出现一个错误信息。

后续为什么该命令会影响Redis的服务呢,据与其他业务了解很多软件都依赖于时间服务,时间服务的变动都会影响到相关业务的服务提供。

后续优化

1、 所有业务链接第三方的api或服务,比如curl、redis、mysql等都需要设置超时

2、Redis设置超时时间建议最大为1秒,根据业务可以减少到毫秒,超时后需要有异常捕获

Redis went away的更多相关文章

  1. 使用redis构建可靠分布式锁

    关于分布式锁的概念,具体实现方式,直接参阅下面两个帖子,这里就不多介绍了. 分布式锁的多种实现方式 分布式锁总结 对于分布式锁的几种实现方式的优劣,这里再列举下 1. 数据库实现方式 优点:易理解 缺 ...

  2. Ignite性能测试以及对redis的对比

    测试方法 为了对Ignite做一个基本了解,做了一个性能测试,测试方法也比较简单主要是针对client模式,因为这种方法和使用redis的方式特别像.测试方法很简单主要是下面几点: 不作参数优化,默认 ...

  3. mac osx 安装redis扩展

    1 php -v查看php版本 2 brew search php|grep redis 搜索对应的redis   ps:如果没有brew 就根据http://brew.sh安装 3 brew ins ...

  4. Redis/HBase/Tair比较

    KV系统对比表 对比维度 Redis Redis Cluster Medis Hbase Tair 访问模式    支持Value大小 理论上不超过1GB(建议不超过1MB) 理论上可配置(默认配置1 ...

  5. Redis数据库

    Redis是k-v型数据库的典范,设计思想及数据结构实现都值得学习. 1.数据类型 value支持五种数据类型:1.字符串(strings)2.字符串列表(lists)3.字符串集合(sets)4.有 ...

  6. redis 学习笔记(2)

    redis-cluster 简介 redis-cluster是一个分布式.容错的redis实现,redis-cluster通过将各个单独的redis实例通过特定的协议连接到一起实现了分布式.集群化的目 ...

  7. redis 学习笔记(1)

    redis持久化 snapshot数据快照(rdb) 这是一种定时将redis内存中的数据写入磁盘文件的一种方案,这样保留这一时刻redis中的数据镜像,用于意外回滚.redis的snapshot的格 ...

  8. python+uwsgi导致redis无法长链接引起性能下降问题记录

    今天在部署python代码到预生产环境时,web站老是出现redis链接未初始化,无法连接到服务的提示,比对了一下开发环境与测试环境代码,完全一致,然后就是查看各种日志,排查了半天也没有查明是什么原因 ...

  9. nginx+iis+redis+Task.MainForm构建分布式架构 之 (redis存储分布式共享的session及共享session运作流程)

    本次要分享的是利用windows+nginx+iis+redis+Task.MainForm组建分布式架构,上一篇分享文章制作是在windows上使用的nginx,一般正式发布的时候是在linux来配 ...

  10. windows+nginx+iis+redis+Task.MainForm构建分布式架构 之 (nginx+iis构建服务集群)

    本次要分享的是利用windows+nginx+iis+redis+Task.MainForm组建分布式架构,由标题就能看出此内容不是一篇分享文章能说完的,所以我打算分几篇分享文章来讲解,一步一步实现分 ...

随机推荐

  1. KVM虚拟机配置

    KVM 全称是 Kernel-Based Virtual Machine.也就是说 KVM 是基于 Linux 内核实现的,KVM有一个内核模块叫 kvm.ko,只用于管理虚拟 CPU 和内存. 在 ...

  2. [学习笔记]后缀自动机SAM

    好抽象啊,早上看了两个多小时才看懂,\(\%\%\%Fading\) 早就懂了 讲解就算了吧--可以去看看其他人的博客 1.[模板]后缀自动机 \(siz\) 为该串出现的次数,\(l\) 为子串长度 ...

  3. Oracle SQL Developer连接报错以及链接oracle的sqlplus出现协议适配器错误

    之前用的好好的Oracle SQL Developer,不知道是不是匆忙关闭软件啥东西没保存或是删了什么东西,今天突然用不了的. 大清早的,打开Oracle SQL Developer,就给我一个惊喜 ...

  4. (原创)Callable、FutureTask中阻塞超时返回的坑点

    直接上代码 import java.util.concurrent.Callable; public class MyCallable implements Callable<String> ...

  5. python进程——生产者消费者

    生产者消费者模型介绍 为什么要使用生产者消费者模型 生产者指的是生产数据的任务,消费者指的是处理数据的任务,在并发编程中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完 ...

  6. [Spring]@Autowired,@Required,@Qualifier注解

    @Required注解 @Required注解用于setter方法,表明这个属性是必要的,不可少的,必须注入值 假设有个测试类,里面有name和password两个属性 我给两个属性的setter方法 ...

  7. System.Threading.ThreadAbortException: 正在中止线程

    症状 如果使用 Response.End.Response.Redirect 或 Server.Transfer 方法,将出现 ThreadAbortException 异常.您可以使用 try-ca ...

  8. 基于vue的web应用如何构建成手机端的原生安装包

    话不多说,点击前往

  9. 全网最详细的Windows里下载与安装Sublime Text *(图文详解)

    不多说,直接上干货! 前言 这是代码编程软件,可以性感编程自己代码,有着非常丰富的插件,界面整洁清爽.第一次使用可能不习惯,当你使用一段时间之后,你就会爱上它. 下载与安装 1.下载:目前官方的正式版 ...

  10. 磁盘分区以及Linux目录挂载详解

    一.背景 一直以来,对于磁盘的分区以及Linux目录挂载的概念都不是很清晰,现在趁着春暖花开周末在家没事就研究了下它们,现在来分享我的理解. 二.概念详解 1.磁盘分区 磁盘分区是把物理的磁盘空间按照 ...