logstash采集mysql数据同步到es中时间字段相差8小时的解决办法

最近在做的项目中,需要将MySQL中的数据通过logstash同步至elasticsearch,但是同步后发现es中的文档时间字段不对了,统统比实际时间提前8小时。

查了资料发现,这是由于logstash在获取时区的时候,默认获取的是UTC默认时间,同时elasticsearch在创建索引的时候,统一使用UTC时间,因为中国使用的为东8时区,源数据和实际创建的索引数据会相差8个小时。

所以如果获取的是UTC时间,会导致我们取es文档时间字段不符合实际,其实可以通过修改 logstash-db-sync.conf 同步配置文件来解决时间差的问题。

以下是我自己项目中用的配置文件,项目上logstash用的是6.8.4版本,该文件位于/usr/local/logstash-6.8.4/sync目录下。

 

input {
    jdbc {
        # 设置 MySql/MariaDB 数据库url以及数据库名称
        jdbc_connection_string => "jdbc:mysql://10.1.1.129:3306/ctscm_uat?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai"
        # 用户名和密码
        jdbc_user => "ctscm_uat"
        jdbc_password => "han2018chen"
        # 数据库驱动所在位置,可以是绝对路径或者相对路径
        jdbc_driver_library => "/usr/local/logstash-6.8.4/sync/mysql-connector-java-8.0.19.jar"
        # 驱动类名
        jdbc_driver_class => "com.mysql.jdbc.Driver"
        # 开启分页
        jdbc_paging_enabled => "true"
        # 分页每页数量,可以自定义
        jdbc_page_size => "1000"
        # 执行的sql文件路径
        # statement_filepath => "/usr/local/logstash-6.8.4/sync/sync.sql"
        statement => "SELECT * FROM contract WHERE update_time > :sql_last_value"
        # 设置定时任务间隔  含义:分、时、天、月、年,全部为*默认含义为每分钟跑一次任务
        schedule => "* * * * *"
        # 索引类型
        type => "contract"
        # 是否开启记录上次追踪的结果,也就是上次更新的时间,这个会记录到 last_run_metadata_path 的文件
        use_column_value => true
        # 记录上一次追踪的结果值
        last_run_metadata_path => "/usr/local/logstash-6.8.4/sync/track_time"
        
        # 如果 use_column_value 为true, 配置本参数,追踪的 column 名,可以是自增id或者时间
        tracking_column => "update_time"
        # tracking_column 对应字段的类型
        tracking_column_type => "timestamp"
        # 是否清除 last_run_metadata_path 的记录,true则每次都从头开始查询所有的数据库记录
        clean_run => false
        # 数据库字段名称大写转小写
        lowercase_column_names => false
        
        jdbc_default_timezone => "Asia/Shanghai"
        
        #使用本地时区为local,否则sql_last_value如果是timestamp,时间会提前8小时
#值可以是任何的:utc,local,默认值为 "utc" plugin_timezone
=> "local" } } filter { # 因为时区问题需要修正时间 ruby { code => "event.set('timestamp', event.get('@timestamp').time.localtime + 8*60*60)" } ruby { code => "event.set('@timestamp',event.get('timestamp'))" } mutate { remove_field => ["timestamp"] } # 因为时区问题需要修正时间 ruby { code => "event.set('create_time', event.get('create_time').time.localtime + 8*60*60)" } # 因为时区问题需要修正时间 ruby { code => "event.set('update_time', event.get('update_time').time.localtime + 8*60*60)" } # 转换成日期格式 ruby { code => "event.set('start_date', event.timestamp.time.localtime.strftime('%Y-%m-%d'))" } # 转换成日期格式 ruby { code => "event.set('end_date', event.timestamp.time.localtime.strftime('%Y-%m-%d'))" } # 转换成日期格式 ruby { code => "event.set('sign_date', event.timestamp.time.localtime.strftime('%Y-%m-%d'))" } } output { elasticsearch { # ES的IP地址及端口 hosts => ["10.1.2.32:9200"] # 同步的索引名 index => "ctscm" # 设置_docID和数据相同 document_id => "%{contract_id}" } # 日志输出 stdout { codec => json_lines } }

 

说明:

主要是以下几个参数要正确配置

1.jdbc_connection_string配置上使用CTT(Asia/shanghai)时间

jdbc_connection_string => "jdbc:mysql://192.168.0.145:3306/db_example?useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT"

或者

jdbc_connection_string => "jdbc:mysql://192.168.0.145:3306/db_example?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/shanghai"

 

2.新增时区参数

  • jdbc_default_timezone

值类型为字符串,此设置没有默认值。

时区转换。Logstash(和Elasticsearch)期望时间戳以UTC术语表示。如果您的数据库记录了相对于另一个时区的时间戳,则将记录该数据库的时区,然后将此设置设置为数据库使用的时区。但是,由于SQL不允许在时间戳字段中提供时区数据,因此我们无法逐条记录地进行计算。此插件将以ISO8601格式的相对UTC时间自动将您的SQL时间戳字段转换为Logstash时间戳。

使用此设置将手动分配指定的时区偏移,而不是使用本地计算机的时区设置。

jdbc_default_timezone => "Asia/Shanghai"
  • plugin_timezone
    值可以是任何的:utc,local,默认值为 "utc"。

如果您希望此插件将时间戳偏移到UTC以外的时区,则可以将此设置设置为local,插件将使用OS时区进行偏移调整。

注意:当指定plugin_timezone和/或时jdbc_default_timezone,偏移量调整在两个地方进行,如果sql_last_value是时间戳,并且在语句中用作参数,则偏移量调整将从插件时区到数据时区,并且在处理记录时,时间戳从数据库时区偏移到插件时区。如果您的数据库时区为UTC,则无需设置这些设置中的任何一个。

 

posted @ 2020-08-21 18:09  gaopengpy  阅读(4040)  评论(0编辑  收藏  举报