解决redis并发过高导致的各项问题看这篇就够了

305 阅读5分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第12天,点击查看活动详情

前言

你是不是经常能在redis日志里面发现报错:

    [2489] 02 Jun 10:43:42 # Error allocating resoures for the client

错误是无法为客户端分配资源,查看redis连接数:

# redis-cli info | grep connected       

connected_clients:5036

connected_slaves:0

客户端的连接竟然有达到5000多

其实最高的时候我发现有达到9000多的情况🐶

查看客户端连接情况:

redis 127.0.0.1:22151> client list

addr=10.247.64.115:52834 fd=5 idle=21 flags=N db=0 sub=0 psub=0 qbuf=0 obl=0 oll=0 events=r cmd=rpush

addr=127.0.0.1:38484 fd=7 idle=0 flags=N db=0 sub=0 psub=0 qbuf=0 obl=0 oll=0 events=r cmd=blpop

addr=10.105.1.2:53125 fd=8 idle=21 flags=N db=0 sub=0 psub=0 qbuf=0 obl=0 oll=0 events=r cmd=rpush

addr=10.105.1.3:32639 fd=9 idle=21 flags=N db=0 sub=0 psub=0 qbuf=0 obl=0 oll=0 events=r cmd=rpush

addr=10.105.1.4:57134 fd=10 idle=21 flags=N db=0 sub=0 psub=0 qbuf=0 obl=0 oll=0 events=r cmd=rpush

addr=10.105.1.5:53126 fd=11 idle=21 flags=N db=0 sub=0 psub=0 qbuf=0 obl=0 oll=0 events=r cmd=rpush

addr=10.105.1.7:8887 fd=12 idle=21 flags=N db=0 sub=0 psub=0 qbuf=0 obl=0 oll=0 events=r cmd=rpush

每个字段含义如下:

addr:客户端的地址和端口

fd:套接字所使用的文件描述符

idle:以秒计算的空闲时长

flags:客户端 flag

db:该客户端正在使用的数据库 ID

sub:已订阅频道的数量

psub:已订阅模式的数量

multi:在事务中被执行的命令数量

qbuf:查询缓冲区的长度(字节为单位, 0 表示没有分配查询缓冲区)

qbuf-free:查询缓冲区剩余空间的长度(字节为单位, 0 表示没有剩余空间)

obl:输出缓冲区的长度(字节为单位, 0 表示没有分配输出缓冲区)

oll:输出列表包含的对象数量(当输出缓冲区没有剩余空间时,命令回复会以字符串对象的形式被入队到这个队列里)

omem:输出缓冲区和输出列表占用的内存总量

events:文件描述符事件

cmd:最近一次执行的命令

一开始我也考虑过,是否是因为客户端的idle空闲时间太长导致连接池维持了太多的无效连接,那么把不用的连接及时的释放就可以,比如:

redis 127.0.0.1:22151> CONFIG SET timeout 30

OK

但是实际上我们的超时已经设置过了,并且我们通过上面的记录可以发现,客户端idle空闲的时间其实并不长

于是我们继续查询客户端连接数的分布情况

    netstat -an |grep 22151|awk '{print $5}'|awk -F: '{print $1}'|sort|uniq -c

大致可以得到:

12:15

      1 0.0.0.0

      1 10.153.192.4

      5 10.153.206.85

    205 10.25.172.208

    490 10.26.95.96

    469 10.27.226.222

    461 10.27.228.69

    400 10.31.132.250

    479 10.45.52.79

    431 10.47.110.98

    481 10.47.77.34

分析下来,因为我们的业务基本全是使用hash的方式存储,并且有大量用到hgetall的场景,入口处的并发也高,所以redis备机连接数过高,导致读取、连接超时

于是我想到了twemproxy

twemproxy(nutcracker)

twemproxy(nutcracker) 是 Twitter开源的轻量级 memcached / redis 代理服务器,本质就是一个集群管理工具,主要用来弥补 Redis和 Memcached对集群管理的不足,非常适合我们目前所遇到的场景

常规步骤

下载压缩包到服务器的目录中 我的全部包都在 /home/source 文件夹中

github地址:

   github.com/twitter/twe…

  • github版本:
git clone <https://github.com/twitter/twemproxy.git>

cd twemproxy

autoreconf -fvi

./configure --prefix=/usr/local/webserver/nutcracker

make && make install

如果中间进行不下去报错啦,注意一下,服务器上是否安装了

autoreconfautoconfautomakelibtool

用 -h 检查一下,找不到的话用 yum install xxx(缺少的环境)

安装一下然后重新继续上次报错停止的步骤就行了

企业微信截图_82e92ee8-d267-4710-8437-a278b30482d3.png

下载一个最新的:如下图

企业微信截图_0397e957-a252-46c0-b5e2-71320576c54a.png

然后用 rz || rz -y 上传到服务器的 /home/source 文件夹中

配置 nutcracker 以及[做一个连接(相当于快捷方式)]

配置 nutcracker.yml 文件代码(推荐在 /etc/ 中自建一个配置文件)

alpha:

  listen: 127.0.0.1:22151

  hash: fnv1a_64

  distribution: ketama

  auto_eject_hosts: true

  redis: true

  server_retry_timeout: 2000

  server_failure_limit: 1

  servers:

   - 10.25.68.40:22151:1



beta:

  listen: 127.0.0.1:22152

  hash: fnv1a_64

  distribution: ketama

  auto_eject_hosts: true

  timeout: 400

  redis: true

  servers:

   - 10.28.254.194:22151:1

建立连接: ln -n 源启动文件 名为nutcracker的快捷启动文件

ln -n /usr/local/webserver/nutcracker/sbin/nutcracker /usr/bin/nutcracker

启动

如何启动 nutcracker 并可以使其断开后自动重新连接并输出日志

写一个脚本,并在一个死循环内部的写运行 nutcracker 的方法: nutcracker(由于上面做过连接可以在任何地方直接调用) -c (配置文件 nutcracker.yml 的位置),为了便于记录进程死的次数,再输出一份重启的日志并记录时间,最后通过 screen 的方式挂在服务器上跑就行了

脚本代码:

while true

do

        day=`date "+%y-%m-%d %H:%M:%S"`

        echo -e "nutcracker Restart "$day"\n" >> ~/logs/nutcracker.log

        nutcracker -c /etc/nutcracker.yml

done
screen -S nutcracker (新建一个名为nutcracker的窗口)

cd /data/auto (脚本放置位置)

./脚本.sh

control + a + d (将screen挂在后台运行)

总结

企业微信截图_0ebe5258-7565-4a74-b122-ea9e748d4e51.png

再检查一下 启动日志是否在正常输出

tail -f ~/logs/nutcracker.log