全量SQL(所有拜访数据库的SQL)能够无效地帮忙平安进行数据库审计,帮忙业务疾速排查性能问题。个别可通过开启genlog日志或者启动MySQL审计插件形式来进行获取,而美团选用了一种非侵入式的旁路抓包计划,应用Go语言实现。无论采纳哪种计划,都须要重点关注它对数据库的性能损耗。本文介绍了美团根底研发平台抓包计划在数据库审计实际中遇到的性能问题以及优化实际,心愿能对大家有所帮忙或启发。

1 背景

数据库安全始终是美团信息安全团队和数据库团队十分重视的畛域,但因为历史起因,对数据库的拜访只具备采样审计能力,导致对于一些攻打事件无奈疾速地发现、定损和优化。平安团队依据历史教训,发现攻打拜访数据库基本上都存在着某些特色,常常会应用一些特定SQL,咱们心愿通过对MySQL拜访流量进行全量分析,辨认出习用SQL,在数据库安全性上做到对症下药。

2 现状及挑战

下图是采样MySQL审计零碎的架构图,数据采集端基于pcap抓包形式实现,数据处理端选用美团大数据中心的日志接入计划。所有MySQL实例都部署了用于采集MySQL相干数据的rds-agent、日志收集的log-agent。rds-agent抓取到MySQL拜访数据,通过log-agent上报到日志接收端,为了缩小延时,上报端与接收端间做了同机房调度优化。日志接收端把数据写入到约定的Kafka中,平安团队通过Storm实时生产Kafka剖析出攻打事件,并定期拉数据长久化到Hive中。

咱们发现,通常被攻打的都是一些外围MySQL集群。经统计发现,这些集群单机最大QPS的9995线约5万次左右。rds-agent作为MySQL机器上的一个寄生过程,为了宿主稳定性,资源管制也极为重要。为了评估rds-agent在高QPS下的体现,咱们用Sysbench对MySQL进行压测,察看在不同QPS下rds-agent抓取的数据失落率和CPU耗费状况,从上面的压测数据来看后果比拟蹩脚:

QPS失落率CPU利用率
10368.721.03%307.35%
17172.617.23%599.90%
29005.5128.75%662.39%
42697.0551.73%622.34%
50833.5063.95%601.39%

如何在高QPS下保障较低的失落率与CPU耗费?曾经成为以后零碎的一个亟待解决的难题与挑战。

3 剖析及优化

上面次要介绍围绕失落率与CPU耗费这一问题,咱们对数据采集端在流程、调度、垃圾回收和协定方面做的剖析与改良。

3.1 数据采集端介绍

首先,简要介绍一下数据采集端rds-agent,它是一个MySQL实例上的过程,采纳Go语言编写,基于开源的MysqlProbe的Agent革新。通过监听网卡上MySQL端口的流量,剖析出客户端的拜访工夫、起源IP、用户名、SQL、指标数据库和指标IP等审计信息。上面是其架构图,次要分为5大功能模块:

1. probe

probe意为探针,采纳了gopacket作为抓包计划,它是谷歌开源的一个Go抓包库,封装了pcap。probe把抓取到原始的数据链路层帧封装成TCP层的数据包。通过变种的Fowler-Noll-Vo算法哈希源和目标IP port字段,疾速实现把数据库连贯打散到不同的worker中,该算法保障了同一连贯的来包与回包的哈希值一样。

2. watcher

登录用户名对于审计来说极其重要,客户端往往都是通过长连贯拜访MySQL,而登录信息仅呈现在MySQL通信协议的认证握手阶段,仅通过抓包容易错过。

watcher通过定时执行show processlist获取以后数据库的所有连贯数据,通过比照Host字段与以后包的客户端ip port,弥补错过的用户名信息。

3. worker

不同的worker负责管理不同数据库连贯的生命周期,一个worker治理多个连贯。通过定期比对worker的以后连贯列表与watcher中的连贯列表,及时发现过期的连贯,敞开并开释相干资源,避免内存透露。

4. connStream

整个数据采集端的外围逻辑,负责依据MySQL协定解析TCP数据包并辨认出特定SQL,一个连贯对应一个connStream Goroutine。因为SQL中可能蕴含敏感数据,connStream还负责对SQL进行脱敏,具体的特定SQL辨认策略,因为平安方面起因,这里不再进行开展。

5. sender

负责数据上报逻辑,通过thrift协定将connStream解析出的审计数据上报给log-agent。

3.2 根底性能测试

抓包库gopacket的性能间接决定了零碎性能下限,为了探索问题是否出在gopacket上,咱们编写了繁难的tcp-client和tcp-server,独自对gopacket在数据流向图中波及到的前三个步骤(如下图所示)进行了性能测试,从上面的测试后果数据上看,性能瓶颈点不在gopacket。

QPSpcap缓冲区失落率CPU利用率
100000100MB0%144.9%

3.3 CPU画像剖析

失落率与CPU耗费二者密不可分,为了探索如此高CPU耗费的起因,咱们用Go自带的pprof工具对过程的CPU耗费进行了画像剖析,从上面火焰图的调用函数能够演绎出几个大头:SQL脱敏、解包、GC和Goroutine调度。上面次要介绍一下围绕它们做的优化工作。

3.4 脱敏剖析及改良

因为SQL中可能蕴含敏感信息,出于平安思考,rds-agent会对每一条SQL进行脱敏解决。

脱敏操作应用了pingcap的SQL解析器对SQL进行模板化:即把SQL中的值全副替换成“?”来达到目标,该操作须要解析出SQL的形象语法树,代价较高。以后只有采样和抓取特定SQL的需要,没有必要在解析阶段对每条SQL进行脱敏。这里在流程上进行了优化,把脱敏下沉到上报模块,只对最终发送进来的样本脱敏。

这个优化获得的成果如下:

比照项QPS失落率CPU利用率
改良前50833.5063.95%601.39%
改良后51246.47<font color=##FF0000>31.95%</font><font color=##FF0000>259.59%</font>

3.5 调度剖析及改良

从上面的数据流向图能够看出整个链路比拟长,容易呈现性能瓶颈点。同时存在泛滥高频运行的Goroutine(红色局部),因为数量多,Go须要常常在这些Goroutine间进行调度切换,切换对于咱们这种CPU密集型的程序来说无疑是一种累赘。

针对该问题,咱们做了如下优化:

  1. 缩短链路:分流、worker、解析SQL等模块合并成一个Goroutine解析器。
  2. 升高切换频率:解析器每5ms从网络协议包的队列中取一次,相当于手动触发切换。(5ms也是一个屡次测试后的折中数据,太小会耗费更多的CPU,太大会引起数据失落)

这个优化获得的成果如下:

比照项QPS失落率CPU利用率
改良前51246.4731.95%259.59%
改良后51229.54<font color=##FF0000>0%</font><font color=##FF0000>206.87%</font>

3.6 垃圾回收压力剖析及改良

下图为rds-agent抓包30秒,已调配指针对象的火焰图。能够看出曾经调配了4千多万个对象,GC压力可想而知。对于GC,咱们理解到如下两种优化计划:

  1. 池化:Go的规范库中提供了一个sync.Pool对象池,可通过复用对象来缩小对象调配,从而升高GC压力。
  2. 手动治理内存:通过零碎调用mmap间接向OS申请内存,绕过GC,实现内存的手动治理。

然而,计划2容易呈现内存透露。从稳定性的角度思考,咱们最终抉择了计划1来治理高频调用函数里创立的指针对象,这个优化获得的成果如下:

比照项QPS失落率CPU利用率
改良前51229.540%206.87%
改良后51275.110%<font color=##FF0000>153.32%</font>

3.7 解包剖析及改良

MySQL是基于TCP协定之上的,在性能调试过程中,咱们发现了很多空包。从上面的MySQL客户端-服务端数据的交互图能够看出:当客户端发送一条SQL命令,服务端响应后果,因为TCP的音讯确认机制,客户端会发送一个空的ack包来确认音讯,而且空包在整个流程中的比例较大,它们会穿透到解析环节,在高QPS下对于Goroutine调度和GC来说无疑是一个累赘。

下图是MySQL数据包的惟一格局,通过剖析,咱们察看到以下特点:

  1. 一个残缺的MySQL数据包长度>=4Byte
  2. 客户端新发送命令的sequence id都是为0或者1

而pcap反对设置过滤规定,让咱们能够在内核层将空包排除掉,上面是上述特点对应的两条过滤规定:

特点1: ip[2:2] - ((ip[0] & 0x0f) << 2) - ((tcp[12:1] & 0xf0) >> 2) >= 4特点2: (dst host {localIP} and dst port 3306 and (tcp[(((tcp[12:1] & 0xf0) >> 2) + 3)] <= 0x01))

这个优化获得的成果如下:

比照项QPS失落率CPU利用率
改良前51275.110%153.32%
改良后51246.020%<font color=##FF0000>142.58%</font>

基于上述教训,咱们对数据采集端进行性能代码重构,同时还进行一些其它优化。

4 最终成绩

上面是优化前后的数据比照,失落率从最高60%降落到了0%, CPU耗费从最高占用6个核降落到了1个核。

为了探索抓包性能对MySQL性能损耗,咱们用Sysbench做了一个性能比照测试。从上面的后果数据能够看出性能对MySQL的TPS、QPS和响应工夫99线指标最高大概有6%的损耗。

5 将来布局

尽管咱们对抓包计划进行了各种优化,但对于一些提早敏感的业务来说性能损耗还是偏大,而且该计划对一些非凡场景反对较差:如TCP协定层产生丢包、重传、乱序时,MySQL协定层应用压缩、传输大SQL时。而业界广泛采纳了间接革新MySQL内核的形式来输入全量SQL,同时也反对输入更多的指标数据。目前,数据库内核团队也实现了该计划开发,正在线上灰度替换抓包计划中。另外,对于线上全量SQL端到端失落率指标的缺失,咱们也将陆续进行补齐。

本文作者

粟含,来自于美团根底研发平台/根底技术部/数据库技术核心。

招聘信息

美团根底技术部-数据库技术核心诚招高级、资深技术专家,Base上海、北京。美团关系数据库规模大,每年疾速的增长,每天承载数千亿的拜访流量。在这里能够体验高并发、高可用、高可扩展性的业务挑战,能够紧跟并开辟业界前沿技术,领会到技术提高带来的生产力晋升,欢送投递简历至:suhan03@meituan.com。

浏览美团技术团队更多技术文章合集

前端 | 算法 | 后端 | 数据 | 平安 | 运维 | iOS | Android | 测试

| 在公众号菜单栏对话框回复【2021年货】、【2020年货】、【2019年货】、【2018年货】、【2017年货】等关键词,可查看美团技术团队历年技术文章合集。

| 本文系美团技术团队出品,著作权归属美团。欢送出于分享和交换等非商业目标转载或应用本文内容,敬请注明“内容转载自美团技术团队”。本文未经许可,不得进行商业性转载或者应用。任何商用行为,请发送邮件至tech@meituan.com申请受权。