三年前寫過一篇ETL的文章,最近又被小夥伴問到了,這期間我也進行過調研,10多個名企,阿里騰訊和傳統企業的都有,總計20多位工程師,因此今天來重新說一下,他們遠不是sql男孩。
雖然已經過去兩三年了,ETL 領域的一些組件也都有了一些更新,但是整體來看設計的理念變化不是特別大(比如實時處理以前流行的是Spark Streaming,現在流行 Flink,而對於組件,本文也不會講解它的一些使用教程。本文更多地是分享做ETL和數據流的思考。)
- 先聊一下什麼是 ETL。聊一下大致的概念和一般意義上的理解。
- 聊一聊數據流是什麼樣子。因爲 ETL 的工作主要會體現在一條條的數據處理流上,因此這裏做一個說明。
- 舉個具體的例子來說明。
0x01 什麼是 ETL
將數據從OLTP系統中轉移到數據倉庫中的一系列操作的集合
嗯,怎麼理解 ETL 這個東西呢?直接上一個網上搜到的招聘信息看一下:
看上面的要求,有幾個點可以關注一下:
數倉的理論
- 計算引擎:Hadoop、Spark、Hive
- 數據同步:Flume、Sqoop、Kettle
- 存儲引擎:Mysql、Oracle、Hbase等存儲平臺
瞭解ETL之前,這些概念是你必須懂的:
- ODS——操作性數據
- DW——數據倉庫
- DM——數據集市
我們大致分析一下這些內容。首先說數倉的理論,這個在前面的博客也都有提到,很重要,從理論上指導了怎麼來進行數據處理。存儲引擎也就不提了。這兩者不太算是 ETL 的範疇。
那就聊一下計算引擎和數據同步的工具。我們可以大致理解 ETL 的主要工作就是利用這些工具來對數據進行處理。下面舉幾個例子來說明 ETL 的場景:
- Nginx 的日誌可以通過 Flume 抽取到 HDFS 上。
- Mysql 的數據可以通過 Sqoop 抽取到 Hive 中,同樣 Hive 的數據也可以通過 Sqoop 抽取到 Mysql 中。
- HDFS 上的一些數據不規整,有很多垃圾信息,可以用 Hadoop 或者 Spark 進行處理並重新存入 HDFS 中。
- Hive 的表也可以通過 Hive 再做一些計算生成新的 Hive 表。
這些都算是 ETL,其中 1 和 2 都比較典型,它們把數據從一個存儲引擎轉移到另一個存儲引擎,在轉移的過程中做了一定的轉換操作。3 和 4 也同樣是 ETL 只是它們更側重的是數據的加工。
到了這一步,我們不再糾結於具體的 ETL 概念是什麼,僅從自己的直觀理解上來定義 ETL,不管嚴謹不嚴謹,反正這些活 ETL 工程師基本都要幹。
ETL 是對數據的加工過程,它包括了數據抽取、數據清洗、數據入庫等一系列操作,大部分和數據處理清洗相關的操作都可以算是 ETL。
0x02 數據流長什麼樣子
舉個簡單的例子,下面是一個種數據流的設計,藍色的框框代表的是數據來源,紅色的框框主要是數據計算平臺,綠色的 HDFS 是我們一種主要的數據存儲,Hive、Hbase、ES這些就不再列出來了。
數據流的分類
我們常說的數據流主要分兩種:
- 離線數據
- 實時數據
其中離線數據一般都是 T+1 的模式,即每天的凌晨開始處理前一天的數據,有時候可能也是小時級的,技術方案的話可以用 Sqoop、Flume、MR 這些。實時數據一般就是指實時接入的數據,一般是分鐘級別以下的數據,常用的技術方案有 Spark Streaming 和 Flink。
現在的大部分數據流的設計都會有離線和實時相結合的方案,即 Lambda 架構,感興趣的同學可以瞭解一下。
0x03 舉個例子
前段時間和一個哥們再聊數據流的設計,正好這裏大概描述一下場景和解決方案。
一、場景
- 數據源主要爲 Mysql,希望實時同步 Mysql 數據到大數據集羣中(肯定是越快越好)。
- 目前每日 20 億數據,可預見的一段時間後的規模是 100 億每日以上。
- 能快速地查到最新的數據,這裏包含兩部分含義:從 Mysql 到大數據集羣的速度快、從大數據集羣中查詢的速度要快。
二、方案選型
遇到這個場景的時候,根據經驗我們主要考慮下面兩個點:數據抽取引擎和存儲引擎。
數據抽取引擎
這裏我們主要考慮兩種方案:
- Sqoop 定時抽取 Mysql 數據到 HDFS 中,可以每天全量抽取一份,也可以隔段時間就抽取一份變更的數據。
- Canal 監聽 Mysql 的 binlog 日誌,相當於是 Mysql 有一條數據久變動,我們就抽取一條數據過來。
優缺點的對比也很明顯:
- Sqoop 相對比較通用一些,不管是 Mysql 還是 PostgreSql都可以用,而且很成熟。但是實時性較差,每次相當於是啓動一個 MR 的任務。
- Canal 速度很快,但是隻能監聽 Mysql 的日誌。
存儲引擎
存儲引擎主要考慮 HDFS、Hbase 和 ES。
一般情況下,HDFS 我們儘量都會保存一份。主要糾結的就是 Hbase 和 ES。本來最初是想用 Hbase 來作爲實時查詢的,但是由於考慮到會有實時檢索的需求,就暫定爲ES
三、方案設計
最終,我們使用了下面的方案。
- 使用 Canal 來實時監聽 Mysql 的數據變動
- 使用 Kafka 作爲消息中間件,主要是爲了屏蔽數據源的各種變動。比如以後即使用 Flume 了,我們架構也不用大變
- 數據落地,有一份都會落地 HDFS,這裏使用 Spark Streaming,算是準實時落地,而且方便加入處理邏輯。在 落地 ES 的時候可以使用 Spark Streaming,也可以使用 Logstach,這個影響不大
四、一些問題
有兩個小問題列一下。
- 小文件,分鐘級別的文件落地,肯定會有小文件的問題,這裏要考慮的是,小文件的處理儘量不要和數據接入流程耦合太重,可以考慮每天、每週、甚至每月合併一次小文件。
- 數據流的邏輯複雜度問題,比如從 Kafka 落地 HDFS 會有一個取捨的考慮,比如說,我可以在一個 SS 程序中就分別落地 HDFS 和 ES,但是這樣的話兩條流就會有大的耦合,如果 ES 集羣卡住,HDFS 的落地也會受到影響。但是如果兩個隔開的話,就會重複消費同一份數據兩次,會有一定網絡和計算資源的浪費。