个人公众号文章:https://mp.weixin.qq.com/s/nyN_QyvQ5M_gjmi4tbkzjQ
个人主页:wang-zhiyang.github.io
引言:众所周知,高并发会打挂mysql,那么mysql是怎么挂的?是io挂?mysql集群挂?还是mysql服务进程挂?还是单纯进程处理变慢?
proxy
对于生产环境,一般不会出现直连db的情况。都是需要走DB代理层。代理有连接池控制,超时控制,熔断控制等。
proxy一般处理流程
- proxy启动后,从后台读取配置,启动监听,监听客户端的连接请求
- 收到客户端连接请求后,启动一个goroutine处理该请求
- 首先进行登录认证,认证通过后转入下面的处理流程,否则给客户端返回错误信息
- 认证通过后,客户端发送sql语句
- proxy解析客户端发送过来的sql语句,proxy对db维护有连接池,选择合适的库,把请求发送到这个库执行
- 接收后端库的返回结果,转发给客户端
当业务qps暴增,mysql的影响
连接数计算
一个连接会被复用,处理完一个sql会放到连接池中。
若单个请求的时间为RT(ms),那么一个连接能扛住的qps是 1000/rt。
QPS暴增
-
首先原先连接处理不完这么多请求,连接数会暴增,直到打满代理配置的上限
-
此时qps继续增大,当连接不够用时,proxy的client会创建连接,直到到达配置的上线。此时qps继续增加,等待一段配置的时间后,就会报常见的连接数不足。
-
此时客户端qps,报错请求数比例占总请求数上升到配置的阈值,将触发熔断机制,之后来的请求将不会请求代理。
影响
由于有proxy client的保护,这样db、proxy都不会有超预期外的压力。这个业务qps暴增也不会影响到其他的业务
多个业务QPS暴增
上面说的是一个业务 或者是clientqps暴增。如果多个client的qps都暴增,导致打proxy的请求也增加,此时proxy会进行排队处理,如果等待时间超过超时时间将超时报错。所以db压力不会异常增长。
影响
由于多个client的业务qps都激增,会影响到使用同一个proxy业务(一般都会有负载均衡)。db依然会被保护,不受影响。
假设业务直连db
从上述可知,proxy对db保护的非常好,如果没有这一层代理,直连db会这么样呢。
-
连接数没有上限,会一直增加
-
没有熔断机制
内存角度:
mysql每一个连接都有自己的一些私有内存区域,包括查询binlog cache、read buffer、sort buffer、join buffer 等,这些内存一旦使用后,在断开连接之前是不会主动释放的。
当db的连接数上来了,内存不足,可能会导致swap[把进程暂时不用的额内存存到磁盘中,并释放这些数据占用的内存,进程再次访问这些内存的时候,从磁盘读取数据到内存
],严重影响性能。最后mysql进程可能会触发OOM-killer机制,OS把消耗内存最多的那个进程kill掉以释放内存。
线程角度:
mysql是单一进程多线程应用,当请求过多时,必然导致线程变多,上下文切换频繁等。整体 SQL 平均响应时间变长,进一步导致running thread变多,导致雪崩效应。
回答
回到原来的问题,由于有代理的保护,qps暴增对db不会有多大影响。业务层面上看到的是数据库超时、连接不够等。如果是直连,qps上来,mysql处理变慢,导致雪崩。mysql进程oom。在集群中这个实例就不可用了。