高并发下PHP请求Redis异常处理
来源:互联网 发布:中国网络远程学校 编辑:程序博客网 时间:2024/05/16 03:31
最近发现线上服务器经常报连接redis异常:Uncaught exception 'RedisException' with message 'Redis server went away'
。
于是摘下一台线上机,对服务器一半以上的接口进行压测:
$ http_load -p 100 -f 100000 urls.txt 100000 fetches, 100 max parallel, 2.46403e+09 bytes, in 46.6896 seconds24640.3 mean bytes/connection2141.81 fetches/sec, 5.27747e+07 bytes/secmsecs/connect: 1.04977 mean, 3.755 max, 0.859 minmsecs/first-response: 44.0343 mean, 142.5 max, 11.804 minHTTP response codes: code 200 -- 100000$ http_load -p 100 -s 100 urls.txt145919 fetches, 100 max parallel, 3.65654e+09 bytes, in 100 seconds25058.7 mean bytes/connection1459.19 fetches/sec, 3.65654e+07 bytes/secmsecs/connect: 1.10872 mean, 14.339 max, 0.863 minmsecs/first-response: 65.4696 mean, 1012.95 max, 12.124 min11082 bad byte countsHTTP response codes: code 200 -- 134837 code 500 -- 11082
发现当接口的请求量达到10w的时候,QPS可以达到2000以上;请求量超过10w的时候,QPS会降到1500以下,需要访问redis服务的接口会出现Redis server went away
异常,并返回500
。
难道说现在机器负载的瓶颈就是redis了吗?压力测试时的redis服务器压力大么?
从监控的趋势图可以看到,压测接口请求的redis最高QPS也就20000,客户端连接数只有不到80,压力并不大。所以瓶颈不会是在redis服务器上。
在排除了Linux,php,nginx,redis配置方面可能出现的问题后,最后锁定问题,应该是在连接Redis的时候出现异常。那PHP是如何连接redis的呢?使用redis扩展。而问题很有可能出在php的redis扩展上,就是phpredis
。
通常我们在使用phpredis
连接redis的时候,都是用的connect()
方法,在大量的php请求请求到redis的时候,这种方式会不断的建立和关闭连接,占用很多资源,导致服务器出现大量的TIME_WAIT
,这样就会有很多php请求无法连接redis,出现Redis server went away
这个异常,实际就说明redis服务没有收到请求,所以昨天看到在压测过程中redis负载压力并不大,但php还是返回500
。
之前的思路都是以为redis层面问题或者服务器配置甚至硬件问题,在换个思路之后,发现phpredis还有个连接redis的方法,就是pconnect()
,这个方法很多人都知道,但是很少把它和高并发联系到一起,pconnect()
和connect()
的区别网上有很多,总结一下就是pconnect
方法建立后的连接并不随这请求的结束而关闭,而是依赖于php-fpm
进程,php-fpm
进程不死,redis connect
就一直存在,直到空闲超时自动断开(目前redis timeout 600
),这样就极大的提高了redis connect
的重复利用,减少大量的IO
开销。不过这样也就出现一个瑕疵,就是redis的connect clients
数量要比以前高出很多,目前线上机单台服务器php-fpm
进程300,线上服务器共有12台,单台redis最高connect clients
可以达到3600,不过这也远低于单台redis配置的maxclients 200000
。
所以我在之前的机器上做了修改,然后重新压测:
$ http_load -p 100 -s 100 urls.txt 253884 fetches, 100 max parallel, 6.44571e+09 bytes, in 100 seconds25388.4 mean bytes/connection2538.84 fetches/sec, 6.4457e+07 bytes/secmsecs/connect: 1.07964 mean, 13.918 max, 0.858 minmsecs/first-response: 36.6679 mean, 250.973 max, 7.66 min1 bad byte countsHTTP response codes: code 200 -- 253884
可以看到100个进程跑了100s,请求量253884,QPS达到2538.84,这个数字基本正常。
再看一下redis负载情况:
重新上线了三台机器之后,可以看到redis端connect_clients
明显增加,但是QPS还是很平稳(请忽略压测导致的凸起点)。
最后有必要反思一下这个过程,其实最后解决问题的方法是有点狗血的,因为pconnect方法很多人都知道,但是都没有把这个方法和高并发请求redis联系起来,所以我严重怀疑很多人对这个方法理解的并不深刻。在遇到问题时,一定要敢于尝试,如果你发现这个问题Google上都没有答案的时候,你应该觉得这是个挑战,所以不要轻易放弃。还有眼界要广,不要纠结于一个点,像redis这么成熟的软件系统,十万级的访问量基本不会构成威胁,所以要检查一个请求经过的每一个环节。
- 高并发下PHP请求Redis异常处理
- 高并发下PHP请求Redis异常处理
- PHP中利用redis实现消息队列处理高并发请求--简洁代码实现效果
- PHP中利用redis实现消息队列处理高并发请求
- PHP中利用redis实现消息队列处理高并发请求
- php处理抢购类功能的高并发请求
- 备忘:Windows下php-cgi不能处理并发PHP请求
- php结合redis高并发下发帖、发微博
- php结合redis高并发下发帖、发微博
- Redis和请求队列解决高并发
- php+redis+TP处理并发
- PHP 处理高并发问题
- 利用redis缓存解决高并发下后端重复请求措施
- 利用redis缓存解决高并发下后端重复请求措施
- ajax异步请求高并发处理
- 高并发处理,CDN,redis---31
- 高并发下合并接口请求
- redis下高并发投票设计
- PCH was compiled with module cache oldpath newpath解决办法
- Hibernate入门
- 返回值的锁
- 面试专题之一Fragment的生命周期
- IOS 常用的宏
- 高并发下PHP请求Redis异常处理
- 取得spring上下文
- 信道估计算法
- Spinner的简单使用
- spark sql dataframe操作
- html5部分总结
- uva12124 Assemble
- Java常见的几种内存溢出及解决方法
- 笔记:多线程