【MySQL】 如何在“海啸”下保命

作者:田杰
在数据库的日常使用中,来自应用的高并发场景并不罕见,其标志性的表现为 高新连接创建速率(CPS,比如 PHP 短连接)、发送大量请求到 DB 数据库层。

如同 海啸,大量的新建连接和请求猛烈的冲击考验着 DB 层的处理能力,非常容易出现数据库被冲击 hang 住或响应极其缓慢的情况(想象下无预知无缓冲的短时间内突然工作量翻涨数倍,会不会立时被忙哭了 ^_^)。
而数据库通常作为架构最下端的数据存取汇聚单元,其性能表现和稳定性往往决定了应用的最终表现和使用体验,可谓业务生死之大事,不可不察。
由此,我们一起看一下 “海啸” 场景下可以用来 “保命” 的各种解决方案。
注:
• 本文目标是总结高并发场景下的应对处理方法,而应对热点更新(秒杀)场景的“招数”会另文介绍。
• 本文的主旨在于方便数据库的使用者理解业务高并发请求场景下的保障 DB 可用性和稳定性的机制和方法,非机制的全面深度技术细节介绍。

1. 线程池

1.1 模型

image.png
我们举一个生活中的例子方便大家理解 线程池(Thread Pool)。
比如有个银行,有 10 个窗口(实例规格 CPU 数量),官方说可以容纳 10 人(Client Thread)。平时呢,人也不多,一直顺畅。稍微忙一点呢,大家挤挤。这个 10 人的地方,挤个 50 人也可以(不是每个人时刻都在窗口办业务)。效率也挺高。
年底发工资、公司结算、发行纪念币来了一大帮人,大家一起挤,谁也不让,就把银行挤满了;大家接踵摩肩,动也动不了,再发生些争抢,那这银行谁也办不了业务了。
好了,来个保安(Timer Thread),搞了个队伍机制(10 个队列 loose_thread_pool_size = 10),按规定执行,一次放 10 个人。这个效率也不错。
当然了,如果一下子来了 1000 个人,那么门口等待的队伍会很长,虽然不致于把银行撑爆,但是后面的同学要等很长时间,有的会去抱怨了(应用侧等待超过自身定义的超时时间后返回错误)。
问题来了,有的同学搞不清楚买哪种纪念币,一直在看看停停,保安看他们也不像马上能决定的样子,而且窗口柜员也不是非常忙,保安就又搞了个规则,叫 “stall_limit”。
看一些同学犹豫超过 stall_limit 定义的时间,那么就算他们 stall 了,可以再放 1 个人进去(oversubscribing)。但去窗口办业务的人数是有上限的,最多 50 个人(10 个窗口每个窗口 5 个人, loose_thread_pool_oversubscribe = 4)。
之后,只能出一个,进一个; 如果都不出来,那也 hang 了。这个时候,至少要让保安能进去,把这些太慢的同学赶出来几个,让等待的队列动起来。
还有,有的同学在里面发现忘带证件了,需要等送进来。他们找地方等(lock wait)。那么他们是在等待了,这个是不算 oversubscribing 数量的,所以保安也可以放人,一直放到 thread_pool_max_threads 个人。
如果证件还没送来,那么银行就被这些等证件的霸占了(hang 了)。另外如果一下子证件都送来,那这个银行一下子忙起来,也爆了(热点更新)。
当然如果这个银行没有大量客户同时办业务的场景,是可以不需要搞个保安,不需要搞个队伍的(loose_thread_pool_enabled = OFF)。这个银行本身最多可以 50 个人,但是保安只让 10 个人进去,那效率就会低了。
还有,门口等待队伍长了,这个可以有 3 种可能,
• 顾客动作慢(慢 SQL),建议考虑优化 SQL 降低执行成本。
• 银行小, 窗口数量少(实例规格小)建议扩店(升级实例规格)。
• 窗口动作慢(物理机问题、数据库 bug;不在本文讨论范围内)。
从上面的例子中,我们可以看到 Thread Pool 是通过队列机制限制数据库的 Client Thread 的并发度(控制 Running Thread 数量),避免大量的争抢和创建 Client Thread 的开销来提升 CPU 使用 效率,保障吞吐的(在应用给与 DB 的访问压力不断增加的情况下,保持 DB 吞吐处理能力)。

1.2 适用场景

如果我们仔细品位下上面的例子,可以发现 Thread Pool 的适用场景:
• 每个要办的业务简短(OLTP 场景)且性能瓶颈在 CPU 资源上
• 场景中不存在 大量 需要长时间执行且无停顿(可以暂时不使用 CPU)的 SQL
• 能够接受一定损失(错误/开销)的业务(启用 Thread Pool 后需要一定开销,存在简单的查询比不启用 Thread Pool 的情况下执行时间增加的可能,比如被分配到了 stall 的 thread group 而要花时间等待执行)

1.3 小结

参数开放修改?默认值说明
1loose_thread_pool_enabledYes是否启用 Thread Pool
2loose_thread_pool_oversubscribeYes每个 Thread Group 在出现 Stall Thread 的情况下可以额外同时执行(active)的线程个数;线程池最多可以同时执行(active)的线程数 =(thread_pool_oversubscribe + 1)* thread_pool_size;建议 >=3
3tloose_thread_pool_sizeYes (RDS)Thread Pool 中分组(Thread Group)的个数,建议设置为实例规格 CPU 个数
4thread_pool_max_threadsNoThread Pool 中最大线程数量,到达这个数量后,无法再创建新的 thread
5thread_pool_idle_timeoutNoThread Group 中空闲的线程退出前的空闲等待(idle)时间
6thread_pool_stall_limitNoTimer Thread 检查 “Stall” 情况的间隔,避免一个 thread 长时间霸占一个 thread group

那么面对存在长时间执行的查询,除了优化 SQL 降低执行成本外(有时不具有可操作性,当然如果该查询对数据时效性不敏感可以考虑转移到只读实例上执行),是否还有其他招数可用? 请看下一招“限流”。

2. 限流

如果“海啸”来的异常猛烈,并且在“海啸”中能够定义出一批带有同样特征的查询,比如 Redis 缓存被击穿,大量相似重复查询打到 DB 层,或者如上例 Thread Pool 中的长时间执行的查询,那么在业务支持/允许降级的情况下我们可以通过对这批请求采取限流的方式来“保命”。
相对 thread pool 这种对“海啸” 全方位覆盖的应对机制,限流更像是集力量于一点的定向打击。

2.1 Statement Concurrency Control

对于 RDS for MySQL 8.0 和 PolarDB for MySQL,我们可以通过“语句并发控制”(Statement Concurrency Control)特性来实现针对指定语句的限流。
比如发现下面的查询在高并发的场景下拖累了整个实例的性能,和业务核实,业务可以接受该查询被限流。

# 高成本慢查询
select count(*)
from jacky.mytab
where cid = 90363
or uid = ???

Copy
确定 SQL 语句后,可以根据语句特征来调用 dbms_ccl 工具包创建规则进行限流。

# 增加限流规则,限制最多 1 个并发执行
call dbms_ccl.add_ccl_rule('select','jacky','mytab',1,'cid=;uid=');
# 显示当前的限流规则
call dbms_ccl.show_ccl_rule();
+------+--------+--------+-------+-------+-------+-------------------+---------+---------+----------+-----------+
| ID   | TYPE   | SCHEMA | TABLE | STATE | ORDER | CONCURRENCY_COUNT | MATCHED | RUNNING | WAITTING | KEYWORDS  |
+------+--------+--------+-------+-------+-------+-------------------+---------+---------+----------+-----------+
|    2 | SELECT | jacky  | mytab | Y     | N     |                 1 |     116 |       1 |       26 | cid=;uid= |
+------+--------+--------+-------+-------+-------+-------------------+---------+---------+----------+-----------+

Copy
限流规则添加后,超过定义的并发度的 SQL 请求在 "Concurrency control waiting" 状态
image.png
限流前后对比,可以看到限流后 CPU 使用率从 100% 降低到 50% 左右,有效恢复业务可用性。
image.png

2.2 DAS 限流

对于 RDS for MySQL 5.6 和 5.7 ,控制台的 CloudDBA 功能直接集成了 SQL 限流功能。
image.png
我们来看一个真实生活中的例子,某客户在业务高峰期出现大量的集中请求,导致高配实例 CPU 完全打满,由于实例响应极其缓慢,能采集到的监控数据显示当时 活动会话达到 14700+ 。
在业务层反复调整无法恢复的情况下 在 2020.3.24 21:35 通过设置 SQL 限流恢复了业务可用性。
image.png
RDS 实例会话情况
image.png
RDS 实例 CPU 使用率情况
image.png

3. 御敌于外

上面介绍的都是数据库层面的应对之策,那么是否我们一定要被动的在数据库层面“兵来将挡”呢?有没有主动“御敌于外”的办法呢?

3.1 名词解释

名称说明
1短连接通信双方有数据交互时,就建立一个 TCP 连接,数据发送完成后,则断开此 TCP 连接;通常基于 PHP 语言的应用采用短连接方式访问数据库
2长连接通信双方有数据交互时,首先尝试复用已有空闲 TCP 连接,如果没有空闲 TCP 连接则尝试创建新连接;数据发送完成后,通常不断开此 TCP 连接以便后续复用;通常基于 Java 语言的应用采用长连接方式访问数据库
3syn queue用于存储接收到的 syn 请求的连接 socket 队列,TCP 协议栈接收到 syn 后系统内核自动回复 syn,ack 同时将 syn 代表的连接放入到 syn queue 队列中,并管理是否需要重传 syn,ack;其长度由 tcp_max_syn_backlog (或 somaxconn)Linux 内核参数确定
4accept queue用于存储完成 TCP 三次握手的连接 socket 队列,当 MySQL 调用 accept() 时从该队列取走一个 socket 处理,其长度由 应用设置的 backlog 参数和内核参数 somaxconn 的较小值决定
5ListenOverFlow由于 syn queue 已经打满,新收到的 syn 请求不被处理而丢弃的场景发生数量
6ListenDrops由于 accept queue 已经打满,完成 TCP 三次握手的连接不被处理而丢弃的场景发生数量

3.2 短连接优化

首先我们来看看一个普通的 SQL 请求是如何被从应用通过网络发送给 DB 层进而得到处理的。
image.png
仔细看一下上述时序图,就会发现如果应用和数据库之间在没有可用的网络连接情况下,需要首先建立起一条基于 TCP/IP 协议栈的 MySQL 网络连接才能够将 SQL 请求发送给数据库实例并获取到处理的结果集。
在应用采用短连接机制(比如基于 PHP 语言开发的应用)的情况下,每个 SQL/Query 都需要和数据库实例创建一个 TCP 网络连接,需要消耗数据库实例(和其所在物理机)的 CPU 资源。
在“海啸”的场景下,采用短连接机制的应用会保持很高的新连接创建速率(CPS,大于等于 QPS),这样在高负载(QPS) 的基础上进一步消耗数据库实例的 CPU 资源,拉高 CPU 使用率,降低 CPU 使用效率,进入恶性循环容易触发数据库雪崩式崩溃。
在 CPU 资源紧张的情况下会出现大量连接请求积压无法处理而触发 ListenOverFlow 和 ListenDrops 情况出现。
这里我们看一个真实世界中的例子。
客户在 13:30 将应用从长连接模式调整为短连接模式,由于短连接模式的高并发新建连接请求速率(CPS - 每秒新建连接数),修改后实例 CPU 使用率总体上升 25+% 左右,业务侧出现大量连接失败错误并感知 RDS 实例响应缓慢。
image.png
部分 CPU 被完全打满,无法满足处理高连接请求的需求而出现 ListenOverFlow / ListenDrops。
image.png
image.png
线程池 Thread Pool 是数据库层对该场景较好的解决方案,而启用了数据库独立代理(RDS for MySQL 读写分离地址 和 PolarDB for MySQL 的集群地址)的实例还可以选择启用“短连接优化”的链路层解决方案。
image.png
当应用断开连接后,数据库独享代理会判断之前的连接是否为空闲(idle)连接,如果是空闲连接,代理会将代理与数据库之间的连接保留在连接池内一段时间(仅释放应用与代理之间的连接)。
在保留连接的这段时间内如果应用发起新连接,代理会直接从连接池里使用保留的连接,从而减少与数据库建立连接的开销。
官方文档:短连接优化

原文链接
本文为云栖社区原创内容,未经允许不得转载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/516167.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

企业微信H5_自建应用连接H5

文章目录1. 进入自建应用2. 自定义菜单3. 添加主菜单4. 补充信息5. 点击发布6. 登录手机企微7. 点击菜单8. 第2种效果1. 进入自建应用 找到自建的应用 2. 自定义菜单 点击-自定义菜单-已启用 3. 添加主菜单 点击-添加主菜单 4. 补充信息 补充信息-点击保存 主菜单&a…

【MySQL】时区设置引发的卡顿

作者:田杰 查询执行时间长引发应用感知 “卡顿” 的场景在数据库的日常支持和使用中并不少见,但由于时区设置引发的 SQL 执行“卡顿”仍然是一个有趣的现象,之前没有具体关注过。 这次客户的细致与坚持让我们找到了问题的源头。 1. 名词解释…

老码农90%的程序猿都是瞎努力,这份路线教你成为高手!

数据正在变得越来越常见,小到我们每个人的社交网络、消费信息、运动轨迹……,大到企业的销售、运营数据,产品的生产数据,交通网络数据……如何从海量数据中获得别人看不见的知识,如何利用数据来武装营销工作、优化产品…

企业微信_H5应用如何本地及真机调试_host配置及代理相关

文章目录一、准备工作1. 下载SwitchHosts2. 创建vue项目3. 启动项目3. 请求验证4. 域名访问5. Invalid Host header二、电脑调试2.1. 设置应用主页2.2. PC企微登录2.3. PC企微应用2.4. 更新验证2.5. 跳转页面三、手机调试3.1. 代理软件3.2. 安装,启动3.3. 连接无线网…

揭秘MySQL生态重要功能,X-Engine引擎核心能力——OnlineDDL

概述 X-Engine是阿里自研的数据库存储引擎,以插件的方式接入到MySQL生态,支持行锁,事务,MVCC等OLTP场景的核心功能。 X-Engine的核心优势是低成本,高性价比,尤其适用于历史库场景,目前阿里巴巴…

企业微信_获取access_token

文章目录一、快速入门1. 开发文档2. 管控台3. 接口文档4. 参数获取5. api调试二、java实战2.1. 入口2.2. 核心方法2.3. 核心配置2.3. RestUtils 工具类2.5. token缓存策略三、源码分享3.1. 后端源码3.2. 前端源码一、快速入门 1. 开发文档 企业内部开发文档: http…

荷兰政府用大数据预测天气预防自然灾害,他们是怎么做的?

作者 | 乔治娜乌斯蒂克翻译 | Katie责编 | 晋兆雨头图 | CSDN付费下载于视觉中国你是否对天气预报电视报道的背后的运作感到好奇?是谁在管理政府卫星?也许你会思考关于传感器的一个问题——数据会流向何处? 在荷兰,这些数据是由KN…

Excel VBA Sql 操作Access数据库

目录 1. 文件创建2. 数据库连接2.1 前期和后期绑定2.2 通过判断 Excel 的不同版本,给出不同的连接字符串2.3 Excel 自连接3. 应用:增、删、改3.1 增加数据的语法3.2 删除数据的语法3.3 修改数据的语法4. 结语1. 文件创建 首先,我们需要在预先设置的路径下新建Excel工作簿。…

企业微信小程序_小程序开发工具及真机调试_host配置及代理

文章目录一、开发前准备1. 开发文档2. 工具安装3. 安装插件4. 调整编译模式5. 选择企业6. PC 调试前端7. PC 调试后端二、甄姬调试前端2.1. 预览小程序2.2. 手机企微扫码2.3. 手机企微调试2.4. 多场景调试2.5. 手机企微调试前后端一、开发前准备 1. 开发文档 小程序开发文档&…

别再盲目学Python了!

如果你想问最近这些年什么编程语言最值得学习,我会毫不犹豫的告诉你是Python。无论是刚入门的程序员,还是年薪BATJ的技术大牛,都无可否认现在Python对于一个程序员职业发展的重要性。所以不仅是开发小白,甚至很多开发老手&#xf…

VBA 网页提取特定内容 - 网抓实践总结

目录 前言1. 常用代码和自定义函数1.1 文本 to 剪贴板1.2 获取网页主体源代码1.2.1 方法一:`InternetExplorer.Application`1.2.2 方法二:`MSXML2.XMLHTTP`1.2.3 方法三:`Msxml2.ServerXMLHTTP`1.2.4 方法四:WinHttp.WinHttpRequest.5.11.2.5 方法五:Microsoft.XMLHTTP1.3…

企业微信_Windows版本调试

文章目录1. 调试文档2. 下载插件3. 插件放置4. 开启调试模式5. 效果图6. 关闭调试模式1. 调试文档 客户端调试文档: https://developer.work.weixin.qq.com/document/path/95384 2. 下载插件 3. 插件放置 把 devtools_resources.pak 放到企业微信的安装目录下&am…

如果千百年前有视觉AI算法,世界将会是什么样的光景呢?

视觉AI算法在近些年取得了一定的突破,被应用在了越来越多的地方,我相信距离真正的AI普及这个大目标也越来越近了。我时常在想假如古代也有视觉AI算法,那是不是很多故事的结局都将被改写?《伯乐相马》、《皇帝批红》、《木兰从军》…

困境实现飞跃,梦想照进现实《安防视频监控数据存储蓝皮书》发布

前言 近年来,随着云计算、5G、AI 技术的不断兴起与发展,安防行业正在发生数字化转型,作为安防行业重要的数据采集与管理中枢,视频监控设备在数量上不断增加,在科技强有力的支撑之下,庞大的图片、视频数据组…

企业微信小程序_获取准确定位的方法及解决定位不准确的问题

文章目录一、经验分享1. 微信api现状2. 解决方案3. 适用场景二、小程序集成腾讯定位服务2.1. 注册腾讯开发者2.2. 创建应用2.3. 添加key2.4. 下载sdk2.5. 合法域名三、开发实战3.1. sdk拷贝3.2. 页面引用3.3. 页面部分3.4. 数据部分3.5. 方法部分四、真机调试4.1. 项目运行4.2.…

深度揭秘:腾讯存储技术发展史

采访嘉宾 | 腾讯云副总裁谢明等图源 | 视觉中国来源 | CSDN(ID:CSDNnews)在腾讯内部,负责腾讯存储技术研发的部门,一直被认为是生产技术专家的“黄埔军校”。腾讯不少技术方向的负责人,最早也都出自这个团队。这或许可…

常见字典用法集锦及代码详解

目录前言字典的简介1. 字典对象1.1 Add 方法1.2 Exists 方法1.3 Keys 方法1.4 Items 方法1.5 Remove 方法1.6 RemoveAll 方法2. 实例2.1 实例1. 普通常见的求不重复值问题2.1.1 问题2.1.2 实例代码2.1.3 代码详解2.2 实例2 求多表的不重复值问题2.2.1 问题2.2.2 代码2.2.3 代码…

企业微信小程序_集成腾讯地图实现精准定位考勤打卡

开源项目地址:https://gitee.com/gblfy/tx-position-check-in 关于微信小程序集成腾讯地图详情,可以参考:https://blog.csdn.net/weixin_40816738/article/details/122519497

18个PPT,29个提问解答,都在这儿啦!

4月25-26日,全球首个 Apache 顶级项目在线盛会 Flink Forward 中文精华版重磅开播,聚焦 Alibaba、 Google、AWS、Uber、Netflix、DellEMC、微博、滴滴等各大互联网公司实时计算的经典场景和业务故事,由 Flink 核心贡献者们对 19 个优质 talk …

CSDN公众号新功能上线,居然还能搜出小姐姐???(文末有福利)

为了给各位打工人更好的搜索体验CSDN总是在学习新技能这次CSDN公众号又给大家带来了一项全新的搜索技能在CSDN旗下的公众号内回复消息就能自动回复想搜索的内容啦小编来给大家演示一下,在公众号内输入“mysql安装教程”,就能得到CSDN全站内关于mysql安装…