php+redis在实际项目中HTTP 500: Internal Server Error故障排除


Posted in PHP onFebruary 05, 2017

问题描述
用户量快速增长,访问量在短时间内翻倍,由于前期容量规划做得比较好,硬件资源可以支撑,可是软件系统方面出现了大问题:
40% 的请求都会返回 HTTP 500: Internal Server Error
通过查看日志,发现错误是在 PHP <-> Redis 的连接处理上
调试处理

第1次
刚开始时并没有找到根本原因,只能尝试各种与错误相关的办法,例如:
增加 PHP 连接数,并把超时时间从 500ms 增加到 2.5s
禁止掉 PHP 设置中的 default_socket_timeout
在主机系统中禁止掉 SYN cookies
检查 Redis 和 Webservers 的文件描述符数量
增加主机系统的 mbuffer
调整 TCP backlog 数量
……

尝试了很多方法,但全部无效

第2次
想在预发布环境中重现这个问题,可惜,还是没成功,应为流量不够大,无法复现

第3次
会不会是代码中没有关闭 Redis 连接呢?
正常来讲,PHP在执行结束时会自动关闭资源连接,但老版本中会有内存泄漏的问题,保险起见,把代码都修改一遍,手动关闭连接
结果还是无效

第4次
怀疑目标:phpredis 这个客户端库
做 A/B 测试,替换回 predis 这个库,部署到数据中心中 20% 的用户量上
得益于良好的代码结构,替换工作很快完成
可结果依旧是无效,但也有好的一面,可以证明 phpredis 没问题嘛

第5次
查看了一下 Redis 的版本,是 v2.6,当时最新版本是 v2.8.9
升级 Redis 试一下吧,升完后还是不行
没事儿,要保持乐观,这不顺便把 Redis 版本升为最新的了

第6次
通过查找大量文档,在官方文档中发现了一个调试好方法 Redis Software Watchdog,打开后执行:

$ redis-cli --latency -p 6380 -h 1.2.3.4
min: 0, max: 463, avg: 2.03 (19443 samples)

查看 Redis 日志:

...
[20398] 22 May 09:20:55.351 * 10000 changes in 60 seconds. Saving...
[20398] 22 May 09:20:55.759 * Background saving started by pid 41941
[41941] 22 May 09:22:48.197 * DB saved on disk
[20398] 22 May 09:22:49.321 * Background saving terminated with success
[20398] 22 May 09:25:23.299 * 10000 changes in 60 seconds. Saving...
[20398] 22 May 09:25:23.644 * Background saving started by pid 42027
...

发现了问题:
每隔几分钟就向硬盘保存一次数据,fork 一个后台存储进行为什么需要大概 400ms(通过上面日志的第1条和第2条的时间可以看出来)

到这儿,终于找到问题的根源了,因为 Redis 实例中有大量的数据,导致每次持久化操作 fork 后台进程时非常耗时,并且在他们的业务中经常修改key,又导致了频繁触发持久化,也就经常产生对 Redis 的阻塞

处理办法:使用单独的 slave 来做持久化

这个 slave 不处理真实的流量请求,唯一的作用就是处理持久化,把之前 Redis 实例上的持久化操作转移到这个 slave 上

效果非常明显,问题基本解决,但有的时候还是会报错

第7次
排查可能阻塞 Redis 的慢查询,发现有地方使用了 keys *

因为 Redis 中的数据越来越多,这个命令自然会产生严重阻塞

可以使用 scan 进行替换

第8次
经过前面的调整,问题已经解决,随后的几个月,即使流量在不断增长,也都抗住了

但他们意识到了新的问题:

现在的方式是,来一个请求就创建一个 Redis 连接,执行几个命令,然后再断开连接,在请求量很大时,这个方式产生了严重的性能浪费,一半以上的命令是用来处理连接操作的,这都超过了业务逻辑上的处理,也使 Redis 变慢

解决方法:引入 proxy,他们选择了 twitter 的 twemproxy,只需要在每个 webserver 上安装代理,twemproxy负责与 Redis 实例进行持久连接,这样就大大减少了连接方面的操作

twemproxy还有两个方便的地方:

支持 memcached
可以阻止非常耗时或者危险的命令,例如 keys、flushall
效果自然很完美,再也不用担心之前的连接错误

第9次
通过数据分片来继续优化:

对不同上下文的数据拆分隔离
对相同上下文的数据进行一致性哈希分片
效果:

减少了每台机器上的请求、负载
提升了缓存的可靠性,不担心节点故障

小结
原文作者写的非常好,详细的描述了他们在 Redis 应用上的成长历程,是很值得参考的实践经验
原文地址http://tech.trivago.com/2017/01/25/learn-redis-the-hard-way-in-production

PHP 相关文章推荐
php 清除网页病毒的方法
Dec 05 PHP
php google或baidu分页代码
Nov 26 PHP
献给php初学者(入门学习经验谈)
Oct 12 PHP
php5.3 注意事项说明
Jul 01 PHP
PHP对表单提交特殊字符的过滤和处理方法汇总
Feb 18 PHP
php分页函数完整实例代码
Sep 22 PHP
PHP微信开发之根据用户回复关键词\位置返回附近信息
Jun 24 PHP
PHP 5.6.11中CURL模块问题的解决方法
Aug 08 PHP
PHP排序算法之直接插入排序(Straight Insertion Sort)实例分析
Apr 20 PHP
PHP分页显示的方法分析【附PHP通用分页类】
May 10 PHP
ThinkPHP 5.x远程命令执行漏洞复现
Sep 23 PHP
php设计模式之享元模式分析【星际争霸游戏案例】
Mar 23 PHP
php实现给二维数组中所有一维数组添加值的方法
Feb 04 #PHP
PHP进制转换实例分析(2,8,16,36,64进制至10进制相互转换)
Feb 04 #PHP
php加密之discuz内容经典加密方式实例详解
Feb 04 #PHP
yii2实现 &quot;上一篇,下一篇&quot; 功能的代码实例
Feb 04 #PHP
PHP正则表达式匹配替换与分割功能实例浅析
Feb 04 #PHP
/etc/php-fpm.d/www.conf 配置注意事项
Feb 04 #PHP
PHP正则替换函数preg_replace()报错:Notice Use of undefined constant的解决方法分析
Feb 04 #PHP
You might like
比特率,大家看看这个就不用收音机音质去比MP3音质了
2021/03/01 无线电
How do I change MySQL timezone?
2008/03/26 PHP
Linux下将excel数据导入到mssql数据库中的方法
2010/02/08 PHP
PHP实现根据设备类型自动跳转相应页面的方法
2014/07/24 PHP
twig模板获取全局变量的方法
2016/02/05 PHP
Laravel中的Auth模块详解
2017/08/17 PHP
Maps Javascript
2007/01/22 Javascript
node.js中的buffer.Buffer.isEncoding方法使用说明
2014/12/14 Javascript
DOM 事件流详解
2015/01/20 Javascript
基于Bootstrap使用jQuery实现输入框组input-group的添加与删除
2016/05/03 Javascript
JavaScript基于原型链的继承
2016/06/22 Javascript
jQuery实现鼠标滚动图片延迟加载效果附源码下载
2016/06/28 Javascript
Vue.js创建Calendar日历效果
2016/11/03 Javascript
jQuery中的on与bind绑定事件区别实例详解
2017/02/28 Javascript
微信小程序中吸底按钮适配iPhone X方案
2017/11/29 Javascript
JS声明对象时属性名加引号与不加引号的问题及解决方法
2018/02/16 Javascript
微信小程序使用template标签实现五星评分功能
2018/11/03 Javascript
jQuery动态操作表单示例【基于table表格】
2018/12/06 jQuery
[04:44]DOTA2西游记战队视频彩蛋流出 师徒开黑巧遇林书豪
2016/08/03 DOTA
如何准确判断请求是搜索引擎爬虫(蜘蛛)发出的请求
2015/10/13 Python
django解决跨域请求的问题详解
2019/01/20 Python
python发送多人邮件没有展示收件人问题的解决方法
2019/06/21 Python
python中eval与int的区别浅析
2019/08/11 Python
浅析pandas 数据结构中的DataFrame
2019/10/12 Python
将python安装信息加入注册表的示例
2019/11/20 Python
python实现在一个画布上画多个子图
2020/01/19 Python
Python就将所有的英文单词首字母变成大写
2021/02/12 Python
Sam’s Club山姆会员商店:沃尔玛旗下高端会员制商店
2017/01/16 全球购物
俄罗斯小米家用电器、电子产品和智能家居商店:Poood.ru
2020/04/03 全球购物
学生拾金不昧表扬信
2014/01/21 职场文书
小学新教师培训方案
2014/02/03 职场文书
班子个人四风问题整改措施
2014/10/04 职场文书
宝宝满月祝酒词
2015/08/10 职场文书
新员工入职感言范文!
2019/07/04 职场文书
2019年度政务公开考核工作总结模板
2019/11/11 职场文书
GTX1660显卡搭配显示器推荐
2022/04/19 数码科技