环境说明

阅读APP、小程序,项目是PHP写的,后端是MySQL+Redis。Redis做缓存使用,用户获取数据主要从Redis获取。三台应用服务器,一台Redis缓存服务器、一台MySQL服务器,均使用Ubuntu系统。每天中午推广,一个小时大约10万人次。

问题描述

某天中午推广时APP、×××小程序都出现了严重的卡顿,登录应用服务器发现Incoming的流量达600MBit/s,Redis服务器Outgoing流量最高1.44GBit/s,其它系统监控信息正常(CPU、IO、Mem)。

解决步骤

  • 通过上面信息进行初步诊断:在没有发现CPU、内存、IO这些方面的一场后,通过在应用服务器使用nload命令发现流量高达600MBit/s,随机查看访问日志,排除了恶意访问和流量×××情况。
  • 用iftop命令查看流量出入,发现主要是与Redis服务器通讯时出现的流量高,在iftop命令中按 t 切换流入流出方向,发现是从Redis流入的数据<=
  • 登录Reids服务器使用nload发现流量最高能达到1.4GBit/s
    Redis服务器出口流量高的解决思路_第1张图片
  • 可以确定是用户访问数据,然后PHP从Redis获取数据时导致的,应该是Redis某个key较大且频繁访问导致的。
  • 在目前流量高的情况下,在redis执行redis_cli的monitor保存当前命令执行情况
    redis-cli -a xxxxxxx monitor > /tmp/redis.rt
  • 然后用第三方工具redis-rdb-tools对Redis备份文件dump.rdb进行分析
    安装
    git clone https://github.com/sripathikrishnan/redis-rdb-tools.git·
    ·cd redis-rdb-tools/·
    ·python setup.py install

    导出所有key信息到csv文件
    rdb -c memory /data/redis/dump.rdb --bytes 128 -f /tmp/memory.csv
    对csv文件分析导出key及大小排序
    awk -F',' '{print $4,$2,$3,$1}' memory.csv |sort -nr > memory.sort
  • 通过上面的方式找到最大的key,发现了最大的key将近10M
    Redis服务器出口流量高的解决思路_第2张图片
  • 此时,把之前一直在monitor的命令停掉,可以看到/tmp/redis.rt这个文件,我们通过下面命令查询所有执行最大的那个key的命令频率
    grep '_ci_redis_serialized' redis.op|awk -F'[ |.]' '{print $1,$9}'|sort|uniq -c|sort -nr
    Redis服务器出口流量高的解决思路_第3张图片
  • 发现最大每秒执行2783次,我们从redis服务器本地登录redis,试试 SISMEMBER _ci_redis_serialized的情况
    Redis服务器出口流量高的解决思路_第4张图片
  • 发现这个key是一个集合,并且有12万个元素,而且本地查就需要20多秒!
  • 通知开发赶紧去处理,经过开发确认,这个key从上线就开始累加,没有设置过期时间,才导致越来越大的。
  • 确认发现这个key已经可以删掉,于是到redis服务 del _ci_redis_serialized删掉了这个key
  • 流量从1.44G瞬间下降到了1150KBit/s !!
    Redis服务器出口流量高的解决思路_第5张图片
    Redis服务器出口流量高的解决思路_第6张图片