背景
大促备战,最大的隐患项之一就是慢sql,带来的破坏性最大,也是日常工作中常常带来整个利用抖动的最大隐患,而且对sql好坏的评估有肯定的技术要求,有一些缺乏经验或者因为不够认真造成一个坏的sql胜利走到了线上,等发现的时候要么是造成了线上影响、报警、或者后置的慢sql采集发现,这时候个别无奈疾速止损,须要批改代码上线、或者调整数据库索引。
外围痛点:
1、无奈提前发现慢sql,可能好转为慢sql的语句
2、线上呈现慢sql后,无奈疾速止损
解决思路
1、把问题解决在上线之前,最好的方法就是在测试阶段,甚至在开发阶段就发现一个sql的好坏
2、线上发现慢sql后除了改代码上线、调整数据库表索引的形式外,反对热更新的形式替换sql语句。
部门外部,目前大部分数据库框架采纳的mybatis,而后基于mybatis自身的实现机制中,开发一个mybatis组件,能够主动对运行的sql进行提取和剖析,定制一套默认的剖析规定,让sql在开发环境和测试环境执行的时候,就可能做初步的评估,把有问题的慢sql在这个阶段裸露进去;同时具备sql替换性能,在线上呈现问题sql的时候,能够通过ducc配置疾速实现对一个sql的在线替换,大大降低线上问题的止损工夫。
开源计划调研
目前,支流的sql剖析组件,外围性能次要放在了两个方向:1、慢sql的剖析和优化倡议 2、sql的优化重写性能,而且次要偏运维的辅助性能无奈做到无侵入的和利用代码进行集成。也就无奈实现咱们的外围痛点,慢sql提前剖析预警和动静sql替换。
[]()
设计方案
外围性能:SQL剖析预警能力、SQL替换能力
[]()
具体设计
次要分为8个功能模块
模块一:core 次要负责组件的接入到mybatis,以及其它模块的编排调用
模块二:config 次要负责组件配置信息的初始化
模块三:extrat 次要通过解析mybatis 相干对象,提取残缺的待执行sql
模块四:analysis 次要拼接剖析语句,执行explain剖析语句并获取剖析后果
模块五:rule sql剖析规定的加载和初始化,反对自定义规定
目前默认规定(继续扩大):
1、查问未匹配索引
2、匹配索引过滤成果较差
3、返回行数过多
4、应用了文件排序
模块六:score 基于剖析后果和配置的评分规定进行匹配打分,优化倡议组装
模块七:out 输出模块,对于输入后果进行输入,目前已error日志、MQ两种输入形式
模块八:replace替换模块,能够对sql语句基于ducc配置进行动静替换
应用办法
1、引入依赖jar包
<dependency> <groupId>com.jd.sql.analysis</groupId> <artifactId>sql-analysis</artifactId> <version>1.2-SNAPSHOT</version></dependency>
2、配置组件xml
<configuration> <plugins> <plugin interceptor="com.jd.sql.analysis.core.SqlAnalysisAspect" > <!-- 开启sql剖析性能最简配置 --> <property name="analysisSwitch" value="true"/> <!-- 开启sql替换性能最简配置 --> <property name="sqlReplaceModelSwitch" value="true"/> <property name="duccAppName" value="workbench-backend"/> <property name="duccUri" value="ucc://workbench-backend:2d6991cb865f4e6bac6c3e1cf7794cdf@test.ducc.jd.local/v1/namespace/workbench_backend/config/default/profiles/test?longPolling=60000&necessary=false"/> <property name="duccMonitorKey" value="refundBugFlag"/> </plugin> </plugins></configuration>
3、外围配置项
属性 | 用处 | 是否必填 | 默认值 | 备注 |
---|---|---|---|---|
analysisSwitch | 是否开启剖析性能 | 是 | false | |
onlyCheckOnce | 是否对一个sqlid只剖析一次 | 非 | true | |
checkInterval | 每个sqlid剖析距离 | 非 | 300000毫秒 | onlyCheckOnce 为false才失效 |
exceptSqlIds | 须要过滤不剖析的sqlid | 非 | ||
sqlType | 剖析的sql类型 | 非 | 默认select、update | 反对 |
scoreRuleLoadClass | 评分规定加载器,用于扩大自定义规定 | 非 | ||
outModel | 默认输入形式 | 非 | 默认值:LOG | 反对LOG、MQ两种形式 |
outputClass | 评分后果输入类,用于扩大自定义后果输入形式 | 非 | ||
sqlReplaceModelSwitch | sql替换模块是否开启 | 非 | 默认 false | |
duccAppName | ducc配置的利用名称(jdos) | 非 | ||
duccUri | ducc uri配置 | 非 | ||
duccMonitorKey | sql替换配置文件对应的key | 非 |
4、默认剖析成果展现
4.1、慢sql剖析成果
[]()
4.2、sql动静替换成果
5、实际应用计划
5.1、慢sql剖析-日志输入+关键词告警
<configuration> <plugins> <plugin interceptor="com.jd.sql.analysis.core.SqlAnalysisAspect" > <property name="analysisSwitch" value="true"/> </plugin> </plugins></configuration>
5.2、慢sql剖析-日志输入+mq输入+es存储+Kibana剖析
<configuration> <plugins> <plugin interceptor="com.jd.sql.analysis.core.SqlAnalysisAspect" > <property name="appName" value="workbench-backend"/> <property name="analysisSwitch" value="true"/> <property name="outputModel" value="mq"/> <property name="mqApp" value="qlstation"/> <property name="mqUser" value="qlstation"/> <property name="mqPassword" value="D1BCC547"/> <property name="mqAddress" value="jmq-testcluster.jd.local:50088"/> <property name="mqTopic" value="jdl_kds_key_node_log"/> </plugin> </plugins></configuration>
最终成果
[]()
5.3、慢sql替换-ducc配置动静更新sql语句
<configuration> <plugins> <plugin interceptor="com.jd.sql.analysis.core.SqlAnalysisAspect" > <property name="sqlReplaceModelSwitch" value="true"/> <property name="duccAppName" value="workbench-backend"/> <property name="duccUri" value="ucc://workbench-backend:2d6991cb865f4e6bac6c3e1cf7794cdf@test.ducc.jd.local/v1/namespace/workbench_backend/config/default/profiles/test?longPolling=60000&necessary=false"/> <property name="duccMonitorKey" value="sqlReplaceConfig"/> </plugin> </plugins></configuration>
发现慢sql
[]()
ducc配置
[]()
线上sql被动静替换
[]()
留神:性能正式修复后,需去掉该配置,该性能仅供给急解决线上问题,不倡议作为性能长期应用
性能测试
测试环境千次一般sql查问,每种场景进行了5次测试
未启用插件耗时:11108ms,10237ms,9482ms,7938ms,8196ms
开启sql剖析耗时:16619ms,17333ms,16321ms,19057ms,18164ms
理论配置,只有首次执行或者间隔时间执行,单次影响10ms左右)
开启sql替换耗时:10642ms,8803ms,8353ms,8830ms,9170ms
根本无影响
实用场景
1、慢sql预防
2、线上问题止损
劣势
1、外围劣势:执行时剖析sql,区别于传统的依赖sql执行耗时来评估慢sql,间接基于语法和索引进行前置剖析,不仅能预防某些坏sql在上线后发现是慢sql,还能给出sql优化倡议,能够大限度的防止线上产生慢sql。反对动静对线上sql进行替换,能够对线上问题疾速止损。
2、性能:基于性能和不同的应用场景思考,反对定制化配置,每个sql是否仅进行一次查看、或者按某个工夫距离进行配置。sql替换简直无损耗。
3、扩大:基于后续sql评分规定的扩大、以及剖析后果以不同的形式输入的思考,反对评分规定、输入形式的自定义扩大。
4、老本:接入成本低,无代码侵入。
作者:京东物流 扈海涛
起源:京东云开发者社区