Tech 导读 针对大促、日常系统稳定性隐患-慢sql的预防和排查,Mybatis-SQL分析组件从一个新的角度发现慢sql,让慢sql止步于发生之前,区别于主流的基于慢sql日志分析和预警,实时根据Explain分析结果进行分析和预警。
01
背景
在今年的敏捷团队建设中,我通过Suite执行器实现了一键自动化单元测试。Juint除了Suite执行器还有哪些执行器呢?由此我的Runner探索之旅开始了!
大促备战,最大的隐患项之一就是慢sql,带来的破坏性最大,也是日常工作中经常带来整个应用抖动的最大隐患,而且对sql好坏的评估有一定的技术要求,有一些缺乏经验或者因为不够仔细造成一个坏的sql成功走到了线上,等发现的时候要么是造成了线上影响、报警、或者后置的慢sql采集发现,这时候一般无法快速止损,需要修改代码上线、或者调整数据库索引。
核心痛点:
1、无法提前发现慢sql,可能恶化为慢sql的语句
2、线上出现慢sql后,无法快速止损
02
理解,首先 MCube 会依据模板缓存状态判断是否需要网络获取最新模板,当获取到模板后进行模板加载,加载阶段会将产物转换为视图树的结构,转换完成后将通过表达式引擎解析表达式并取得正确的值,通过事件解析引擎解析用户自定义事件并完成事件的绑定,完成解析赋值以及事件绑定后进行视图的渲染,最终将目标页面展示到屏幕。
1、把问题解决在上线之前,最好的办法就是在测试阶段,甚至在开发阶段就发现一个sql的好坏
2、线上发现慢sql后除了改代码上线、调整数据库表索引的方式外,支持热更新的方式替换sql语句
部门内部,目前大部分数据库框架采用的mybatis,然后基于mybatis本身的实现机制中,开发一个mybatis组件,可以自动对运行的sql进行提取和分析,定制一套默认的分析规则,让sql在开发环境和测试环境执行的时候,就能够做初步的评估,把有问题的慢sql在这个阶段暴露出来;同时具备sql替换功能,在线上出现问题sql的时候,可以通过ducc配置快速完成对一个sql的在线替换,大大降低线上问题的止损时间。
03
理解,首先 MCube 会依据模板缓存状态判断是否需要网络获取最新模板,当获取到模板后进行模板加载,加载阶段会将产物转换为视图树的结构,转换完成后将通过表达式引擎解析表达式并取得正确的值,通过事件解析引擎解析用户自定义事件并完成事件的绑定,完成解析赋值以及事件绑定后进行视图的渲染,最终将目标页面展示到屏幕。
目前,主流的sql分析组件,核心功能主要放在了两个方向:1、慢sql的分析和优化建议 2、sql的优化重写功能,而且主要偏运维的辅助功能无法做到无侵入的和应用代码进行集成,也就无法解决核心痛点,慢sql提前分析预警和动态sql替换。
图1.主流的sql分析组件功能示意
04
设计方案
理解,首先 MCube 会依据模板缓存状态判断是否需要网络获取最新模板,当获取到模板后进行模板加载,加载阶段会将产物转换为视图树的结构,转换完成后将通过表达式引擎解析表达式并取得正确的值,通过事件解析引擎解析用户自定义事件并完成事件的绑定,完成解析赋值以及事件绑定后进行视图的渲染,最终将目
核心功能:SQL分析预警能力、SQL替换能力
图2.设计方案示意
05
详细设计
理解,首先 MCube 会依据模板缓存状态判断是否需要网络获取最新模板,当获取到模板后进行模板加载,加载阶段会将产物转换为视图树的结构,转换完成后将通过表达式引擎解析表达式并取得正确的值,通过事件解析引擎解析用户自定义事件并完成事件的绑定,完成解析赋值以及事件绑定后进行视图的渲染,最终将目标页面展示到屏幕。
主要分为8个功能模块
模块一:core 主要负责组件的接入到mybatis,以及其它模块的编排调用
模块二:config 主要负责组件配置信息的初始化
模块三:extrat 主要通过解析mybatis 相关对象,提取完整的待执行sql
模块四:analysis 主要拼接分析语句,执行explain分析语句并获取分析结果
模块五:rule sql分析规则的加载和初始化,支持自定义规则
目前默认规则(持续扩展):
1、查询未匹配索引
2、匹配索引过滤效果较差
3、返回行数过多
4、使用了文件排序
模块六:score 基于分析结果和配置的评分规则进行匹配打分,优化建议组装
模块七:out 输出模块,对于输出结果进行输出,目前已error日志、MQ两种输出方式
模块八:replace替换模块,可以对sql语句基于ducc配置进行动态替换
06
使用方法
理解,首先 MCube 会依据模板缓存状态判断是否需要网络获取最新模板,当获取到模板后进行模板加载,加载阶段会将产物转换为视图树的结构,转换完成后将通过表达式引擎解析表达式并取得正确的值,通过事件解析引擎解析用户自定义事件并完成事件的绑定,完成解析赋值以及事件绑定后进行视图的渲染,最终将目标页面展示到屏幕。
6.1 引入依赖jar包
<dependency>
<groupId>com.jd.sql.analysis</groupId>
<artifactId>sql-analysis</artifactId>
<version>1.2-SNAPSHOT</version>
</dependency>
6.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="XXx"/>
<property name="duccUri" value="ucc://xxxx@test.ducc.jd.local/v1/namespace/workbench_backend/config/default/profiles/test?longPolling=60000&necessary=false"/>
<property name="duccMonitorKey" value="refundBugFlag"/>
</plugin>
</plugins>
</configuration>
6.3 核心配置项
6.4 默认分析效果展示
图3.慢sql分析效果
图4.sql动态替换效果
6.5 实践使用方案
<configuration>
<plugins>
<plugin interceptor="com.jd.sql.analysis.core.SqlAnalysisAspect" >
<property name="analysisSwitch" value="true"/>
</plugin>
</plugins>
</configuration>
<configuration>
<plugins>
<plugin interceptor="com.jd.sql.analysis.core.SqlAnalysisAspect" >
<property name="appName" value="xxx-backend"/>
<property name="analysisSwitch" value="true"/>
<property name="outputModel" value="mq"/>
<property name="mqApp" value="xxx"/>
<property name="mqUser" value="xxx"/>
<property name="mqPassword" value="xxx"/>
<property name="mqAddress" value="jmq-testcluster.jd.local:50088"/>
<property name="mqTopic" value="jdl_kds_key_node_log"/>
</plugin>
</plugins>
</configuration>
最终效果
图5.最终效果示意
<configuration>
<plugins>
<plugin interceptor="com.jd.sql.analysis.core.SqlAnalysisAspect" >
<property name="sqlReplaceModelSwitch" value="true"/>
<property name="duccAppName" value="zzz-backend"/>
<property name="duccUri" value="ucc://xxx/v1/namespace/workbench_backend/config/default/profiles/test?longPolling=60000&necessary=false"/>
<property name="duccMonitorKey" value="sqlReplaceConfig"/>
</plugin>
</plugins>
</configuration>
发现慢sql
图6.发现慢sql
ducc配置
图7.ducc配置
线上sql被动态替换
图8.线上sql被动态替换
注意:功能正式修复后,需去掉该配置,该功能仅供应急处理线上问题,不建议作为功能长期使用
07
理解,首先 MCube 会依据模板缓存状态判断是否需要网络获取最新模板,当获取到模板后进行模板加载,加载阶段会将产物转换为视图树的结构,转换完成后将通过表达式引擎解析表达式并取得正确的值,通过事件解析引擎解析用户自定义事件并完成事件的绑定,完成解析赋值以及事件绑定后进行视图的渲染,最终将目标页面展示到屏幕。
测试环境千次普通sql查询,每种场景进行了5次测试
未启用插件耗时:11108ms,10237ms,9482ms,7938ms,8196ms
开启sql分析耗时:16619ms,17333ms,16321ms,19057ms,18164ms
实际配置,只有首次执行或者间隔时间执行,单次影响10ms左右
开启sql替换耗时:10642ms,8803ms,8353ms,8830ms,9170ms
基本无影响
08
理解,首先 MCube 会依据模板缓存状态判断是否需要网络获取最新模板,当获取到模板后进行模板加载,加载阶段会将产物转换为视图树的结构,转换完成后将通过表达式引擎解析表达式并取得正确的值,通过事件解析引擎解析用户自定义事件并完成事件的绑定,完成解析赋值以及事件绑定后进行视图的渲染,最终将目标页面展示到屏幕。
1、慢sql预防
2、线上问题止损
09
理解,首先 MCube 会依据模板缓存状态判断是否需要网络获取最新模板,当获取到模板后进行模板加载,加载阶段会将产物转换为视图树的结构,转换完成后将通过表达式引擎解析表达式并取得正确的值,通过事件解析引擎解析用户自定义事件并完成事件的绑定,完成解析赋值以及事件绑定后进行视图的渲染,最终将目标页面展示到屏幕。
1、核心优势:执行时分析sql,区别于传统的依赖sql执行耗时来评估慢sql,直接基于语法和索引进行前置分析,不仅能预防某些坏sql在上线后发现是慢sql,还能给出sql优化建议,可以大限度的避免线上产生慢sql。支持动态对线上sql进行替换,可以对线上问题快速止损。
2、性能:基于性能和不同的使用场景考虑,支持定制化配置,每个sql是否仅进行一次检查、或者按某个时间间隔进行配置。sql替换几乎无损耗。
3、扩展:基于后续sql评分规则的扩展、以及分析结果以不同的方式输出的考虑,支持评分规则、输出方式的自定义扩展。
4、成本:接入成本低,无代码侵入。
10
理解,首先 MCube 会依据模板缓存状态判断是否需要网络获取最新模板,当获取到模板后进行模板加载,加载阶段会将产物转换为视图树的结构,转换完成后将通过表达式引擎解析表达式并取得正确的值,通过事件解析引擎解析用户自定义事件并完成事件的绑定,完成解析赋值以及事件绑定后进行视图的渲染,最终将目标页面展示到屏幕。
本组件的核心思想,通过把慢sql分析过程中最常用的explain分析规则,以Mybatis组件的形式集成到项目中,在运行时同步分析。大家参考这种方式的时候,需要衡量性能的影响以及规则的复杂度,欢迎大家指正和提出意见。
▪
底层能力:维护用户基础数据、行为数据建模、用户画像分析、精准营销策略的制定
▪功能支撑:会员成长体系、等级计算策略、权益体系、营销底层能力支持
▪用户活跃:会员关怀、用户触达、活跃活动、业务线交叉获客、拉新促活