flink写入hive的时区问题
概述
本文主要對[3]進行復現和闡述
環境版本
| 組件 | 版本 |
| Hadoop | 3.1.2 |
| Hive | 2.3.6 |
| Flink | 1.12.0 |
| Zookeeper | 3.6.0 |
#####################################################################################################################
本文流水線觸發條件
我們目前接觸到的有下面兩種:
| 環境 | 觸發計算條件(為了方便論述,這里忽略遲到數據等) |
| watermark寫入hive分區 | watermark?>?toMills(partTime)?+?commitDelay |
| watermark與window計算[4] | watermark >= window_end_time? |
本文論述的是第一種
百度上常見的是表格中第二種
#####################################################################################################################
時區機制
Flink源碼中的toMills并不是jdk中的
java.time.Duration.toMillis()
兩者不是一個東西,不要搞混.
?
上述表格中的toMills會把傳入的創建hive分區的時間戳partTime誤當做UTC時間(作為輸入),
然后+8小時轉化為東八區的時間toMills(partTime).
整理如下:
| ? | 使用的數據來自 | 被Flink誤當做 | 進一步轉化為 |
| watermark | 東八區 | UTC時區 | 無 |
| partTime(創建hive分區的時間) | 東八區 | UTC時區 | toMills(partTime)=partTime+8:00 |
所以這就尷尬了,時區失配,導致無案發觸發Partition Commit(講人話就是Flink已經寫入Sink的數據在Hive中看不到).
場景舉例:
16:23:48我新建了一個hive表(當然也就等于是新建了hive分區)
16:26:25時我去hive表格中查看數據,結果一條都沒有.
為啥呢?
根據上述表格,我建立hive中表格fs_table的時間,被flink加了8小時,需要當前寫入的數據的時間戳生成的watermark
大于0:23:48(16:23:48+8:00)以后才能看到
因為沒有滿足表格中的水位線觸發條件,所以無法觸發Hive的Partition Commit,
最終導致一個奇怪的現象:
Flink明明已經寫入Sink的數據,在Hive的fs_table中看不到
#####################################################################################################################
實驗驗證
口說無憑,我們來做一個對照實驗
| 步驟 | 實驗組 | 對照組 | 備注 |
| ① | 創建Hive表格fs_table | 創建Hive表格fs_table | ? |
| ② | 運行StreamingWriteHive_bug.java | 運行StreamingWriteHive.java | 對照組的水印加了8小時 |
| ③ | select * from fs_table; | select * from fs_table; | ? |
| ④ | Hive的fs_table中無結果 | Hive的fs_table中一大堆結果 | ? |
?
#####################################################################################################################
?
Reference:
[1]Hive分區和分桶區別
[2]重要|flink的時間及時區問題解決
[3]flink教程-flink 1.11 使用sql將流式數據寫入hive
[4]Flink EventTime和Watermarks原理結合代碼分析(轉載+解決+精簡記錄)
[5]踩坑記 | Flink 天級別窗口中存在的時區問題
[6]Hive創建二級分區表
總結
以上是生活随笔為你收集整理的flink写入hive的时区问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 和平精英哥斯拉在哪
- 下一篇: AppendStream和Retract