laravel7使用redis报错Error while reading line from the server / invalid bulk length

7 篇文章 0 订阅

问题描述:

代码是从另一个php项目拷贝过来了,都是用redis简单存储kv。本地报错有点懵逼,网上找了一下原因,大致是连接数过多,导致连接不上服务器,设置read_write_timeout=-1,重启服务等。试了没毛的用。。

use Illuminate\Support\Facades\Redis;
...

Redis::exists('proc:' . $relationId);
Redis::setex('proc:' . $v['id'], 10, 1);

$sendTimeList = Redis::get('sendTimeList');
if (!in_array($sendTime, $sendTimeList)) {
    $sendTimeList[] = $sendTime;
    Redis::set('sendTimeList', $sendTimeList); 
}

在这里插入图片描述


解决方案:

问题定位到最后的Redis::set('sendTimeList', $sendTimeList);,对比上面那两个redis发现存储的结构是数组会复杂一点,再结合偶尔会出现message:ERR Protocol error: invalid bulk length, 试着把数组转成字符串存储后就正常运行了。。

$sendTimeList = json_decode(Redis::get('sendTimeList'), true);
if (!in_array($sendTime, $sendTimeList)) {
    $sendTimeList[] = $sendTime;
    Redis::set('sendTimeList', json_encode($sendTimeList)); 
}

复盘
之前项目redis用的是1.1.1版本的predis,redis版本是3.2,可以正常运行。
当前项目laravel用的是1.1.7版本的predis,redis版本是6.0,报错。

docker给当前项目新增一个3.2版本的测试,发现还是会报错,排除redis版本问题。
1.1.7版本的问题?。。。不想研究了

不能解决问题?尝试其他方法~以下是复制粘贴过来了,搜索引擎翻了好几页都是这个玩意

连接数过多,导致连接不上服务器??
查看进程,看看是否有大量redis状态为TIME_WAIT的tcp连接。

有的话首先考虑减少TIME_WAIT的进程,保证随时可以连接到服务器,将进程快速回收。
修改内核参数sysctl.conf,net.ipv4.tcp_timestamps=1(1为开启),
开启快速回收net.ipv4.tcp_tw_recycle=1。
tw_recycle是通过时间戳判断哪个是最新的进程,将不是最新的TIME_WAIT的进程回收,所以需要先开启tcp_timestamps。

修改后观察,果然没有继续报错。

但是使能快速回收TIME_WAIT进程,可能会丢包,导致没有收到应答,不能成功建立连接。但这种办法也不是最佳解决办法,尤其修改内核参数,涉及环节太多,需深入了解才可修改。

底层不去修改,就从predis客户端入手,源码发现有read_write_timeout这个参数,可以设置超时时间,这样读取流数据时就不会报错。Predis作者建议设置关闭redis.conf中timeout(修改timeout 0),表示不关闭与客户端的连接,我感觉这样比较耗费资源,可以适当增加timeout时间。

所以这次暂时是这样解决的,设置read_write_timeout=-1和redis.conf的timeout参数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值