摘要:最近将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 
替换成功的话,会出现下面如图显示

mysql数据迁移到goldendb Mysql数据迁移到es_mysql数据迁移到goldendb

 

 

#采用下面的语句安装插件 
/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中。是否你的查询条件能够满足你的要求。