互聯網海量數據如何存儲Kafka
對于大部分互聯網公司來說,數據量最大的幾類數據是:點擊流數據、監控數據和日志數據。這里面「點擊流」指的是在 App、小程序和 Web 頁面上的埋點數據,這些埋點數據記錄用戶的行為,比如你打開了哪個頁面,點擊了哪個按鈕,在哪個商品上停留了多久等等這些。
當然你不用太擔心自己的隱私問題,記錄的這些行為數據不是為了監控用戶,主要目的是為了從統計上分析群體用戶的行為,從而改進產品和運營。比如,某件商品看的人很多,停留時間很長,最后下單購買的人卻很少,那采銷人員就要考慮是不是這件商品的定價太高了。
除了點擊流數據以外,還有監控和日志數據都是大家常用的。
這類數據都是真正海量的數據,相比于訂單、商品這類業務的數據,數據量要多出 2~3 個數量級。每天產生的數據量就可能會超過 TB(1 TB = 1024 GB)級別,經過一段時間累積下來,有些數據會達到 PB(1 PB = 1024 TB)級別。
這種量級的數據,在大數據技術出現之前,是沒法保存和處理的,只能是通過抽樣的方法來湊合著做分析。Hadoop 等大數據技術出現以后,才使得存儲和計算海量數據成為可能。那么如果要保存像「點擊流」這樣的海量數據,應該選擇什么樣的存儲系統?
使用 Kafka 存儲海量原始數據
早期對于這類海量原始數據,都傾向于先計算再存儲 。也就是,在接收原始數據的服務中,先進行一些數據過濾、聚合等初步的計算,將數據先收斂一下,再落存儲。這樣可以降低存儲系統的寫入壓力,也能節省磁盤空間。
這幾年,隨著存儲設備越來越便宜,并且,數據的價值被不斷地重新挖掘,更多的大廠都傾向于 先存儲再計算,直接保存海量的原始數據,再對數據進行實時或者批量計算。這種方案,除了貴以外都是優點:
- 不需要二次分發就可以同時給多個流和批計算任務提供數據;
- 如果計算任務出錯,可以隨時回滾重新計算;
- 如果對數據有新的分析需求,上線后直接就可以用歷史數據計算出結果,而不用去等新數據。
但是,這種方式對保存原始數據的存儲系統要求就很高了:既要有足夠大的容量,能水平擴容,還要讀寫都足夠快,跟得上數據生產的寫入速度,還要給下游計算提供低延遲的讀服務。什么樣的存儲能滿足這樣的要求呢?這里給出幾種常用的解決方案。
第一種方案是,使用 Kafka 來存儲。Kafka 不是一個消息隊列么,怎么成了存儲系統了?實際上,現代的消息隊列,本質上就是分布式的流數據存儲系統。
那么Kafka的數據是如何存儲、分片、復制的?它是如何保證高可用,如何保證數據一致性的?那你會發現它和分布式存儲系統,并沒有什么太大的區別。唯一的區別就是,它的查詢語言(生產和消費消息)和存儲引擎的數據結構(Commit Log)比一般的存儲系統要簡單很多。但也正是因為這個原因,使得 Kafka 的讀寫性能遠遠好于其他的存儲系統。Kafka 官方給自己的定位也是「分布式流數據平臺」,不只是一個 MQ。
Kafka 提供「無限」的消息堆積能力,具有超高的吞吐量,可以滿足我們保存原始數據的大部分要求。寫入點擊流數據的時候,每個原始數據采集服務作為一個生產者,把數據發給 Kafka 就可以了。下游的計算任務,可以作為消費者訂閱消息,也可以按照時間或者位點來讀取數據。并且,Kafka 作為事實標準,和大部分大數據生態圈的開源軟件都有非常好的兼容性和集成度,像 Flink、Spark 等大多計算平臺都提供了直接接入 Kafka 的組件。
Kafka 也支持把數據分片,這個在 Kafka 中叫 Partition,每個分片可以分布到不同的存儲節點上。寫入數據的時候,可以均勻地寫到這些分片上,理論上只要分片足夠多,存儲容量就可以是「無限」的。但是,單個分片總要落到某一個節點上,而單節點的存儲容量畢竟是有限的,隨著時間推移,單個分片總有寫滿的時候。
即使它支持擴容分片數量,也沒辦法像其他分布式存儲系統那樣,重新分配數據,把已有分片上的數據遷移一部分到新的分片上。所以擴容分片也解決不了已有分片寫滿的問題。而 Kafka 又不支持按照時間維度去分片,所以,受制于單節點的存儲容量,Kafka 實際能存儲的數據容量并不是無限的。
#Kafka 之外還有哪些解決方案?
如果需要長時間(幾個月 - 幾年)保存的海量數據,就不適合用 Kafka 存儲。這種情況下,只能退而求其次,使用第二種方案了。
第二種方案是,使用 HDFS 來存儲。使用 HDFS 存儲數據也很簡單,就是把原始數據寫成一個一個文本文件,保存到 HDFS 中。我們需要按照時間和業務屬性來組織目錄結構和文件名,以便于下游計算程序來讀取,比如說:click/20200808/Beijing_0001.csv
,代表 2020 年 8 月 8 日,從北京地區用戶收集到的點擊流數據,這個是當天的第一個文件。
對于保存海量的原始數據這個特定的場景來說,HDFS 的吞吐量是遠不如 Kafka 的。按照平均到每個節點上計算,Kafka 的吞吐能力很容易達到每秒鐘大幾百兆,而 HDFS 只能達到百兆左右。這就意味著,要達到相同的吞吐能力,使用 HDFS 就要比使用 Kafka,多用幾倍的服務器數量。
但 HDFS 也有它的優勢,第一個優勢就是,它能提供真正無限的存儲容量,如果存儲空間不夠了,水平擴容就可以解決。另外一個優勢是,HDFS 能提供比 Kafka 更強的數據查詢能力。Kafka 只能按照時間或者位點來提取數據,而 HDFS 配合 Hive 直接就可以支持用 SQL 對數據進行查詢,雖然說查詢的性能比較差,但查詢能力要比 Kafka 強大太多了。
以上這兩種方案因為都有各自的優勢和不足,在實際生產中,都有不少的應用,你可以根據業務的情況來選擇。那有沒有兼顧這二者優勢的方案呢?最好能做到,既有超高的吞吐能力,又能無限擴容,同時還能提供更好的查詢能力,有這樣的好事兒么?
目前已經有一些的開源項目,都致力于解決這方面的問題。
一類是 分布式流數據存儲,比較活躍的項目有 Pravega 和 Pulsar 的存儲引擎 Apache BookKeeper。這些分布式流數據存儲系統,走的是類似 Kafka 這種流存儲的路線,在高吞吐量的基礎上,提供真正無限的擴容能力,更好的查詢能力。
還有一類是 時序數據庫(Time Series Databases),比較活躍的項目有 InfluxDB 和 OpenTSDB 等。這些時序數據庫,不僅有非常好的讀寫性能,還提供很方便的查詢和聚合數據的能力。但是,它們不是什么數據都可以存的,它們專注于類似監控數據這樣,有時間特征并且數據內容都是數值的數據。如果你有存儲海量監控數據的需求,可以關注一下這些項目。
在互聯網行業,點擊流、監控和日志這幾類數據,是海量數據中的海量數據。對于這類數據,一般的處理方式都是 先存儲再計算,計算結果保存到特定的數據庫中,供業務系統查詢。
所以,對于海量原始數據的存儲系統,我們要求的是超高的寫入和讀取性能,和近乎無限的容量,對于數據的查詢能力要求不高。生產上,可以選擇 Kafka 或者是 HDFS,Kafka 的優點是讀寫性能更好,單節點能支持更高的吞吐量。而 HDFS 則能提供真正無限的存儲容量,并且對查詢更友好。
為什么 Kafka 能做到幾倍于 HDFS 的吞吐能力,技術上的根本原因是什么?
這個問題的最根本原因是,對于磁盤來說,順序讀寫的性能要遠遠高于隨機讀寫,這個性能差距視不同的磁盤,大約在幾十倍左右。Kafka 是為順序讀寫設計的,而 HDFS 是為隨機讀寫的設計的,所以在順序寫入的時候,Kafka 的性能會更好。
雖然 hdfs 和 kafka 都可以用來做存儲, 但 kafka 在使用方面像磁帶;hdfs 更像硬盤,總結一下針對海量數據的存儲方案有如下幾個要點:
- 采用批處理的方式提升吞吐量
- 利用了磁盤文件順序讀寫性能高的特點設計存儲
- 利用了操作系統的 PageCache 做緩存,減少 IO
- 采用零拷貝技術加速消費流程