摘要:最近将mysql数据库表里面的内容转移到了ES里面,这里面还是踩了一些坑,特意进行记录
需求:通过select语句查询mysql的数据,然后将所有查询到的内容存储到ES中,注意,重点理解什么数据会被存储到ES中。
需求完成方式:需要使用到logstash,将该sql语句交给logstash去定时执行,然后再提交给ES
涉及到的组件:
工具 | 版本 |
ES | 7.8 |
kibana | 7.8 |
logstash | 7.8 |
首先安装上面的三个组件,可以参考网上的教程。
这里重点说的是logstash的配置,我的logstash是安装在了/usr/local/logstash目录下。
logstash执行mysql语句需要依赖一个插件:logstash-integration-jdbc【原来叫logstash-input-jdbc】
这里来说说该插件的安装,网上很多的安装都是比较老的了。
安装步骤:
yum install -y gem
# 替换官网的rubygem源,替换成华为的 # 网上很多说使用阿里的,其实阿里的这个源早就停止维护了
gem sources --add https://mirrors.huaweicloud.com/repository/rubygems/ --remove https://rubygems.org/
# 使用下面的命令查看替换是否成功
gem sources -l
替换成功的话,会出现下面如图显示
#采用下面的语句安装插件
/usr/local/logstash/bin/logstash-plugin install logstash-integration-jdbc
说明:如果不替换rubygem源的话,安装过程会很长,而且还有很大几率失败。
插件安装完成后,就需要下载一个java连接mysql的jar包,由于logstash-integration-jdbc插件采用了java去连接数据库,所以需要下载该包。下载方法就是在百度上搜索“mysql-connector-java”,就可以很轻松下载到。我是在官网上下载的,下载的是一个tar包,加压后将mysql-connector-java-5.1.49.tar.gz解压后,将解压出来的jar包移到/usr/local/logstash/logstash-core/lib/jars/目录下。
现在我们的插件安装了,连接数据库的jar包也有了。接下来就是去编写logstash的配置文件了。将下面的内容放在/usr/local/logstash/conf/jdbc.conf
input {
stdin {}
jdbc {
# 连接的数据库地址和哪一个数据库,指定编码格式,禁用SSL协议,设定自动重连
jdbc_connection_string => "jdbc:mysql://192.168.1.4:3306/mysql_dbname?tinyInt1isBit=false&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&serverTimezone=GMT%2B8"
jdbc_user => "mysql_user"
jdbc_password => "mysql_password"
# 下载连接数据库的驱动包,建议使用绝对地址
jdbc_driver_library => "/usr/local/logstash/logstash-core/lib/jars/mysql-connector-java-5.1.49.jar"
# 默认是将mysql字段的大写转成小写,关闭这个转换
lowercase_column_names => false
jdbc_driver_class => "com.mysql.jdbc.Driver"
jdbc_paging_enabled => "true"
jdbc_page_size => "50000"
codec => plain { charset => "UTF-8"}
#使用其它字段追踪,而不是用时间。
#use_column_value => true
#这里如果是用时间追踪比如:数据的更新时间或创建时间等,那么这里一定不能是true, 切记切记切记,我是用update_time来追踪的
#追踪字段一般有两种,一种是时间[update_time]一种是数字类[id]
#追踪的字段
tracking_column => update_time
# 是否记录上一次查询的追踪字段的值。
record_last_run => true
#上一个sql_last_value值的存放文件路径, 必须要在文件中指定字段的初始值 这里说是必须指定初始值,没指定默认是1970-01-01 08:00:00
last_run_metadata_path => "/usr/local/logstash/lastrun/.logstash_jdbc_last_run"
jdbc_default_timezone => "Asia/Shanghai"
# 这是执行的sql语句,我是写在了jdbc.sql文件中
statement_filepath => "/usr/local/logstash/data/jdbc.sql"
#是否清除 last_run_metadata_path 的记录,如果为真那么每次都相当于从头开始查询所有的数据库记录
clean_run => false
#这是控制定时的,重复执行导入任务的时间间隔,这里设置为1分钟去执行一次sql
schedule => "* * * * *"
}
}
filter {
json {
source => "message"
remove_field => ["message"]
}
}
output {
elasticsearch {
# 要导入到的Elasticsearch所在的主机
hosts => ["192.168.1.2:9200"]
# 要导入到的Elasticsearch的索引的名称
index => "index_name"
# 类型名称(类似数据库表名)
document_type => "_doc"
# 主键名称(类似数据库主键)
document_id => "%{id}"
}
stdout {
# JSON格式输出
codec => json_lines
}
}
下面是我在:/usr/local/logstash/data/jdbc.sql的内容
SELECT u.id,
u.openId,
u.cardId,
DATE_FORMAT( u.createTs,'%Y-%m-%d %T' ) AS createTs,
u.state,
u.userName,
u.phone,
u.delete,
u.identiType,
u.IDCardNo,
DATE_FORMAT(u.Time, '%Y-%m-%d %T' ) AS Time,
u.sex,
u.birthday,
u.hospitalId,
u.uniqueId,
u.patientRegNo,
u.patientId,
u.phoneSelf,
u.medicalCardNo,
u.medicalPaySign,
u.type,
u.cardEncrypt,
u.isDefault,
u.qrCodeUrl,
u.qrCodeBase64,
u.healthStatus,
u.patientCard,
u.platform,
u.channel,
DATE_FORMAT( u.update_time, '%Y-%m-%d %T' ) AS update_time,
e.id AS e_id,
e.username AS e_username,
e.phone AS e_phone,
e.channel AS e_channel,
e.area AS e_area,
DATE_FORMAT( e.add_time, '%Y-%m-%d %T' ) AS e_add_time,
e.state AS e_state
FROM tableA u
LEFT JOIN table b e
ON u.channel = e.channel
AND e.hospitalId = u.hospitalId
WHERE u.update_time >= :sql_last_value
java的mysql包默认查询的时候,会将是将格式查出来是:2020-08-28T01:01:50.000Z这种格式,但是我们又不能用这种格式,所以必须将时间格式在select中进行格式化转换。这样logstash查出来的格式就是:2020:08:28 01:01:50这种格式。
接下来就可以在ES中建立索引,并进行字段的映射,如果你没进行字段映射的话,logstash会自动帮你以默认字段格式写入到ES中。
开启logstash:/usr/local/logstash/bin/logstash -f /usr/local/logstash/config/jdbc.conf
开启后查看logstash的日志,看是否开启成功。不过你也可能开启成功,但是日志中有WARN的警告,这时候你就要当心了,说明有数据没有成功写入到ES中。我在排错的时候,就是通过这里找出了很多问题。
注意:/usr/local/logstash/lastrun/.logstash_jdbc_last_run,这个文件会记录你上次查询的时间,下次查询的时候会以这个文件内的时间为基准往下查询。如果你想从头开始查,就需要将Logstash关闭然后删除它。
写在后面的内容:
要明白你要将什么数据存入ES中,通过这种方式你是将SELECT出来的数据存储到ES中的。所以你在往ES里面存数据的时候就要考虑好,你要查询哪些数据,将这些数据写入到ES中。是否你的查询条件能够满足你的要求。