ELK 构建 MySQL 慢日志收集平台详解

ELK 介绍

ELK 最早是 Elasticsearch(以下简称ES)、Logstash、Kibana 三款开源软件的简称,三款软件后来被同一公司收购,并加入了Xpark、Beats等组件,改名为Elastic Stack,成为现在最流行的开源日志解决方案,虽然有了新名字但大家依然喜欢叫她ELK,现在所说的ELK就指的是基于这些开源软件构建的日志系统。

我们收集mysql慢日志的方案如下:

  • mysql 服务器安装 Filebeat 作为 agent 收集 slowLog

  • Filebeat 读取 mysql 慢日志文件做简单过滤传给 Kafka 集群

  • Logstash 读取 Kafka 集群数据并按字段拆分后转成 JSON 格式存入 ES 集群

  • Kibana读取ES集群数据展示到web页面上

慢日志分类

目前主要使用的mysql版本有5.5、5.6 和 5.7,经过仔细对比发现每个版本的慢查询日志都稍有不同,如下:

5.5 版本慢查询日志

5.6 版本慢查询日志

5.7 版本慢查询日志

慢查询日志异同点:

  1. 每个版本的Time字段格式都不一样

  2. 相较于5.6、5.7版本,5.5版本少了Id字段

  3. use db语句不是每条慢日志都有的

  4. 可能会出现像下边这样的情况,慢查询块# Time:下可能跟了多个慢查询语句

处理思路

上边我们已经分析了各个版本慢查询语句的构成,接下来我们就要开始收集这些数据了,究竟应该怎么收集呢?

  1. 拼装日志行:mysql 的慢查询日志多行构成了一条完整的日志,日志收集时要把这些行拼装成一条日志传输与存储。

  2. Time行处理:# Time: 开头的行可能不存在,且我们可以通过SET timestamp这个值来确定SQL执行时间,所以选择过滤丢弃Time行

  3. 一条完整的日志:最终将以# User@Host: 开始的行,和以SQL语句结尾的行合并为一条完整的慢日志语句

  4. 确定SQL对应的DB:use db这一行不是所有慢日志SQL都存在的,所以不能通过这个来确定SQL对应的DB,慢日志中也没有字段记录DB,所以这里建议为DB创建账号时添加db name标识,例如我们的账号命名方式为:projectName_dbName,这样看到账号名就知道是哪个DB了

  5. 确定SQL对应的主机:我想通过日志知道这条SQL对应的是哪台数据库服务器怎么办?

    慢日志中同样没有字段记录主机,可以通过filebeat注入字段来解决,例如我们给filebeat的name字段设置为服务器IP,这样最终通过beat.name这个字段就可以确定SQL对应的主机了。

Filebeat配置

filebeat 完整的配置文件如下:

# mysql_slow.log
-input_type: logpaths:- /home/logs/mysql/mysqld_slow.logdocument_type: mysqld-slowexclude_lines: ['^\# Time']multiline.pattern: '^\# Time|^\# User'multiline.negate: truemultiline.match: aftertail_files: true

重要参数解释:

  • input_type:指定输入的类型是log或者是stdin

  • paths:慢日志路径,支持正则,比如/data/*.log

  • exclude_lines:过滤掉# Time开头的行

  • multiline.pattern:匹配多行时指定正则表达式,这里匹配以# Time或者# User开头的行,Time行要先匹配再过滤

  • multiline.negate:定义上边pattern匹配到的行是否用于多行合并,也就是定义是不是作为日志的一部分

  • multiline.match:定义如何将皮排行组合成时间,在之前或者之后

  • tail_files:定义是从文件开头读取日志还是结尾,这里定义为true,从现在开始收集,之前已存在的不管

  • name:设置filebeat的名字,如果为空则为服务器的主机名,这里我们定义为服务器IP

  • output.kafka:配置要接收日志的kafka集群地址可topic名称

Kafka 接收到的日志格式:

{"@timestamp":"2018-08-07T09:36:00.140Z","beat":{"hostname":"db-7eb166d3","name":"10.63.144.71","version":"5.4.0"},"input_type":"log","message":"# User@Host: select[select] @  [10.63.144.16]  Id: 23460596\n# Query_time: 0.155956  Lock_time: 0.000079 Rows_sent: 112  Rows_examined: 366458\nSET timestamp=1533634557;\nSELECT DISTINCT(uid) FROM common_member WHERE hideforum=-1 AND uid != 0;","offset":1753219021,"source":"/data/slow/mysql_slow.log","type":"log"}

  

Logstash配置

logstash完整的配置文件如下:

仅显示filter信息

  if [type] =~ "mysqld-slow" {mutate {add_field => {"line_message" => "%{message} %{offset}"}}ruby {code => "require 'digest/md5';event.set('computed_id', Digest::MD5.hexdigest(event.get('line_message')))"}#有ID有usegrok {match => { "message" => "(?m)^# User@Host: %{USER:user}\[[^\]]+\] @\s+(?:(?<clienthost>\S*))?\s+\[(?:%{IP:clientip})?\]\s+Id:\s+%{NUMBER:id:
int}\n\#\s+Query_time: %{NUMBER:query_time:float}\s+Lock_time: %{NUMBER:lock_time:float}\s+Rows_sent:\s+%{NUMBER:rows_sent:int}\s+Rows_examined: 
%{NUMBER:rows_examined:int}\nuse\s(?<dbname>\w+)\;\s+SET\s+timestamp=%{NUMBER:timestamp_mysql:int}\;\s+(?<query>.*)" }}#有ID无usegrok {match => {"message" => "(?m)^# User@Host: %{USER:user}\[[^\]]+\] @\s+(?:(?<clienthost>\S*))?\s+\[(?:%{IP:clientip})?\]\s+Id:\s+%{NUMBER:id
:int}\n\#\s+Query_time: %{NUMBER:query_time:float}\s+Lock_time: %{NUMBER:lock_time:float}\s+Rows_sent:\s+%{NUMBER:rows_sent:int}\s+Rows_examined:%{NUMBER:rows_examined:int}\nSET\s+timestamp=%{NUMBER:timestamp_mysql:int}\;\s+(?<query>.*)"}}#无ID有usegrok {    				                                match => {"message" => "(?m)^# User@Host: %{USER:user}\[[^\]]+\] @\s+(?:(?<clienthost>\S*))?\s+\[(?:%{IP:clientip})?\]\n\#\s+Query_time: %
{NUMBER:query_time:float}\s+Lock_time: %{NUMBER:lock_time:float}\s+Rows_sent:\s+%{NUMBER:rows_sent:int}\s+Rows_examined: %{NUMBER:rows_examined:i
nt}\nuse\s(?<dbname>\w+)\;\nSET\s+timestamp=%{NUMBER:timestamp_mysql:int}\;\s+(?<query>.*)"}}#无ID无usegrok {match => { "message" => "(?m)^# User@Host: %{USER:user}\[[^\]]+\] @\s+(?:(?<clienthost>\S*))?\s+\[(?:%{IP:clientip})?\]\n\#\s+Query_time: %{
NUMBER:query_time:float}\s+Lock_time: %{NUMBER:lock_time:float}\s+Rows_sent:\s+%{NUMBER:rows_sent:int}\s+Rows_examined: %{NUMBER:rows_examined:in
t}\nSET\s+timestamp=%{NUMBER:timestamp_mysql:int}\;\s+(?<query>.*)" }}date {match => ["timestamp_mysql", "UNIX"]target => "@timestamp"}mutate {remove_field => ["line_message","message","kafka","tags"]}}

重要参数解释:

  • input:配置 kafka 的集群地址和 topic 名字

  • filter:过滤日志文件,主要是对 message 信息(看前文 kafka 接收到的日志格式)进行拆分,拆分成一个一个易读的字段,例如User、Host、Query_time、Lock_time、timestamp等。

    grok段根据我们前文对mysql慢日志的分类分别写不通的正则表达式去匹配,当有多条正则表达式存在时,logstash会从上到下依次匹配,匹配到一条后边的则不再匹配。

    date字段定义了让SQL中的timestamp_mysql字段作为这条日志的时间字段,kibana上看到的实践排序的数据依赖的就是这个时间

  • output:配置ES服务器集群的地址和index,index自动按天分割

ES 中mysqld-slow-*索引模板

{"order": 0,"template": "mysqld-slow-*","settings": {"index": {"refresh_interval": "5s"}},"mappings": {"mysqld-slow": {"numeric_detection": true,"properties": {"@timestamp": {"type": "date","format": "strict_date_optional_time||epoch_millis"},"@version": {"type": "string"},"query_time": {"type": "double"},"row_sent": {"type": "string"},"rows_examined": {"type": "string"},"clientip": {"type": "string"},"clienthost": {"type": "string"},"id": {"type": "integer"},"lock_time": {"type": "string"},"dbname": {"type": "keyword"},"user": {"type": "keyword"},"query": {"type": "string","index": "not_analyzed"},"tags": {"type": "string"},"timestamp": {"type": "string"},"type": {"type": "string"}}}},"aliases": {}
}

kibana查询展示

  • 打开Kibana添加 mysql-slowlog-* 的Index,并选择timestamp,创建Index Pattern

  •  进入Discover页面,可以很直观的看到各个时间点慢日志的数量变化,可以根据左侧Field实现简单过滤,搜索框也方便搜索慢日志,例如我要找查询时间大于2s的慢日志,直接在搜索框输入 query_time: > 2 回车即可。

  • 点击每一条日志起边的很色箭头能查看具体某一条日志的详情。

  • 如果你想做个大盘统计慢日志的整体情况,例如top 10 SQL等,也可以很方便的通过web界面配置。

  • 总结

    1. 不要望而却步,当你开始去做已经成功一半了

    2. 本篇文章详细介绍了关于mysql慢日志的收集,收集之后的处理呢?我们目前是DBA每天花时间去Kibana上查看分析,有优化的空间就跟开发一起沟通优化,后边达成默契之后考虑做成自动报警或处理

    3. 关于报警ELK生态的xpark已经提供,且最新版本也开源了,感兴趣的可以先研究起来,欢迎一起交流

 

转载于:https://www.cnblogs.com/xzlive/p/10762998.html

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

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

相关文章

数据类型转换规则C语言

一、数据类型 为什么对数据进行分类&#xff1a;节约存储空间&#xff0c;提高运行速度。整型&#xff1a;signedsigned char 1 -128~127signed short 2 -32678~32767signed int 4 正负20亿signed long 4/8 正负20亿/9…

Visual Studio 的码云扩展 V1.0.85 发布

开发四年只会写业务代码&#xff0c;分布式高并发都不会还做程序员&#xff1f; >>> Visual Studio 的码云扩展 V1.0.85 已发布&#xff1a; 针对扩展进行了SDK部分的重写修正克隆窗体和快捷方式的图标颜色随主题变化修正快捷方式 优化用户登录和token处理机制调整了…

用 FastJSON 将 JSON 字符串转换为 Map

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 本文是利用阿里巴巴封装的FastJSON来转换json字符串的。例子如下&#xff1a; import com.alibaba.fastjson.JSON; import com.aliba…

shark恒破解笔记4-API断点GetPrivateProfileStringA

这小节是通过断在GetPrivateProfileStringA&#xff0c;然后找到注册码的。 1.运行程序输入假码111111&#xff0c;提示重启。通过这判断这是一个重启来验证的&#xff0c;那么它是如何来验证的呢&#xff1f;观察程序目录下会发现有一个名为“config.ini"的文件 那么判断…

开关语句、循环语句、goto

复习&#xff1a; 1、数据类型&#xff1a;signed char 1 %hhd -128~127signed short 2 %hd -32768~32767signed int 4 %d 正负20亿signed long 4 %ldsigned long long 8 %lld 9天开头的19位数unsigned char …

成功男士的健康心理特征

自信&#xff1a;他们普遍都有很强的自信心&#xff0c;有时有咄咄逼人的感觉。 急迫感&#xff1a;他们通常很急地想见到事物的成果&#xff0c;因此会给别人带来许多的压力。他们信仰“时间就是金钱”&#xff0c;不喜欢也不会把宝贵的时间浪费在琐碎的无聊事情上。 脚踏实…

DBlink的创建与删除

创建方式一&#xff1a; create [public] database link link名称 connect to 对方数据库用户identified by 对方数据库用户密码 using 对方数据库ip:端口/服务名; 创建方式二&#xff1a; create [public] database link link名称 connect to 对方数据库用户identified by 对…

kong 启动报错 could not retrieve server_version: timeout

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 报错&#xff1a; nginx: [error] init_by_lua error: /usr/local/share/lua/5.1/kong/init.lua:169: [postgres error] could not ret…

2-STM32物联网开发WIFI(ESP8266)+GPRS(Air202)系统方案安全篇(监听Wi-Fi和APP的数据)

1-STM32物联网开发WIFI(ESP8266)GPRS(Air202)系统方案安全篇(来看一下怎么样监听网络数据,监听电脑上位机软件的数据) 因为那个软件只能监听咱自己电脑上的数据,所以咱就用电脑开个热点,然后让Wi-Fi和APP连接咱电脑的热点,这样就能监听数据了 电脑开个热点 手机APP连接这个热点…

数组越界的后果

数组&#xff1a; 什么是数组&#xff1a;变量的组合&#xff0c;是一种批量定义变量的方式。 定义&#xff1a;类型 数组名[数量];int arr[5]; 使用&#xff1a;数组名[下标];下标&#xff1a;从零开始&#xff0c;范围&#xff1a;0~数量-1。 遍历&#xff1a;与for循环配合…

职场心理:12个建议或许能改变你的一生(图)

心理引言&#xff1a;如何更好实现自我的职业目标&#xff1f;听起来很简单&#xff0c;回答也很简短&#xff0c;就是你必须清楚你最终想要实现什么&#xff1f;只要你这样做&#xff0c;你就已经开始从看的见和看不见的两条路径来实现你的目标。职场是一种特殊的环境&#xf…

python—包

1.模块 可以增加代码的重复利用的方式 避免命名冲突 如何定义模块 模块就是一个普通文件&#xff0c;所以任何代码可以直接书写规范 函数&#xff08;单一的功能&#xff09;类&#xff08;相似功能的组合&#xff0c;或者类似业务模块&#xff09;测试代码 如何使用模块 模块…

Docker Installation : Docker 中安装并启动 Kong

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 Details about how to use Kong in Docker can be found on the DockerHub repository hosting the image: kong. We also have a Docke…

tomcat是否有必要配置环境变量(摘)

之前发表了一篇关于如何安装和配置Tomcat的文章&#xff0c;而最近在开发项目的时候总是报错。后来被公司的大神问了一句&#xff1a;是谁告诉你Tomcat是需要配置环境变量的&#xff1f; 作为新手的我瞬间整个人都不好了&#xff01;于是偷偷百度了一下&#xff0c;终于找到了关…

走迷宫+推箱子

两个小游戏的大致逻辑 走迷宫: 1、定义二维字符数组作为迷宫 2、定义变量记录老鼠的位置 3、获取游戏开始时间 3、进入循环 1、清理屏幕&#xff0c;使用system调用系统命令。 2、显示迷宫(遍历二维字符数组) 3、检查是否到达出口 获取游戏结束时间&#xff0c;计算出走出迷宫用…

Facebook开源ptr:在Python环境中并行运行单元测试

Facebook开源了一个名为Python Test Runner&#xff08;ptr&#xff09;的新项目&#xff0c;允许开发人员运行Python单元测试套件。ptr和现有测试运行器之间的主要区别在于ptr通过爬取存储库查找一定的Python项目&#xff0c;这些项目带有的单元测试在安装文件中已经定义过。 …

小窍门解决大问题(组图)

1.洗头时&#xff0c;在水中放少许盐&#xff0c;也可以预防脱发。 2.用醋洗头&#xff0c;可以令头发飘顺&#xff0c;容易打理而且兼有去头皮屑的功效。特别适合烫染后的头发。 3.刷牙时在牙膏上加上一点小苏打&#xff0c;刷三次后牙齿洁白如玉&#xff0c;牙锈自然脱落…

解决报错: Connecting to Kong on http ... Could not reach Kong on http://xxx.xxx.xxx.xxx:8001

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1. Docker 中安装并启动好网关 kong 后&#xff0c;想要安装 kong 的图形化界面 kong-dashboard &#xff0c;运行命令&#xff1a; do…

生成迷宫/C++

小时候&#xff0c;都喜欢玩迷宫&#xff0c;现在的电脑上还可以玩3D类迷宫。 那么每次开始游戏时&#xff0c;迷宫里密密麻麻的道路是怎么生成的呢&#xff1f; 在代码里面&#xff0c;我们把它们想象成一堆像素小格子&#xff0c;当两个格子连在一起&#xff0c;就像一堵墙&a…

Spring boot 配置tomcat后 控制台不打印SQL日志

在pom.xml中配置tomcat启动处加上&#xff1a; <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><exclusions><exclusion><groupId>org.springframework.boot</…