解决mysql产生的大量time_wait以及其他

最近由于网站在大量访问后偶尔遇到数据库连接失败的情况,为了解决这个问题,做了一些分析。然后逐步挖掘,获得了一些有意思的东西。记录一下。

网站访问量大,在某些时刻提示数据库连接失败。但从后端看数据库状态一切正常,当前连接数也远小于最大连接数。

在日志中发现以下提示:

SQLSTATE[HY000] [2002] Cannot assign requested address

使用netstat 查看,发现大量到mysql的连接处于 TIME_WAIT 状态。

netstat -anlpt | grep 3306 |grep TIME_WAIT

按道理说,php使用pdo连接数据库后很快就完成了操作,并释放了连接。为什么还会有这么多等待呢。

后面发现,虽然pdo执行完操作,然后php页面也结束后,资源应该也释放了。这体现在mysql中的当前实际连接上是对的,页面执行完成后,当前实际连接会减少。但是该端口监听并不会马上断开,和mysql的 wait_timeout参数有关。而默认的wait_timeout 是28800,8小时。太长了。根据实际需要将 wait_timeout 调整至100秒足够业务使用。

这是第一步,减少了TIME_WAIT 的回收时间。

另外,网上提到,如果确实产生大量的TIME_WAIT,可以修改系统参数,启用端口重用。

修改 /etc/sysctl.conf  
net.ipv4.ip_local_port_range = 10000     61000   
net.ipv4.tcp_tw_recycle=1
net.ipv4.tcp_tw_reuse = 1

第一行增大本地端口可用范围,后面两行启用端口重用。sysctl -p 使修改生效。`

这样改后,确实效果明显,TIME_WAIT一下子少了很多。

不过这里有一个巨坑。真的是巨坑。网上几乎很少提及这个问题。那就是在nat网络环境下,如果使用了这个设置,会导致nat网络下无法访问该服务器。
看了几十篇文章,只有一篇提到了这个。 https://www.cnblogs.com/billyxp/p/3683559.html

我也遇到了这样的问题,修改生效后。公司内网的同事由于在一个网段内,都无法访问网站了,但是外面其他网络没有任何问题,手机也能正常访问。

于是将以下参数改回,然后内网访问恢复正常。

net.ipv4.tcp_tw_recycle=0
net.ipv4.tcp_tw_reuse = 0

这似乎又回到了原点。还是会有大量的TIME_WAIT产生,只是说给了更多的可用端口范围,和更快的回收时间而已。

思来想去,还是只有从根源上解决问题。

观察php连接Mysql的代码发现,代码都是使用短连接来完成,用完后系统自动回收资源。由于访问量巨大,所以产生了很多连接。

修改连接代码使用长连接连接Mysql,本次使用完毕后,下次连接数据库时该连接可以重用,避免建立新的连接。修改后观察,随着原来临时连接达到timeout时限,time_wait的情况越来越少,后面几乎没有了。恢复正常。目前只有由php-fpm创建的长连接稳定保持在一定数据,当然这和配置的php-fpm的线程数有关系。

自此,该问题基本解决。最终,还是要把代码写好才行啊,不然再好的硬件配置都是枉然。

解决掉这个,然后顺手看了下redis,似乎也存在同样的问题。

按照同样的思路,将redis改成长连接,不过似乎没有什么效果。不知道是不是我的phpredis版本问题。由于切换这个有可能会影响系统稳定性,暂时未作进一步挖掘。目前redis的TIME_WAIT只有几百个,还属于可接受范围,后续再做处理。

在这个过程中,发现了一个新的东西。用unix socket连接redis比用ip地址连接更快。由于redis本来就放在本机,所以用unix socket也是没什么问题的。立即做了一个简单测试。

redis-normal.php
$start_time = microtime(1);
$redis = new Redis();
$redis->connect('127.0.0.1');
for($i=1;$i<10000;$i++){
     $list_len = $redis->llen("visit_list");
     $data = $redis->lrange("visit_list",0,$list_len);
}
$redis->close();
echo microtime(1) - $start_time ;
0.69s
redis-socket.php
$start_time = microtime(1);
$redis = new Redis();
$redis->connect('/var/myredis.sock');
for($i=1;$i<10000;$i++){
     $list_len = $redis->llen("visit_list");
     $data = $redis->lrange("visit_list",0,$list_len);
}
$redis->close();
echo microtime(1) - $start_time ;
0.38s

使用socket连接的速度是完胜使用ip连接的,速度几乎快了一倍。

如果把redis的connect放在循环内,进行一万次的连接和关闭。也是socket方式更快,也是几乎快了一倍。不过整体会消耗更多的时间。

所以,socket连接看来确实比ip连接优秀不少,这在本机redis环境下很实用。

另外,顺手看了些关于unix socket的资料,对一些细节更了解了一些。本次查资料还涉及到了使用tcpdump,以及tcp的三次握手,四次再见等等,发现抽丝剥茧的感觉很爽,不过要花很多时间去一步步深入。

以下是一些参考:

What's the difference between Unix socket and TCP/IP socket?

A UNIX socket is an inter-process communication mechanism that allows bidirectional data exchange between processes running on the same machine.

IP sockets (especially TCP/IP sockets) are a mechanism allowing communication between processes over the network. In some cases, you can use TCP/IP sockets to talk with processes running on the same computer (by using the loopback interface).

UNIX domain sockets know that they’re executing on the same system, so they can avoid some checks and operations (like routing); which makes them faster and lighter than IP sockets. So if you plan to communicate with processes on the same host, this is a better option than IP sockets.

Edit: As per Nils Toedtmann's comment: UNIX domain sockets are subject to file system permissions, while TCP sockets can be controlled only on the packet filter level.

Windows 10 has support for Unix sockets. There are some limitations, but it's available: blogs.msdn.microsoft.com/commandline/2017/12/19/…Tyson Jul 30 '18 at 2:45

Unix Socket Tutorial

https://www.tutorialspoint.com/unix_sockets/index.htm

简单的tcpdump教程

https://danielmiessler.com/study/tcpdump/#protocol

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,997评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,603评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,359评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,309评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,346评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,258评论 1 300
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,122评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,970评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,403评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,596评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,769评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,464评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,075评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,705评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,848评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,831评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,678评论 2 354

推荐阅读更多精彩内容