【elasticsearch】数据早8小时Or晚8小时,你知道为何吗,附解决方案

前言
  • 这篇文章,不会解释什么是本初子午线,只想以作实验的方式来理解数据差8小时的问题。下面就先说结论,再来谈原理。
解决方案
  • 想必你们都很清楚:中国标准时间= UTC + 8小时。
  • 那么全部和时区有关的地方,都有可能成为“凶手”。
若是是java写入es怎么解决时区问题?
  • 若是你使用java程序来写入es,我推荐你写入带T的时间字符串。提供程序以下:
/**
     * String timeZoneConvert = timeZoneConvert(
     *              new Date().getTime()
     *              , "yyyy-MM-dd'T'HH:mm:ss.SSSZ",
     *              "Asia/Shanghai");
     *              
     * @param date 毫秒
     * @param pattern format时间格式
     * @param timeZone 时区
     * @return 如:2019-12-30T16:32:07.616+0800
     */
    public static String timeZoneConvert(Long date,String pattern,String timeZone){
        SimpleDateFormat simpleDateFormat=new SimpleDateFormat(pattern);
        simpleDateFormat.setTimeZone(TimeZone.getTimeZone(timeZone));
        return simpleDateFormat.format(date);
    }
  • 为何?由于java有些api是带时区的。如new Date().getTime()默认是东八区,System.currentTimeMillis() 依赖于当前时区来计算毫秒值。
  • 虽然上述例子依赖了这个api,可是这里只是想说明java程序所处的环境的时区一样有影响,特别是这个程序极可能是容器化的,那么可能又和系统镜像的时区有关了。
若是是logstash写入es怎么解决时区问题?
  • 建议input的时间源数据就是带上时区的字符串,不然就要进行转换。
mutate{
        gsub => [
           "time", "[+]", "T"
        ]
      } 
        mutate{
      replace => ["time","%{time}+08:00"]
      }

或是:java

date {
    match => ["timestamp", "yyyy-MM-dd HH:mm:ss"]
    target => "my_timestamp"
    timezone => "+08:00"
}
若是是语句聚合es数据怎么解决时区问题?
  • 指定time_zone配置
"aggs": {
    "by_day": {
      "date_histogram": {
        "field":     "date",
        "interval":  "day",
        "time_zone": "Asia/Shanghai"
      }
    }
  }
kibana显示怎么解决时区问题?
  • Management>>Advanced Settings设置时区。

file

原理&试验
Es中和时间相关的数据类型
  • 通常在写入es的时候,会以json的方式写入,因为json中没有日期数据类型,因此日期如何存储显示,是由es决定的,也就是说es会进行隐式的类型转换。
  • es中的日期能够是:
  • 格式化日期的字符串,例如"2019-12-30"或"2019/12/30 12:10:30"。
  • 毫秒值。
  • 秒值。
试验
  • 这里以不一样的时间api准备了一些数据写入es,让咱们来看看会发生什么。

file

  • 数据打印出来以下:
{
    "AsiaTime":"2019-12-30T16:32:07.616+0800",
    "newDateTime":1577694727581,
    "localTimeNow":"2019-12-30T16:32:07.615",
    "systemCurrentTimeMilis":1577694727581,
    "newDate":1577694727581
}
  • 默认不设置索引模板的状况,写入es后,咱们发现带 时区‘T’的数据类型为date。
    filejson

  • 接下来,咱们将轮流设置这两个字段为kibana的时间搜索字段,看看会发生什么。api

两个实验对时区的思考
  • 实验一:以localTimeNow作时间搜索字段,显示比数据时间晚了8小时。
    file3d

  • 实验二:以AsiaTime作时间搜索字段,显示比数据时间早了8小时。
    filecode

  • 如何解释?固然是因为时区影响。记住这几个点,就很好理解了:
    • es内部,时间会转换成UTC格式,实际按照数值型存储。能够理解为毫秒数。
    • kibana会经过获取时区配置显示时间到界面。

首先来讲实验一,为何kibana上显示的时比数据时间多8个小时呢?明明是30号的数据,愣是跑到31号去了?orm

  • 这条数据 "localTimeNow":"2019-12-30T16:32:07.615"。带时区T,默认是UTC时区,
    而kibana获取的时区配置是Asia/Shanghai,为东8区,至关于在原来的时间上加上8个小时显示,因此跑到31号去了。
    用大腿想一下,你确定知道,这种状况下若是把kibana时区设置为UTC,固然数据就显示正常啦。blog

  • 再来讲实验二, "AsiaTime":"2019-12-30T16:32:07.616+0800,因为上面设置了当前kibana时区为UTC,数据带东八区的时区,因此晚了8小时。同理将kibana时区改成东八区后显示正常。索引

总结

  • 时区问题,万变不离其宗,搞清楚原理后,任意数据怎么变化,咱们都可以有方法应对,但愿这篇文章对你有所帮助。开发

    欢迎来公众号【侠梦的开发笔记】 一块儿交流进步字符串

相关文章
相关标签/搜索