【elasticsearch】資料早8小時Or晚8小時,你知道為什麼嗎,附解決方案
阿新 • • 發佈:2019-12-30
前言
- 這篇文章,不會解釋什麼是本初子午線,只想以做實驗的方式來理解資料差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"] }
或是:
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設定時區。
原理&試驗
Es中和時間相關的資料型別
- 一般在寫入es的時候,會以json的方式寫入,由於json中沒有日期資料型別,所以日期如何儲存顯示,是由es決定的,也就是說es會進行隱式的型別轉換。
- es中的日期可以是:
- 格式化日期的字串,例如"2019-12-30"或"2019/12/30 12:10:30"。
- 毫秒值。
- 秒值。
試驗
- 這裡以不同的時間api準備了一些資料寫入es,讓我們來看看會發生什麼。
- 資料打印出來如下:
{
"AsiaTime":"2019-12-30T16:32:07.616+0800",
"newDateTime":1577694727581,
"localTimeNow":"2019-12-30T16:32:07.615",
"systemCurrentTimeMilis":1577694727581,
"newDate":1577694727581
}
預設不設定索引模板的情況,寫入es後,我們發現帶 時區‘T’的資料型別為date。
接下來,我們將輪流設定這兩個欄位為kibana的時間搜尋欄位,看看會發生什麼。
兩個實驗對時區的思考
實驗一:以localTimeNow做時間搜尋欄位,顯示比資料時間晚了8小時。
實驗二:以AsiaTime做時間搜尋欄位,顯示比資料時間早了8小時。
- 如何解釋?當然是由於時區影響。記住這幾個點,就很好理解了:
- es內部,時間會轉換成UTC格式,實際按照數值型儲存。可以理解為毫秒數。
- kibana會通過獲取時區配置顯示時間到介面。
首先來說實驗一,為什麼kibana上顯示的時比資料時間多8個小時呢?明明是30號的資料,愣是跑到31號去了?
這條資料 "localTimeNow":"2019-12-30T16:32:07.615"。帶時區T,預設是UTC時區,
而kibana獲取的時區配置是Asia/Shanghai,為東8區,相當於在原來的時間上加上8個小時顯示,所以跑到31號去了。
用大腿想一下,你肯定知道,這種情況下如果把kibana時區設定為UTC,當然資料就顯示正常啦。再來說實驗二, "AsiaTime":"2019-12-30T16:32:07.616+0800,由於上面設定了當前kibana時區為UTC,資料帶東八區的時區,所以晚了8小時。同理將kibana時區改為東八區後顯示正常。
總結
時區問題,萬變不離其宗,搞清楚原理後,任意資料怎麼變化,我們都能夠有方法應對,希望這篇文章對你有所幫助。
歡迎來公眾號【俠夢的開發筆記】 一起交流進步