日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

东八区转为0时区_踩坑记 | Flink 天级别窗口中存在的时区问题

發布時間:2025/3/19 编程问答 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 东八区转为0时区_踩坑记 | Flink 天级别窗口中存在的时区问题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?

本系列每篇文章都是從一些實際的 case 出發,分析一些生產環境中經常會遇到的問題,拋磚引玉,以幫助小伙伴們解決一些實際問題。本文介紹 Flink 時間以及時區問題,分析了在天級別的窗口時會遇到的時區問題,如果對小伙伴有幫助的話,歡迎點贊 + 再看~

?

本文主要分為兩部分:

第一部分(第 1 - 3 節)的分析主要針對 flink,分析了 flink 天級別窗口的中存在的時區問題以及解決方案。

第二部分(第 4 節)的分析可以作為所有時區問題的分析思路,主要以解決方案中的時區偏移量為什么是加 8 小時為案例做了通用的深度解析。

為了讓讀者能對本文探討的問題有一個大致了解,本文先給出問題 sql,以及解決方案。后文給出詳細的分析~

1.問題以及解決方案

問題 sql

sql 很簡單,用來統計當天累計 uv。

---------------?偽代碼?---------------
INSERT?INTO
??kafka_sink_table
SELECT
??--?窗口開始時間
??CAST(
????TUMBLE_START(proctime,?INTERVAL?'1'?DAY)?AS?bigint
??)?AS?window_start,
??--?當前記錄處理的時間
??cast(max(proctime)?AS?BIGINT)?AS?current_ts,
??--?每個桶內的?uv
??count(DISTINCT?id)?AS?part_daily_full_uv
FROM
??kafka_source_table
GROUP?BY
??mod(id,?bucket_number),
??--?bucket_number?為常數,根據具體場景指定具體數值
??TUMBLE(proctime,?INTERVAL?'1'?DAY)
---------------?偽代碼?---------------

你是否能一眼看出這個 sql 所存在的問題?(PS:數據源以及數據匯時區都為東八區)

「沒錯,天級別窗口所存在的時區問題,即這段代碼統計的不是樓主所在東八區一整天數據的 uv,這段代碼統計的一整天的范圍在東八區是第一天早 8 點至第二天早 8 點。」

解決方案

樓主目前所處時區為東八區,解決方案如下:

---------------?偽代碼?---------------
CREATE?VIEW?view_table?AS
SELECT
???id,
???--?通過注入時間解決
???--?加上東八區的時間偏移量,設置注入時間為時間戳列
???CAST(CURRENT_TIMESTAMP?AS?BIGINT)?*?1000?+?8?*?60?*?60?*?1000?as?ingest_time
FROM?
???source_table;

INSERT?INTO
??target_table
SELECT
??CAST(
????TUMBLE_START(ingest_time,?INTERVAL?'1'?DAY)?AS?bigint
??)?AS?window_start,
??cast(max(ingest_time)?AS?BIGINT)?-?8?*?3600?*?1000?AS?current_ts,
??count(DISTINCT?id)?AS?part_daily_full_uv
FROM
??view_table
GROUP?BY
??mod(id,?1024),
???--?根據注入時間劃分天級別窗口
??TUMBLE(ingest_time,?INTERVAL?'1'?DAY)
---------------?偽代碼?---------------

通過上述方案,就可以將統計的數據時間范圍調整為東八區的今日 0 點至明日 0 點。下文詳細說明整個需求場景以及解決方案的實現和分析過程。

2.需求場景以及實現方案

需求場景

coming,需求場景比較簡單,就是消費上游的一個埋點日志數據源,根據埋點中的 id 統計當天 0 點至當前時刻的累計 uv,按照分鐘級別產出到下游 OLAP 引擎中進行簡單的聚合,最后在 BI 看板進行展示,沒有任何維度字段(感動到哭?)。

數據鏈路以及組件選型

客戶端用戶行為埋點日志 -> logServer -> kafka -> flink(sql) -> kafka -> druid -> BI 看板。

實現方案以及具體的實現方式很多,這次使用的是 sql API。

flink sql schema

source 和 sink 表 schema 如下(只保留關鍵字段):

---------------?偽代碼?---------------
CREATE?TABLE?kafka_sink_table?(
??--?天級別窗口開始時間
??window_start?BIGINT,
??--?當前記錄處理的時間
??current_ts?BIGINT,
??--?每個桶內的?uv(處理過程對?id?進行了分桶)
??part_daily_full_uv?BIGINT
)?WITH?(
?--?...?
);

CREATE?TABLE?kafka_source_table?(
??--?...?
??--?需要進行?uv?計算的?id
??id?BIGINT,
??--?處理時間
??proctime?AS?PROCTIME()
)?WITH?(
??--?...?
);
---------------?偽代碼?---------------

flink sql transform

---------------?偽代碼?---------------
INSERT?INTO
??kafka_sink_table
SELECT
??--?窗口開始時間
??CAST(
????TUMBLE_START(proctime,?INTERVAL?'1'?DAY)?AS?bigint
??)?AS?window_start,
??--?當前記錄處理的時間
??cast(max(proctime)?AS?BIGINT)?AS?current_ts,
??--?每個桶內的?uv
??count(DISTINCT?id)?AS?part_daily_full_uv
FROM
??kafka_source_table
GROUP?BY
??mod(id,?bucket_number),
??--?bucket_number?為常數,根據具體場景指定具體數值
??TUMBLE(proctime,?INTERVAL?'1'?DAY)
---------------?偽代碼?---------------

使用 early-fire 機制(同 DataStream API 中的 ContinuousProcessingTimeTrigger),并設定觸發間隔為 60 s。

在上述實現 sql 中,我們對 id 進行了分桶,那么每分鐘輸出的數據條數即為 bucket_number 條,最終在 druid 中按照分鐘粒度將所有桶的數據進行 sum 聚合,即可得到從當天 0 點累計到當前分鐘的全量 uv。

時區問題

?

18???:

「頭文字 ∩ 技術小哥哥」:使用 sql,easy game,閑坐摸魚...

「頭文字 ∩ 技術小哥哥」:等到 「00:00」 時,發現指標還在不停地往上漲,難道是 sql 邏輯錯了,不應該啊,試過分鐘,小時級別窗口都木有這個問題

「頭文字 ∩ 技術小哥哥」:摳頭ing,算了,稍后再分析這個問題吧,現在還有正事要干?

「頭文字 ∩ 技術小哥哥」:到了早上,瞅了一眼配置的時間序列報表,發現在 「08:00」 點的時候指標歸零,重新開始累計。woc,想法一閃而過,東八區?(當時為啥沒 format 下 sink 數據中的 window_start...)

?

3.問題定位

問題說明

flink 在使用時間的這個概念的時候是基于 java 時間紀元(即格林威治 1970/01/01 00:00:00,也即 Unix 時間戳為 0)概念的,窗口對齊以及觸發也是基于 java 時間紀元[1]

問題場景復現

可以通過直接查看 sink 數據的 window_start 得出上述結論。

但為了還原整個過程,我們按照如下 source 和 sink 數據進行整個問題的復現:

source 數據如下:

sink 數據(「為了方便理解,直接按照 druid 聚合之后的數據展示」):

從上述數據可以發現,天級別窗口「開始時間」在 UTC + 8(北京)的時區是每天早上 8 點,即 UTC + 0(格林威治)的凌晨 0 點。

「下文先給出解決方案,然后詳細解析各個時間以及時區概念~」

解決方案

  • 「框架層面解決」:Blink Planner 支持時區設置[2]
  • 「sql層面解決」:從 sql 實現層面給出解決方案

sql 層面解決方案

---------------?偽代碼?---------------
CREATE?VIEW?view_table?AS
SELECT
???id,
???--?通過注入時間解決
???--?加上東八區的時間偏移量,設置注入時間為時間戳列
???CAST(CURRENT_TIMESTAMP?AS?BIGINT)?*?1000?+?8?*?60?*?60?*?1000?as?ingest_time
FROM?
???source_table;

INSERT?INTO
??target_table
SELECT
??CAST(
????TUMBLE_START(ingest_time,?INTERVAL?'1'?DAY)?AS?bigint
??)?AS?window_start,
??cast(max(ingest_time)?AS?BIGINT)?-?8?*?3600?*?1000?AS?current_ts,
??count(DISTINCT?id)?AS?part_daily_full_uv
FROM
??view_table
GROUP?BY
??mod(id,?1024),
???--?根據注入時間劃分天級別窗口
??TUMBLE(ingest_time,?INTERVAL?'1'?DAY)
---------------?偽代碼?---------------

我目前所屬的時區是東八區(北京時間),通過上述 sql,設置注入時間,并對注入時間加上 8 小時的偏移量進行天級別窗口的劃分,就可以對此問題進行解決(也可以在 create table 時,在 schema 中根據計算列添加對應的注入時間戳進行解決)。如果你在 sql 層面有更好的解決方案,歡迎討論~

?

Notes:

  • 「東 n 區的解決方案就是時間戳 +n * 3600 秒的偏移量,西 n 區的解決方案就是時間戳 -n * 3600 秒的偏移量」
  • 「DataStream API 存在相同的天級別窗口時區問題」
?

這里提出一個問題,為什么東八區是需要在時間戳上加 8 小時偏移量進行天級別窗口計算,而不是減 8 小時或是加上 32(24 + 8) 小時,小伙伴們有詳細分析過嘛~

根據上述問題,引出本文的第二大部分,即深度解析時區偏移量問題,這部分可以作為所有時區問題的分析思路。

4.為什么東八區是加 8 小時?

時間和時區基本概念

「時區[3]:由于世界各國家與地區經度不同,地方時也有所不同,因此會劃分為不同的時區。

「Unix 時間戳(Unix timestamp)[4]:Unix 時間戳(Unix timestamp),或稱 Unix 時間(Unix time)、POSIX 時間(POSIX time),是一種時間表示方式,定義為從格林威治時間 1970 年 01 月 01 日 00 時 00 分 00 秒(UTC/GMT的午夜)起至現在的總秒數。Unix 時間戳不僅被使用在 Unix 系統、類 Unix 系統中,也在許多其他操作系統中被廣泛采用。

「GMT」:Greenwich Mean Time 格林威治標準時間。這是以英國格林威治天文臺觀測結果得出的時間,這是英國格林威治當地時間,這個地方的當地時間過去被當成世界標準的時間。

「UT」:Universal Time 世界時。根據原子鐘計算出來的時間。

「UTC」:Coordinated Universal Time 協調世界時。因為地球自轉越來越慢,每年都會比前一年多出零點幾秒,每隔幾年協調世界時組織都會給世界時 +1 秒,讓基于原子鐘的世界時和基于天文學(人類感知)的格林威治標準時間相差不至于太大。并將得到的時間稱為 UTC,這是現在使用的世界標準時間。協調世界時不與任何地區位置相關,也不代表此刻某地的時間,所以在說明某地時間時要加上時區也就是說 GMT 并不等于 UTC,而是等于 UTC + 0,只是格林威治剛好在 0 時區上。

白話時間和時區

當時看完這一系列的時間以及時區說明之后我大腦其實是一片空白。...ojbk...,我用自己現在的一些理解,嘗試將上述所有涉及到時間的概念解釋一下。

  • 「GMT」:格林威治標準時間。
  • 「UTC」:基于原子鐘協調之后的世界標準時間。可以認為 UTC 時間和格林威治標準時間一致。即 GMT = UTC + 0,其中 0 代表格林威治為 0 時區。
  • 「時區」:逆向思維來解釋下(只從技術層面解釋,不從其他復雜層面解釋),沒有時區劃分代表著全世界都是同一時區,那么同一時刻看到的外顯時間是一樣的。舉個?:假如全世界都按照格林威治時間作為統一時間,在格林威治時間 0 點時,對于北京和加拿大的兩個同學來說,這兩個同學感知到的是北京是太陽剛剛升起(清晨),加拿大是太陽剛剛落下(傍晚)。但是由于沒有時區劃分,這兩個同學看到的時間都是 0 點,因此這是不符合人類對「感知到的時間」和自己「看到的時間」的理解的。所以劃分時區之后,可以滿足北京(東八區 UTC + 8)同學看到的時間是上午 8 點,加拿大(西四區 UTC - 4)同學看到的時間是下午 8 點。注意時區的劃分是和 UTC 綁定的。東八區即 UTC + 8。
  • 「flink 時間」:flink 使用的時間基于 java 時間紀元(GMT 1970/01/01 00:00:00,UTC + 0 1970/01/01 00:00:00)。
  • 「Unix 時間戳」:世界上任何一個地方,同時接收到的數據的對應的 Unix 時間戳都是相同的,類似時區中我們舉的不分時區的?,全世界同一時刻的 Unix 時間戳一致。
  • 「Unix 時間戳為 0」:對應的格林威治時間:1970-01-01 00:00:00,對應的北京時間(東八區):1970-01-01 08:00:00**

概念關系如圖所示:

為什么東八區是加 8 小時?

下述表格只對一些重要的時間進行了標注:

拿第一條數據解釋下,其代表在北京時間 1970/01/01 00:00:00 時,生成的一條數據所攜帶的 Unix 時間戳為 -8 * 3600。

根據需求和上圖和上述表格內容,我們可以得到如下推導過程:

  • 需求場景是統計一個整天的 uv,即天級別窗口,比如統計北京時間 1970/01/01 00:00:00 - 1970/01/02 00:00:00 范圍的數據時,這個日期范圍內的數據所攜帶的 Unix 時間戳范圍為 -8 * 3600 到 16 * 3600

  • 對于 flink 來說,默認情況下它所能統計的一個整天的 Unix 時間戳的范圍是 0 到 24 * 3600

  • 所以當我們想通過 flink 實現正確統計北京時間(1970/01/01 00:00:00 - 1970/01/02 00:00:00)范圍內的數據時,即統計 Unix 時間戳為 -8 * 3600 到 16 * 3600 的數據時,就需要對時間戳做個映射。

  • 映射方法如下,就是將整體范圍內的時間戳做在時間軸上做平移映射,就是把 -8 * 3600 映射到 0,16 * 3600 映射到 24 * 3600。相當于是對北京時間的 Unix 時間戳整體加 8 * 3600。

  • 最后在產出的時間戳上把加上的 8 小時再減掉(因為外顯時間會自動按照時區對 Unix 時間戳進行格式化)。

?

Notes:

  • 「可以加 32 小時嗎?答案是可以。在東八區,對于天級別窗口的劃分,加 8 小時和加 8 + n * 24(其中 n 為整數)小時后進行的天級別窗口劃分和計算的效果是一樣的,flink 都會將東八區的整一天內的數據劃分到一個天級別窗口內。所以加 32(8 + 24),56(8 + 48),-16(8 - 24)小時效果都相同,上述例子只是選擇了時間軸平移最小的距離,即 8 小時。注意某些系統的 Unix 時間戳為負值時會出現異常。」
  • 「此推理過程適用于所有遇到時區問題的場景,如果你也有其他應用場景有這個問題,也可以按照上述方式解決」
?

Appendix

求輸入 Unix 時間戳對應的東八區每天 0 點的 Unix 時間戳。

public?static?final?long?ONE_DAY_MILLS?=?24?*?60?*?60?*?1000L;

public?static?long?transform(long?timestamp)?{
????return?timestamp?-?(timestamp?+?8?*?60?*?60?*?1000)?%?ONE_DAY_MILLS;
}

5.總結

本文首先介紹了直接給出了我們的問題 sql 和解決方案。

第二節從需求場景以及整個數據鏈路的實現方案出發,解釋了我們怎樣使用 flink sql 進行了需求實現,并進而引出了 sql 中天級別窗口存在的時區問題。

第三節確認了天級別窗口時區問題原因,引出了 flink 使用了 java 時間紀元,并針對此問題給出了引擎層面和 sql 層面的解決方案。也進而提出了一個問題:為什么我們的解決方案是加 8 小時偏移量?

第四節針對加 8 小時偏移量的原因進行了分析,并詳細闡述了時區,UTC,GMT,Unix 時間戳之間的關系。

最后一節對本文進行了總結。

如果你有更方便的時區偏移量理解方式,歡迎留言~

Reference

[1]

java 時間紀元: https://cloud.tencent.com/developer/article/1447368

[2]

Blink Planner 時區設置: https://www.alibabacloud.com/help/zh/doc-detail/96910.htm?spm=a2c63.p38356.b99.48.28613830DXb6FQ

[3]

時區: https://baike.baidu.com/item/%E6%97%B6%E5%8C%BA/491122?fr=aladdin

[4]

Unix 時間戳(Unix timestamp): https://baike.baidu.com/item/unix%E6%97%B6%E9%97%B4%E6%88%B3/2078227?fr=aladdin

?踩坑記 | Flink 事件時間語義下數據亂序丟數

更多 Flink 實時大數據分析相關技術博文,視頻。后臺回復?“flink”?獲取。

點個贊+在看,少個 bug?? 與50位技術專家面對面20年技術見證,附贈技術全景圖

總結

以上是生活随笔為你收集整理的东八区转为0时区_踩坑记 | Flink 天级别窗口中存在的时区问题的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 一区二区三区手机在线观看 | 欧美精品久久久久久久久 | 婷婷6月天 | www狠狠操| 久久羞羞| 色综合久久久 | 黑人一级黄色片 | 91av在线免费| 丰满女人又爽又紧又丰满 | 久久1234 | 中文人妻熟妇乱又伦精品 | 久草视频在线免费播放 | 永久免费看黄网站 | 国产亚洲视频在线观看 | 青青草免费看 | 黄页网站视频在线观看 | 日本精品一区二区视频 | 在线观看免费看片 | 青青草综合视频 | 少妇高潮一区二区三区99 | 伦伦影院午夜理伦片 | 欧美在线导航 | 国产一区二区三区视频在线观看 | 无码国产69精品久久久久同性 | 免费黄色小视频 | 成人深夜网站 | 亚洲欧美成人一区二区 | 黄色中文 | 国产伦精品一区二区三区高清 | 男女床上拍拍拍 | 91精品国产欧美一区二区 | 精品自拍第一页 | www.黄色片网站 | 无遮挡裸光屁屁打屁股男男 | 中文字幕在线观看国产 | wwwsss在线观看 | 国产亚洲欧美日韩高清 | 少妇喷潮明星 | 欧美日韩国产第一页 | 亚洲美女久久 | 日韩精品导航 | 96福利视频| 青苹果av | 日本内谢少妇xxxxx少交 | 欧美成人精品一区二区综合免费 | 人妻激情偷乱视频一区二区三区 | 韩日产理伦片在线观看 | 国产精品一区二区性色av | 国产偷亚洲偷欧美偷精品 | 欧美日韩成人一区二区 | 日韩天天干| 新红楼梦2005锦江版高清在线观看 | 日韩精品视频在线观看网站 | 麻豆成人免费视频 | 国产在线视频卡一卡二 | 啪在线视频 | 亚洲国产精品成人无码区 | 蜜桃视频在线入口www | 国产一区二区三区91 | 日本成人中文字幕 | 国产高中女学生第一次 | 97国产精品人人爽人人做 | 九九热免费在线 | 国产av一区二区三区 | 色草在线 | 免费av在线电影 | 欧美日韩在线免费 | 日韩av在线免费看 | 91美女免费看| 凸凹人妻人人澡人人添 | 91污网站 | 国产精品一区三区 | 国产成人无码精品久久二区三 | 国产sm网站 | 午夜国产福利在线观看 | 国产成a人亚洲精v品无码 | 91九色丨porny丨肉丝 | 揄拍成人国产精品视频 | 一级黄色网址 | 玖玖爱av | 久久久久逼 | 欧美色图17p | 91网站免费看 | 精品亚洲一区二区三区四区五区高 | 男女插插插视频 | 欧美午夜三级 | 亚洲黄色小视频 | 久爱精品| 欧美大浪妇猛交饥渴大叫 | 黄色网页在线播放 | 噜噜吧噜噜色 | 中国18videosex极品 | 1769国产精品 | 搡老熟女老女人一区二区 | 成人激情四射网 | 亚洲在线观看一区 | 久久久久成人片免费观看蜜芽 | 精品国产999 | 网址你懂的在线 |