Elasticsearch 滞后8个小时等时区问题,一网打尽!

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: 1、实战问题如下都是实战环节遇到的问题:logstash谁解决过时区问题,mysql是东八区shanghai 但是这玩意读完存到es就少了8小时?目前索引会比真正时间晚8小时,导致8点前的日志写到昨天索引里,大佬们有招吗?问一下 logstash输出日志到本地文件中,按照小时生成索引,但是他这边的时区是utc,生成的时间和北京时间少8小时,这一块大佬们是咋操作的?......从浏览器kibana那里看timestamp时间戳变成了utc的时区?上面的问题都涉及到时区问题,涉及到数据的同步(logstash)、写入、检索(elasticsearch)、可视化(kibana)

2、时区问题拆解

我们通过如下几个问题展开拆解。


2.1 Elasticserch 默认时区是?能改吗?

官方文档强调:在 Elasticsearch 内部,日期被转换为 UTC时区并存储为一个表示自1970-01-01 00:00:00  以来经过的毫秒数的值。


Internally, dates are converted to UTC (if the time-zone is specified) and stored as a long number representing milliseconds-since-the-epoch.


https://www.elastic.co/guide/en/elasticsearch/reference/current/date.html


Elasticsearch date 类型默认时区:UTC。


正如官方工程师强调(如下截图所示):Elasticsearch 默认时区不可以修改。

image.png

https://discuss.elastic.co/t/index-creates-in-different-timezone-other-than-utc/148941


但,我们可以“曲线救国”,通过:


ingest pipeline 预处理方式写入的时候修改时区;


logstash filter 环节做时区转换;


查询时指定时区;


聚合时指定时区。


2.2 Kibana 默认时区是?能改吗?

kibana 默认时区是浏览器时区。可以修改,修改方式如下:


Stack Management -> Advanced Settings ->Timezone for data formatting.

image.png

2.3 Logstash 默认时区是?能改吗?

默认:UTC。

可以通过中间:filter 环节进行日期数据处理,包括:转时区操作。

小结一下:

image.png

logstash 默认 UTC 时区。


Elasticsearch 默认 UTC 时区。


Kibana 默认浏览器时区,基本我们用就是:东八区。


如果基于Mysql 同步数据,Mysql 数据是:东八区。


我们看一下东8区百度百科定义:东八区(UTC/GMT+08:00)是比世界协调时间(UTC)/格林尼治时间(GMT)快8小时的时区,理论上的位置是位于东经112.5度至127.5度之间,是东盟标准的其中一个候选时区。当格林尼治标准时间为0:00时,东八区的标准时间为08:00。


通过上面的定义,能加深对 logstash 同步数据后,数据滞后8小时的理解。


3、时区问题解决方案

基于上面的分析,如何解决时区问题呢?


由于 kibana 支持手动修改时区,不在下文讨论 的范围之内。实战项目中,自己根据业务需求修改即可。


那么问题就转嫁为:写入的时候转换成给定时区(如:东8区)就可以了。


3.1 方案一:ingest 预处理为东8区时区

步骤 1:定义预处理管道:chage_utc_to_asiash(名称自己定义即可)。


在该管道中实现了时区转换。


步骤 2:创建索引同时指定缺省管道:chage_utc_to_asiash。


步骤 3:写入数据(单条或 bulk 批量均可)


PUT _ingest/pipeline/chage_utc_to_asiash

{

 "processors": [

   {

     "date" : {

       "field" : "my_time",

       "target_field": "my_time",

       "formats" : ["yyyy-MM-dd HH:mm:ss"],

       "timezone" : "Asia/Shanghai"

     }

   }

 ]

}

PUT my-index-000001

{

 "settings": {

   "default_pipeline": "chage_utc_to_asiash"

 },

 "mappings": {

   "properties": {

     "my_time": {

       "type": "date"

     }

   }

 }

}

PUT my-index-000001/_doc/1

{

 "my_time": "2021-08-09 08:07:16"

}

当写入数据后,执行检索时,kibana dev tool 返回结果如下:


"hits" : [

     {

       "_index" : "my-index-000001",

       "_type" : "_doc",

       "_id" : "1",

       "_score" : 1.0,

       "_source" : {

         "my_time" : "2021-08-09T08:07:16.000+08:00"

       }

     }

   ]

最明显的特征是:多了+08:00 时区(东8区)标志。


然后,我们用:kibana discover可视化展示一下:

image.png

上图中,kibana 采用默认浏览器时区。


如果不做上面的 ingest 预处理实现,会怎么样呢?大家如果实现过,肯定会感触很深。


需要我们在kibana中切换时间范围,才能找到之前写入的数据。


ingest 预处理时区的好处:方便、灵活的实现了写入数据的时区转换。


3.2 方案二:logstash 中间 filter 环节处理

拿真实同步案例讲解一下时区处理:


数据源端:Mysql;


数据目的端:Elasticsearch;


同步方式:logstash,本质借助:logstash_input_jdbc 插件同步;


时区处理:logstash filter 环节 ruby 脚本处理。


如下只给出了中间 filter 环节的脚本:


filter {

ruby {

  code => "event.set('timestamp', event.get('publish_time').time.localtime + 8*60*60)"

}

ruby {

  code => "event.set('publish_time',event.get('timestamp'))"

}

mutate {

  remove_field => ["timestamp"]

}

}

三行脚本含义,解释如下:


第一行:将 publish_time 时间加 8 小时处理,赋值给 timestamp。


publish_time  到了 logstash 已转成了 UTC 时区了。


timestamp 类似似 C 语言中的交换两个数函数中的 temp 临时变量。


第二行:将 timestamp 时间赋值给 publish_time。


第三行:删除中转字段:timestamp。


源数据Mysql 效果:

image.png

image.png

如上两个截图,对比一下区别:


publish_time 做了时区处理,两者时间已一致,都是东 8 区。


update_time 未做时间处理,写入Elasticsearch 后由东8区时间 10:57:31 转为UTC时区时间 02:57:31,少了8小时。


4、检索和聚合的时候指定时区

假定我们写入ES前未做时区处理(实战环节常有的场景),但是检索或者聚合的时候想做时区处理可以吗?


可以的,具体实现方式如下:


POST testindex/_search?pretty

{

 "query": {

   "range": {

     "date": {

       "gte": "2020-01-01 00:00:00",

       "lte": "2020-01-03 23:59:59",

       "format": "yyyy-MM-dd HH:mm:ss",

       "time_zone": "+08:00"

     }

   }

},

 "size": 0,

 "aggs": {

   "per_day": {

     "date_histogram": {

       "calendar_interval": "day",

       "field": "date",

       "time_zone": "+08:00"

     }

   }

 }

}

如上示例中,整合了检索和聚合,有两个要点:


要点1:range query 中指定时区检索。


要点2:data_histogram 聚合中指定时区聚合。


5、小结

数据写入时间不一致、数据滞后8小时等时区问题的本质是:各个处理端时区不一致,写入源的时区、Kibana默认是本地时区(如中国为:东8区时区),而 logstash、Elasticsearch 是UTC时区。

本文给出了两种写入前预处理的解决方案,方案一:基于管道预处理;方案二:基于logstash filter 中间环节过滤。两种方案各有利弊,预处理管道相对更轻量级,实战选型建议根据业务需求。本文最后指出在检索和聚合环节使用时区处理方式。


大家在实战中有没有遇到时区问题,是怎么解决的呢?欢迎大家留言交流。


参考

https://t.zsxq.com/2nYnq76


推荐

1、Elasticsearch 7.X 进阶实战私训课


2、如何系统的学习 Elasticsearch ?


3、全网首发!《 Elasticsearch 最少必要知识教程 V1.0 》低调发布


4、从实战中来,到实战中去——Elasticsearch 技能更快提升方法论


5、刻意练习 Elasticsearch 10000 个小时,鬼知道经历了什么?!


6、干货 | Logstash自定义正则表达式ETL实战


7、干货 | Logstash Grok 数据结构化ETL实战

相关实践学习
使用阿里云Elasticsearch体验信息检索加速
通过创建登录阿里云Elasticsearch集群,使用DataWorks将MySQL数据同步至Elasticsearch,体验多条件检索效果,简单展示数据同步和信息检索加速的过程和操作。
ElasticSearch 入门精讲
ElasticSearch是一个开源的、基于Lucene的、分布式、高扩展、高实时的搜索与数据分析引擎。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr(也是基于Lucene)。 ElasticSearch的实现原理主要分为以下几个步骤: 用户将数据提交到Elastic Search 数据库中 通过分词控制器去将对应的语句分词,将其权重和分词结果一并存入数据 当用户搜索数据时候,再根据权重将结果排名、打分 将返回结果呈现给用户 Elasticsearch可以用于搜索各种文档。它提供可扩展的搜索,具有接近实时的搜索,并支持多租户。
相关文章
|
存储 Java Spring
五分钟带你玩转Elasticsearch(十四)企业实战——springboot与es时区相差8小时解决方案
五分钟带你玩转Elasticsearch(十四)企业实战——springboot与es时区相差8小时解决方案
826 0
五分钟带你玩转Elasticsearch(十四)企业实战——springboot与es时区相差8小时解决方案
|
4月前
|
存储 安全 数据管理
如何在 Rocky Linux 8 上安装和配置 Elasticsearch
本文详细介绍了在 Rocky Linux 8 上安装和配置 Elasticsearch 的步骤,包括添加仓库、安装 Elasticsearch、配置文件修改、设置内存和文件描述符、启动和验证 Elasticsearch,以及常见问题的解决方法。通过这些步骤,你可以快速搭建起这个强大的分布式搜索和分析引擎。
116 5
|
5月前
|
存储 JSON Java
elasticsearch学习一:了解 ES,版本之间的对应。安装elasticsearch,kibana,head插件、elasticsearch-ik分词器。
这篇文章是关于Elasticsearch的学习指南,包括了解Elasticsearch、版本对应、安装运行Elasticsearch和Kibana、安装head插件和elasticsearch-ik分词器的步骤。
444 0
elasticsearch学习一:了解 ES,版本之间的对应。安装elasticsearch,kibana,head插件、elasticsearch-ik分词器。
|
6月前
|
NoSQL 关系型数据库 Redis
mall在linux环境下的部署(基于Docker容器),Docker安装mysql、redis、nginx、rabbitmq、elasticsearch、logstash、kibana、mongo
mall在linux环境下的部署(基于Docker容器),docker安装mysql、redis、nginx、rabbitmq、elasticsearch、logstash、kibana、mongodb、minio详细教程,拉取镜像、运行容器
mall在linux环境下的部署(基于Docker容器),Docker安装mysql、redis、nginx、rabbitmq、elasticsearch、logstash、kibana、mongo
|
7月前
|
数据可视化 Docker 容器
一文教会你如何通过Docker安装elasticsearch和kibana 【详细过程+图解】
这篇文章提供了通过Docker安装Elasticsearch和Kibana的详细过程和图解,包括下载镜像、创建和启动容器、处理可能遇到的启动失败情况(如权限不足和配置文件错误)、测试Elasticsearch和Kibana的连接,以及解决空间不足的问题。文章还特别指出了配置文件中空格的重要性以及环境变量中字母大小写的问题。
一文教会你如何通过Docker安装elasticsearch和kibana 【详细过程+图解】
|
7月前
|
JSON 自然语言处理 数据库
Elasticsearch从入门到项目部署 安装 分词器 索引库操作
这篇文章详细介绍了Elasticsearch的基本概念、倒排索引原理、安装部署、IK分词器的使用,以及如何在Elasticsearch中进行索引库的CRUD操作,旨在帮助读者从入门到项目部署全面掌握Elasticsearch的使用。
|
8月前
|
Docker 容器
docker desktop安装es并连接elasticsearch-head:5
以上就是在Docker Desktop上安装Elasticsearch并连接Elasticsearch-head:5的步骤。
308 2
|
7月前
|
Ubuntu Oracle Java
如何在 Ubuntu VPS 上安装 Elasticsearch
如何在 Ubuntu VPS 上安装 Elasticsearch
80 0
|
7月前
|
存储 Ubuntu Oracle
在Ubuntu 14.04上安装和配置Elasticsearch的方法
在Ubuntu 14.04上安装和配置Elasticsearch的方法
72 0
|
7月前
|
存储 安全 Java
在CentOS 7上安装和配置Elasticsearch的方法
在CentOS 7上安装和配置Elasticsearch的方法
442 0