一、使用Logstash使用jdbc从MySQL读取数据操作

1.1 安装jdbc插件

jdbc默认已安装,如果没安装使用logstash-plugin安装即可(logstash-plugin在logstash的bin目录下):

logstash-plugin install logstash-input-jdbc

1.2 下载mysql jdbc驱动

mysql最新版是8.0,但使用时报错,这里仍以5.1版本演示

wget https://cdn.mysql.com//Downloads/Connector-J/mysql-connector-java-5.1.47.zip
# 不推荐放/tmp目录,但这里为了与用户无关所以直接解压到/tmp目录
unzip mysql-connector-java-5.1..zip -d /tmp

1.3 配置logstash文件

配置如下项,如无意外mysql中数据即可同步到elasticsearch

input{
jdbc {
# jdbc:mysql://数据库ip:端口/数据库名
jdbc_connection_string => "jdbc:mysql://10.10.6.91:3306/expdb"
# 数据库用户名
jdbc_user => "root"
# 数据库密码
jdbc_password => "root"
# mysql java驱动文件位置
jdbc_driver_library => "/tmp/mysql-connector-java-5.1.47/mysql-connector-java-5.1.47.jar"
# 驱动类名,这个一般不需要改
jdbc_driver_class => "com.mysql.jdbc.Driver"
jdbc_paging_enabled => "true"
jdbc_page_size => ""
# 与crontab类似的格式,* * * * *基本隔十来秒就同步一次
schedule => "* * * * *"
# 同步时要执行的sql语句,语句最终的结果集同步到elasticsearch; 我这里只是简单将表中所有记录查出
# 如果语句很多,可使用statement_file来指定sql语句文件
statement => "select * from exploit_records"
}
} filter { } output{
elasticsearch {
hosts => ["localhost:9200"]
}
}

二、记录重复问题

2.1 单日记录重复问题

2.1.1 问题描述

elasticsearch以_id项作为主键,只要传过来的数据中_id项的值尚未存在elasticsearch会接收该数据。

而_id项的值默认其实是数据到来时elasticsearch自己生成的然后添加上去的,所以在这种情况下_id是不可能重复的,即所有数据都会被来者不拒地接收。

logstash jdbc插件对数据库的数据的操作是依照计划(schedule)执行sql语句(statement),所有查出来的数据就统统按output发过去。

在这种模式下,每执行一次计划(schedule)所有记录就会被发往elasticsearch一次,而_id是由elasticsearch生成的不会重复,所以不同次计划(schedule)的同一条记录会被elasticsearch反复收录。

2.1.2 问题处理办法

同一条记录被反复收录这种情况一般都不是我们想要的,而要消除这种情况其关键是要将_id变成不是由elasticsearch自动生成,更确切地讲是要将_id变成人为可控地生成。

这种配置也不难,elasticsearch允计通过使用document_id来配置_id。

假设我们表的主键是edb_id,为了避免重复,我们要以表主键值赋值给document_id即可。此时1.3中配置修改如下:

input{
jdbc {
# jdbc:mysql://数据库ip:端口/数据库名
jdbc_connection_string => "jdbc:mysql://10.10.6.91:3306/expdb"
# 数据库用户名
jdbc_user => "root"
# 数据库密码
jdbc_password => "root"
# mysql java驱动文件位置
jdbc_driver_library => "/tmp/mysql-connector-java-5.1.47/mysql-connector-java-5.1.47.jar"
# 驱动类名,这个一般不需要改
jdbc_driver_class => "com.mysql.jdbc.Driver"
jdbc_paging_enabled => "true"
jdbc_page_size => ""
# 与crontab类似的格式,* * * * *基本隔十来秒就同步一次
schedule => "* * * * *"
# 同步时要执行的sql语句,语句最终的结果集同步到elasticsearch; 我这里只是简单将表中所有记录查出
# 如果语句很多,可使用statement_file来指定sql语句文件
statement => "select * from exploit_records"
}
} filter { } output{
elasticsearch {
hosts => ["localhost:9200"]
# 相比1.3只多加了这一句
# 将表主键edb_id字段的值赋值给elasticsearch的主键
document_id => "%{edb_id}"
}
}

2.1.3 多路径输入问题

由于我们这里只查询了一张表,所以2.2中的配置没有什么问题。但只果此时要多输入一张表这张表没有edb_id字段,那么按document_id => "%{edb_id}"取到的edb_id会为空,这张表的数据会因_id项值都为空而被视为重复项不为elasticsearch所收录。

对于这种情况,jdbc预留了type项,可将type项赋值为表名进行区分。

但如果表中原来就有type字段,那么给type项赋值将会覆盖type字段的值,这是我们所不想看到的。此时就不适合使用type项了,只能转而使用其他条件加以区分比如if [edb_id] != ""等等。

如果不是读表而是读其他东西,比如读txt文件处理思路是一样的,只要找到一个if条件让txt文件的内容会转到其相应output输出即可。

input{
jdbc {
# jdbc:mysql://数据库ip:端口/数据库名
jdbc_connection_string => "jdbc:mysql://10.10.6.91:3306/expdb"
# 数据库用户名
jdbc_user => "root"
# 数据库密码
jdbc_password => "root"
# mysql java驱动文件位置
jdbc_driver_library => "/tmp/mysql-connector-java-5.1.47/mysql-connector-java-5.1.47.jar"
# 驱动类名,这个一般不需要改
jdbc_driver_class => "com.mysql.jdbc.Driver"
jdbc_paging_enabled => "true"
jdbc_page_size => ""
# 与crontab类似的格式,* * * * *基本隔十来秒就同步一次
schedule => "* * * * *"
# 同步时要执行的sql语句,语句最终的结果集同步到elasticsearch; 我这里只是简单将表中所有记录查出
# 如果语句很多,可使用statement_file来指定sql语句文件
statement => "select * from exploit_records"
# 将type项赋值为表名exploit_records
type => "exploit_records"
}
# 多读一张表cve_records
jdbc {
jdbc_connection_string => "jdbc:mysql://10.10.6.91:3306/expdb"
jdbc_user => "root"
jdbc_password => "root"
jdbc_driver_library => "/tmp/mysql-connector-java-5.1.47/mysql-connector-java-5.1.47.jar"
jdbc_driver_class => "com.mysql.jdbc.Driver"
jdbc_paging_enabled => "true"
jdbc_page_size => ""
schedule => "* * * * *"
statement => "select * from cve_records"
# 将type项赋值为表名cve_records
type => "cve_records"
}
} filter { } output{
if [type] == "exploit_records"{
elasticsearch {
hosts => ["localhost:9200"]
document_id => "%{edb_id}"
}
}
if [type] == "cve_records"{
elasticsearch {
hosts => ["localhost:9200"]
document_id => "%{cve}"
}
}
}

2.2 多日记录重复问题

2.2.1 问题描述

经过2.1的处理后在单日中已不会出现重复记录,但由于elasticsearch中将不同日期收到的记录存到不同index中,index不同即便是同id也不会被认为是同一条记录所以记录会被收复,有时这种不同日期的重复我们也是不希望有的。

其实更本质而言,并不是“elasticsearch中将不同日期收到的记录存到不同index中”,elasticsearch只是接收记录将记录存放到记录index字段所标识的index中。而logstash的elasticsearch插件默认生成的index字段值是"logstash-%{+YYYY.MM.dd}"

我们要避免不同日期记录重复,其做法就是重写index值将其设置成一个不随日期变化的固定值。

2.2.2 配置示例

input{
jdbc {
# jdbc:mysql://数据库ip:端口/数据库名
jdbc_connection_string => "jdbc:mysql://10.10.6.91:3306/expdb"
# 数据库用户名
jdbc_user => "root"
# 数据库密码
jdbc_password => "root"
# mysql java驱动文件位置
jdbc_driver_library => "/tmp/mysql-connector-java-5.1.47/mysql-connector-java-5.1.47.jar"
# 驱动类名,这个一般不需要改
jdbc_driver_class => "com.mysql.jdbc.Driver"
jdbc_paging_enabled => "true"
jdbc_page_size => ""
# 与crontab类似的格式,* * * * *基本隔十来秒就同步一次
schedule => "* * * * *"
# 同步时要执行的sql语句,语句最终的结果集同步到elasticsearch; 我这里只是简单将表中所有记录查出
# 如果语句很多,可使用statement_file来指定sql语句文件
statement => "select * from exploit_records"
}
} filter { } output{
elasticsearch {
hosts => ["localhost:9200"]
# 将记录id设为表关键字,避免单日重复
document_id => "%{edb_id}"
# 将index由默认的logstash-%{+YYYY.MM.dd}设置成固定值,避免多日重复
index => "exploit_records"
}
}

三、if-else语句写法

在第二大节中我们多处用到if语句,这里再更具体说明一下其写法。

官方说明见:https://www.elastic.co/guide/en/logstash/current/event-dependent-configuration.html#conditionals

if-else语句格式如下,和各语言的写法是类似的:

if EXPRESSION {
...
} else if EXPRESSION {
...
} else {
...
}

而表达示(EXPRESSION)进一步可细化成操作项、操作符、和操作值三种元素。

比如在我们前面的写法中[type]就是操作项,==就是操作符,"exploit_records"就是操作值;操作项和操作值的位和其他语言一样可以互换(本质就是一个比较)。

if [type] == "exploit_records"{
elasticsearch {
hosts => ["localhost:9200"]
document_id => "%{edb_id}"
}
}

操作项----所有项的获取都和上边type一样使用中括号括起来的形式。

操作值----就是我们自己设定的操作项的比较标准。另外如果操作项是整型那操作值也应该是整型。

操作符----

一元操作符(unary):!
布尔操作符(boolean):and, or, nand, xor
相等操作符(equality): ==, !=, <, >, <=, >=
正则操作符(regexp): =~, !~ (checks a pattern on the right against a string value on the left,操作项在左边正则操作值在右边)
包含操作符(inclusion): in, not in

参考:

https://segmentfault.com/a/1190000014387486

ELK+MySQL出现大量重复记录问题处理的更多相关文章

  1. mysql中删除重复记录,只保留一条

    表结构如下: mysql> desc test1; +--------------+------------------+------+-----+---------+------------- ...

  2. 从mysql数据库删除重复记录只保留其中一条

    这两天做了一个调用第三方接口的小程序,因为是实时更新数据,所以请求接口的频率就很高,这样有时会出现往数据库插入重复的数据,对数据库造成压力也不方便管理,因为要通过原生sql语句,解决数据库的去重问题. ...

  3. MySQL查询表内重复记录

    查询及删除重复记录的方法(一)1.查找表中多余的重复记录,重复记录是根据单个字段(peopleId)来判断select * from peoplewhere peopleId in (select p ...

  4. MySQL之——查询重复记录、删除重复记录方法大全

    查找所有重复标题的记录: SELECT * FROM t_info a WHERE ((SELECT COUNT(*) FROM t_info WHERE Title = a.Title) >  ...

  5. 京东联盟开发(12)——删除MySQL表中重复记录并且只保留一条

    本文介绍如何删除商品表中的一些重复记录. 有时,一条商品由于有多个skuid,比如某种手机有不同颜色,但价格.优惠等信息却是一致,导致其被多次收录.由于其各种条件基本类似,这样它在商品中多个sku都排 ...

  6. MySQL查询表内重复记录并删除

    在日常业务场景中,经常会出现一个问题就是解决数据重复的问题,这里用到了一张用户表(s_user)做重复数据操作,分别包含了两个字段,id.name分别用于做唯一标示以及相同姓名的检索. 表结构以及测试 ...

  7. mysql中删除重复记录,并保留重复数据中的一条数据的SQL语句

    正好想写一条删除重复语句并保留一条数据的SQL,网上查了一部分资料写的很详细,但还是在这里写下自己的理解,以遍后续学习 .如下: 表字段和数据: SQL语句: [sql] view plain cop ...

  8. mysql如何删除重复记录

    方法有很多,除了最简便的, alter ignore table 表名  add UNIQUE index(字段名); 然后再将索引drop掉,这个方法外. 更加中规中矩的方法也是有的.. 比如我在网 ...

  9. mysql中去重复记录

    Distinct 这个只能放在查询语句的最前面 参考 : https://www.cnblogs.com/lushilin/p/6187743.html

随机推荐

  1. GDB查看堆栈局部变量

    GDB查看堆栈局部变量 “参数从右到左入栈”,“局部变量在栈上分配空间”,听的耳朵都起茧子了.最近做项目涉及C和汇编互相调用,写代码的时候才发现没真正弄明白.自己写了个最简单的函数,用gdb跟踪了调用 ...

  2. JUnit单元测试代码

    package com.storage.test; import org.junit.Before; import org.junit.Test; import org.springframework ...

  3. solr6.5.1搜索引擎的部署

    目录结构如下: 6.5.1版本的solr已经集成有jetty服务器(在server目录下),所以可以直接启动solr应用. 1.java环境配置好(这里不再累赘). 2.打开cmd,路径切换到bin目 ...

  4. 2018-2019-1 20189203《Linux内核原理与分析》第八周作业

    第一部分 课本学习 ELF文件(目标文件)格式主要三种: 1)可重定向文件:文件保存着代码和适当的数据,用来和其他的目标文件一起来创建一个可执行文件或者是一个共享目标文件.(目标文件或者静态库文件,即 ...

  5. python列表常用内建方法

    python列表常用内建方法: abc = ['a',1,3,'a'] #abc.pop(1) #删除索引1的值.结果['a', 3] #abc.append([123]) #结果:['a', 1, ...

  6. C#设计模式(12)——享元模式(Flyweight Pattern)(转)

    一.引言 在软件开发过程,如果我们需要重复使用某个对象的时候,如果我们重复地使用new创建这个对象的话,这样我们在内存就需要多次地去申请内存空间了,这样可能会出现内存使用越来越多的情况,这样的问题是非 ...

  7. 【2017-05-18】WebForm的Repeater控件及简单控件

    <%@ %> - 这里面写一些声明和引用的 <%  %> - 编写C#代码的 <%= %> - 往界面上输出一个变量的值 <%# Eval("属性名 ...

  8. 【Spark-core学习之二】 RDD和算子

    环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 jdk1.8 scala-2.10.4(依赖jdk1.8) spark ...

  9. win10安装JDK

    1.下载 首先,在官网下载 JDK:Oracle 官网 如上图所示,在 Oracle 官网下载 JDK,有一点需要注意,那就是在咱们下载合适的 JDK 之前,需要先点击“标记1”所在的按钮,选择接受. ...

  10. pssh批量管理

    因为公司金融项目正式上线,有等保的要求,所有的线上服务器对操作过历史命令都要记录下来,需要修改一部分的配制文件.总共有300多台Linux服务器,总不能一台一台去改吧.首先想到是ansble,salt ...