大資料開發面試題
包含Hadoop、zookeeper、Hive、flume、kafka、Hbase、flink、spark、數倉等高頻面試題,
資料來自原博主爬蟲獲取!
文章目錄
- 大資料開發面試題
- **Hadoop**
- **一、HDFS檔案寫入和讀取程序**
- **HDFS寫資料流程**
- **HDFS讀資料流程**
- **HDFS寫資料流程**
- **HDFS讀資料流程**
- **二、MapReduce作業原理**
- **Zookeeper**
- **Zookeeper的選舉機制**
- **Hive**
- **Hive的內部表和外部表的區別**
- **Flume**
- **Flume的source、channel、sink分別都有哪些**
- **Kafka**
- **Kafka是如何實作高吞吐的**
- **HBase**
- **HBase的rowkey設計原則**
- **Spark**
- **Spark資料傾斜問題+解決方案**
- **說下RDD的寬依賴和窄依賴**
- **Flink**
- **Flink的Exactly Once語意怎么保證**
- **資料倉庫**
- **資料倉庫分層(層級劃分),每層做什么**
- **Saprk Streaming和Flink的區別**
Hadoop
一、HDFS檔案寫入和讀取程序
可靈活回答 :
1)HDFS讀寫原理(流程)
2)HDFS上傳下載流程
3)講講(介紹下)HDFS
4)HDFS存盤機制
回答這個問題之前,我們先來看下機架感知 機制,也就是HDFS上副本存盤結點的選擇,

Hadoop3.x副本結點選擇:
由上圖可知,第一個副本在Client所處的節點上,如果客戶端在集群外,隨機選一個,
第二個副本在另一個機架的隨機一個節點,
第三個副本在第二個副本所在機架的隨機節點,
關于HDFS讀寫流程,這里還是給出兩個版本,有助于理解
第一個版本:簡潔版
HDFS寫資料流程

1)客戶端通過Distributed FileSystem模塊向NameNode請求上傳檔案,NameNode檢查目標檔案是否已存在,父目錄是否存在,
2)NameNode回傳是否可以上傳,
3)客戶端請求第一個 block上傳到哪幾個datanode服務器上,
4)NameNode回傳3個datanode節點,分別為dn1、dn2、dn3,
5)客戶端通過FSDataOutputStream模塊請求dn1上傳資料,dn1收到請求會繼續呼叫dn2,然后dn2呼叫dn3,將這個通信管道建立完成,
6)dn1、dn2、dn3逐級應答客戶端,
7)客戶端開始往dn1上傳第一個block(先從磁盤讀取資料放到一個本地記憶體快取),以packet為單位,dn1收到一個packet就會傳給dn2,dn2傳給dn3;dn1每傳一個packet會放入一個應答佇列等待應答,
8)當一個block傳輸完成之后,客戶端再次請求NameNode上傳第二個block的服務器,(重復執行3-7步),
HDFS讀資料流程

1)客戶端通過Distributed FileSystem向NameNode請求下載檔案,NameNode通過查詢元資料,找到檔案塊所在的DataNode地址,
2)挑選一臺DataNode(就近原則,然后隨機)服務器,請求讀取資料,
3)DataNode開始傳輸資料給客戶端(從磁盤里面讀取資料輸入流,以packet為單位來做校驗),
4)客戶端以packet為單位接收,先在本地快取,然后寫入目標檔案,
第二個版本:詳細版,有助于理解
HDFS寫資料流程

1)Client將FileA按128M分塊,分成兩塊,block1和Block2;
2)Client向nameNode發送寫資料請求,如圖藍色虛線①------>,
3)NameNode節點,記錄block資訊,并回傳可用的DataNode,如粉色虛線②------->,
????Block1: host2,host1,host6
????Block2: host7,host3,host4
4)client向DataNode發送block1;發送程序是以流式寫入,
流式寫入程序:
(1)將64M的block1按64k的package劃分;
(2)然后將第一個package發送給host2;
(3)host2接收完后,將第一個package發送給host1,同時client向host2發送第二個package;
(4)host1接收完第一個package后,發送給host6,同時接收host2發來的第二個package,
(5)以此類推,如圖紅線實線所示,直到將block1發送完畢,
(6)host2,host1,host6向NameNode,host2向Client發送通知,說“訊息發送完了”,如圖粉紅顏色實線所示,
(7)client收到host2發來的訊息后,向namenode發送訊息,說我寫完了,這樣就完成了,如圖黃色粗實線,
(8)發送完block1后,再向host7,host3,host4發送block2,如圖藍色實線所示,
(9)發送完block2后,host7,host3,host4向NameNode,host7向Client發送通知,如圖淺綠色實線所示,
(10)client向NameNode發送訊息,說我寫完了,如圖黃色粗實線,,,這樣就完畢了,
HDFS讀資料流程

1)client向namenode發送讀請求,
2)namenode查看Metadata資訊,回傳fileA的block的位置,
????block1:host2,host1,host6
????block2:host7,host3,host4
3)block的位置是有先后順序的,先讀block1,再讀block2,而且block1去host2上讀取;然后block2,去host7上讀取,
二、MapReduce作業原理
可靈活回答:
1)MapReduce執行流程
2)對MapReduce的理解
3)MapReduce程序
4)MapReduce的詳細程序
5)MapTask和ReduceTask作業機制
6)MapReduce中有沒有涉及到排序

1)準備一個200M的檔案,submit中對原始資料進行切片;
2)客戶端向YARN提交資訊,YARN開啟一個MrAppmaster,MrAppmaster讀取客戶端對應的資訊,主要是job.split,然后根據切片個數(這里2個)開啟對應數量的MapTask(2個);
3)MapTask通過InputFormat去讀取資料(默認按行讀取),K是偏移量,V是一行內容,資料讀取后交給Mapper,然后根據用戶的業務需求對資料進行處理;
4)資料處理之后輸出到環型緩沖區(默認100M),環型緩沖區一邊是存資料,一邊存的是索引(描述資料的元資料),環型緩沖區存盤資料到達80%后進行反向溢寫,并對資料進行磁區、排序;
5)再對磁區且區內有序的檔案進行歸并排序 ,然后存盤到磁盤;

6)當所有MapTask任務完成后,啟動相應數量的ReduceTask,并告知ReduceTask處理資料范圍(資料磁區),注意:不是必須等到所有MapTask結束后才開始,可以自行配置,
7)ReduceTask開啟后,ReduceTask主動從MapTask對應的磁區拉取資料;
8)再對ReduceTask拉取過來的資料進行一個全域合并排序;
9)順序讀取資料,按key分,key相同的資料進入同一個Reducer,一次讀取一組資料;
10)Reducer處理完資料,通過OutPutFormat往外寫資料,形成對應檔案,
簡潔版:面試可手寫

Zookeeper
Zookeeper的選舉機制
可靈活回答:
1)Zookeeper的選舉策略
2)Zookeeper的選舉程序
3)Zookeeper的Leader選舉是如何實作的
1)半數機制:集群中半數以上機器存活,集群可用,所以Zookeeper適合安裝奇數臺服務器,
2)Zookeeper雖然在組態檔中并沒有指定Master和Slave,但是,Zookeeper作業時,是有一個節點為Leader,其他則為Follower,Leader是通過內部的選舉機制臨時產生的,
3)選舉程序
假設有五臺服務器組成的Zookeeper集群,它們的id從1-5,同時它們都是最新啟動的,也就是沒有歷史資料,在存放資料量這一點上,都是一樣的,假設這些服務器依序啟動,來看看會發生什么,

(1)服務器1啟動,發起一次選舉,服務器1投自己一票,此時服務器1票數一票,不夠半數以上(3票),選舉無法完成,服務器1狀態保持為LOOKING;
(2)服務器2啟動,再發起一次選舉,服務器1和2分別投自己一票并交換選票資訊:此時服務器1發現服務器2的ID比自己目前投票推舉的(服務器1)大,更改選票為推舉服務器2,此時服務器1票數0票,服務器2票數2票,沒有半數以上結果,選舉無法完成,服務器1,2狀態保持LOOKING
(3)服務器3啟動,發起一次選舉,此時服務器1和2都會更改選票為服務器3,此次投票結果:服務器1為0票,服務器2為0票,服務器3為3票,此時服務器3的票數已經超過半數,服務器3當選Leader,服務器1,2更改狀態為FOLLOWING,服務器3更改狀態為LEADING;
(4)服務器4啟動,發起一次選舉,此時服務器1,2,3已經不是LOOKING狀態,不會更改選票資訊,交換選票資訊結果:服務器3為3票,服務器4為1票,此時服務器4服從多數,更改選票資訊為服務器3,并更改狀態為FOLLOWING;
(5)服務器5啟動,同4一樣當小弟,
Hive
Hive的內部表和外部表的區別
內部表 (managed table):未被external修飾
外部表 (external table):被external修飾
區別:
1)內部表資料由Hive自身管理,外部表資料由HDFS管理;
2)內部表的資料存盤位置是hive.metastore.warehouse.dir,默認位置:/user/hive/warehouse,外部表資料的存盤位置由自己制定(如果沒有LOCATION,Hive將在HDFS上的/user/hive/warehouse檔案夾下以外部表的表名創建一個檔案夾,并將屬于這個表的資料存放在這里);
3)洗掉內部表會直接洗掉元資料(metadata)及存盤資料;洗掉外部表僅僅會洗掉元資料,HDFS上的檔案并不會被洗掉;
4)對內部表的修改會將修改直接同步給元資料,而對外部表的表結構和磁區進行修改,則需要修復(MSCK REPAIR TABLE table_name;)
Flume
Flume的source、channel、sink分別都有哪些
可靈活回答:
1)Flume的source、channel、sink分別用的什么型別的?
2)Flume的Kafka sink
3)Flume分為哪幾塊?
4)channel的型別

Agent
Agent是一個JVM行程,它以事件的形式將資料從源頭送至目的,
Agent主要由Source、Channel、Sink3個部分組成,
Source
Source是負責接收資料到Flume Agent的組件,

Channel
Channel是位于Source和Sink之間的緩沖區,因此,Channel允許Source和Sink運作在不同的速率上,Channel是執行緒安全的,可以同時處理幾個Source的寫入操作和幾個Sink的讀取操作,

Sink
Sink不斷地輪詢Channel中的事件且批量地移除它們,并將這些事件批量寫入到存盤或索引系統、或者被發送到另一個Flume Agent,

Kafka
Kafka是如何實作高吞吐的
可靈活回答:
1)Kafka為什么低延遲高吞吐?
2)Kafka高吞吐的原因
3)Kafka為什么高可用、高吞吐?
4)Kafka如何保證高吞吐量?
Kafka是分布式訊息系統,需要處理海量的訊息,Kafka的設計是把所有的訊息都寫入速度低容量大的硬碟,以此來換取更強的存盤能力,但實際上,使用硬碟并沒有帶來過多的性能損失,
kafka主要使用了以下幾個方式實作了超高的吞吐率,
1)順序讀寫
kafka的訊息是不斷追加到檔案中的,這個特性使kafka可以充分利用磁盤的順序讀寫性能,順序讀寫不需要硬碟磁頭的尋道時間,只需很少的扇區旋轉時間,所以速度遠快于隨機讀寫,
Kafka官方給出了測驗資料(Raid-5,7200rpm):
順序 I/O: 600MB/s
隨機 I/O: 100KB/s
2)零拷貝
先簡單了解下檔案系統的操作流程,例如一個程式要把檔案內容發送到網路,
這個程式是作業在用戶空間,檔案和網路socket屬于硬體資源,兩者之間有一個內核空間,
在作業系統內部,整個程序為:

在 Linux kernel2.2 之后出現了一種叫做"零拷貝(zero-copy)"系統呼叫機制,就是跳過“用 戶緩沖區”的拷貝,建立一個磁盤空間和記憶體的直接映射,資料不再復制到“用戶態緩沖區” ,
系統背景關系切換減少為 2 次,可以提升一倍的性能,

3)檔案分段
kafka的佇列topic被分為了多個區partition,每個partition又分為多個段segment,所以一個佇列中的訊息實際上是保存在N多個片段檔案中

通過分段的方式,每次檔案操作都是對一個小檔案的操作,非常輕便,同時也增加了并 行處理能力
4)批量發送
Kafka允許進行批量發送訊息,先將訊息快取在記憶體中,然后一次請求批量發送出去,比如可以指定快取的訊息達到某個量的時候就發出去,或者快取了固定的時間后就發送出去 ,如100 條訊息就發送,或者每5秒發送一次,這種策略將大大減少服務端的I/O次數
5)資料壓縮
Kafka 還支持對訊息集合進行壓縮,Producer可以通過GZIP或Snappy格式對訊息集合進行壓縮,壓縮的好處就是減少傳輸的資料量,減輕對網路傳輸的壓力,Producer壓縮之后,在 Consumer需進行解壓,雖然增加了CPU的作業,但在對大資料處理上,瓶頸在網路上而不是 CPU,所以這個成本很值得,
HBase
HBase的rowkey設計原則
可靈活回答:
1)HBase如何設計rowkey?
2)你HBase的rowkey為什么這么設計?有什么優缺點?
3)Hbase rowKey設定講究
HBase中,表會被劃分為1…n個Region,被托管在RegionServer中,Region二個重要的屬性:StartKey與EndKey表示這個Region維護的rowKey范圍,當我們要讀/寫資料時,如果rowKey落在某個start-end key范圍內,那么就會定位到目標region并且讀/寫到相關的資料,
那怎么快速精準的定位到我們想要操作的資料,就在于我們的rowkey的設計了,
設計原則如下:
1、rowkey長度原則
Rowkey是一個二進制碼流,Rowkey的長度被很多開發者建議說設計在10~100個位元組,不過建議是越短越好,不要超過16個位元組,
原因如下:
1)資料的持久化檔案HFile中是按照Key Value 存盤的,如果Rowkey過長比如100個位元組,1000萬列資料光Rowkey就要占用100*1000 萬=10億個位元組,將近1G資料,這會極大影響 HFile的存盤效率;
2)MemStore將快取部分資料到記憶體,如果 Rowkey欄位過長記憶體的有效利用率會降低,系統將無法快取更多的資料,這會降低檢索效率,因此Rowkey的位元組長度越短越好;
3)目前作業系統是都是64位系統,記憶體8位元組對齊,控制在16個位元組,8位元組的整數倍利用作業系統的最佳特性,
2、rowkey散列原則
如果Rowkey是按時間戳的方式遞增,不要將時間放在二進制碼的前面,建議將Rowkey的高位作為散列欄位,由程式回圈生成,低位放時間欄位,將會提高資料均衡分布在每個Regionserver實作負載均衡的幾率,如果沒有散列欄位,首欄位直接是時間資訊將產生所有新資料都在一個 RegionServer上堆積的熱點現象,這樣在做資料檢索的時候負載將會集中在個別 RegionServer,降低查詢效率,
3、rowkey唯一原則
必須在設計上保證其唯一性,rowkey是按照字典順序排序存盤的,因此,設計rowkey的時候,要充分利用這個排序的特點,將經常讀取的資料存盤到一塊,將最近可能會被訪問的資料放到一塊,
Spark
Spark資料傾斜問題+解決方案
1、資料傾斜
資料傾斜指的是,并行處理的資料集中,某一部分(如Spark或Kafka的一個Partition)的資料顯著多于 其它部分,從而使得該部分的處理速度成為整個資料集處理的瓶頸
資料傾斜倆大直接致命后果
1)資料傾斜直接會導致一種情況:Out Of Memory
2)運行速度慢
主要是發生在Shuffle階段,同樣Key的資料條數太多了,導致了某個key(下圖中的80億條)所在的Task數 據量太大了,遠遠超過其他Task所處理的資料量

一個經驗結論是:一般情況下,OOM的原因都是資料傾斜
2、如何定位資料傾斜
資料傾斜一般會發生在shuffle程序中,很大程度是使用可能會觸發shuffle操作的算子:distinct、groupByKey、reduceByKey、aggregateByKey、join、cogroup、repartition等,
查看任務->查看Stage->查看代碼

也可從以下幾種情況考慮:
1)是不是有OOM情況出現,一般是少數記憶體溢位的問題
2)是不是應用運行時間差異很大,總體時間很長
3)需要了解你所處理的資料Key的分布情況,如果有些Key有大量的條數,那么就要小心資料傾斜的問題
4)一般需要通過Spark Web UI和其他一些監控方式出現的例外來綜合判斷
5)看看代碼里面是否有一些導致Shuffle的算子出現
3、資料傾斜的幾種典型情況
3.1 資料源中的資料分布不均勻,Spark需要頻繁互動
3.2 資料集中的不同Key由于磁區方式,導致資料傾斜
3.3 JOIN操作中,一個資料集中的資料分布不均勻,另一個資料集較小(主要)
3.4 聚合操作中,資料集中的資料分布不均勻(主要)
3.5 JOIN操作中,兩個資料集都比較大,其中只有幾個Key的資料分布不均勻
3.6 JOIN操作中,兩個資料集都比較大,有很多Key的資料分布不均勻
3.7 資料集中少數幾個key資料量很大,不重要,其他資料均勻
4、資料傾斜的處理方法
4.1 資料源中的資料分布不均勻,Spark需要頻繁互動
解決方案:避免資料源的資料傾斜
實作原理 :通過在Hive中對傾斜的資料進行預處理,以及在進行kafka資料分發時盡量進行平均分配,這種方案從根源上解決了資料傾斜,徹底避免了在Spark中執行shuffle類算子,那么肯定就不會有資料傾斜的問題了,
方案優點 :實作起來簡單便捷,效果還非常好,完全規避掉了資料傾斜,Spark作業的性能會大幅度提升,
方案缺點 :治標不治本,Hive或者Kafka中還是會發生資料傾斜,
適用情況 :在一些Java系統與Spark結合使用的專案中,會出現Java代碼頻繁呼叫Spark作業的場景,而且對Spark作業的執行性能要求很高,就比較適合使用這種方案,將資料傾斜提前到上游的Hive ETL,每天僅執行一次,只有那一次是比較慢的,而之后每次Java呼叫Spark作業時,執行速度都會很快,能夠提供更好的用戶體驗,
總結 :前臺的Java系統和Spark有很頻繁的互動,這個時候如果Spark能夠在最短的時間內處理資料,往往會給前端有非常好的體驗,這個時候可以將資料傾斜的問題拋給資料源端,在資料源端進行資料傾斜的處理,但是這種方案沒有真正的處理資料傾斜問題
4.2 資料集中的不同Key由于磁區方式,導致資料傾斜
**解決方案1:**調整并行度
實作原理 :增加shuffle read task的數量,可以讓原本分配給一個task的多個key分配給多個task,從而讓每個task處理比原來更少的資料,
方案優點 :實作起來比較簡單,可以有效緩解和減輕資料傾斜的影響,
方案缺點 :只是緩解了資料傾斜而已,沒有徹底根除問題,根據實踐經驗來看,其效果有限,
實踐經驗 :該方案通常無法徹底解決資料傾斜,因為如果出現一些極端情況,比如某個key對應的資料量有100萬,那么無論你的task數量增加到多少,都無法處理,

解決方案2:
自定義Partitioner(緩解資料傾斜)
適用場景 :大量不同的Key被分配到了相同的Task造成該Task資料量過大,
解決方案 :使用自定義的Partitioner實作類代替默認的HashPartitioner,盡量將所有不同的Key均勻分配到不同的Task中,
優勢 :不影響原有的并行度設計,如果改變并行度,后續Stage的并行度也會默認改變,可能會影響后續Stage,
劣勢 :適用場景有限,只能將不同Key分散開,對于同一Key對應資料集非常大的場景不適用,效果與調整并行度類似,只能緩解資料傾斜而不能完全消除資料傾斜,而且需要根據資料特點自定義專用的Partitioner,不夠靈活,
4.3 JOIN操作中,一個資料集中的資料分布不均勻,另一個資料集較小(主要)
解決方案:
Reduce side Join轉變為Map side Join
適用場景 :在對RDD使用join類操作,或者是在Spark SQL中使用join陳述句時,而且join操作中的一個RDD或表的資料量比較小(比如幾百M),比較適用此方案,
實作原理 :普通的join是會走shuffle程序的,而一旦shuffle,就相當于會將相同key的資料拉取到一個shuffle read task中再進行join,此時就是reduce join,但是如果一個RDD是比較小的,則可以采用廣播小RDD全量資料+map算子來實作與join同樣的效果,也就是map join,此時就不會發生shuffle操作,也就不會發生資料傾斜,
優點 :對join操作導致的資料傾斜,效果非常好,因為根本就不會發生shuffle,也就根本不會發生資料傾斜,
缺點 :適用場景較少,因為這個方案只適用于一個大表和一個小表的情況,
4.4 聚合操作中,資料集中的資料分布不均勻(主要)
解決方案:兩階段聚合(區域聚合+全域聚合)
適用場景 :對RDD執行reduceByKey等聚合類shuffle算子或者在Spark SQL中使用group by陳述句進行分組聚合時,比較適用這種方案
實作原理 :將原本相同的key通過附加隨機前綴的方式,變成多個不同的key,就可以讓原本被一個task處理的資料分散到多個task上去做區域聚合,進而解決單個task處理資料量過多的問題,接著去除掉隨機前綴,再次進行全域聚合,就可以得到最終的結果,具體原理見下圖,
優點 :對于聚合類的shuffle操作導致的資料傾斜,效果是非常不錯的,通常都可以解決掉資料傾斜,或者至少是大幅度緩解資料傾斜,將Spark作業的性能提升數倍以上,
缺點 :僅僅適用于聚合類的shuffle操作,適用范圍相對較窄,如果是join類的shuffle操作,還得用其他的解決方案
將相同key的資料分拆處理

4.5 JOIN操作中,兩個資料集都比較大,其中只有幾個Key的資料分布不均勻
解決方案:為傾斜key增加隨機前/后綴
適用場景 :兩張表都比較大,無法使用Map側Join,其中一個RDD有少數幾個Key的資料量過大,另外一個RDD的Key分布較為均勻,
解決方案 :將有資料傾斜的RDD中傾斜Key對應的資料集單獨抽取出來加上隨機前綴,另外一個RDD每條資料分別與隨機前綴結合形成新的RDD(笛卡爾積,相當于將其資料增到到原來的N倍,N即為隨機前綴的總個數),然后將二者Join后去掉前綴,然后將不包含傾斜Key的剩余資料進行Join,最后將兩次Join的結果集通過union合并,即可得到全部Join結果,
優勢 :相對于Map側Join,更能適應大資料集的Join,如果資源充足,傾斜部分資料集與非傾斜部分資料集可并行進行,效率提升明顯,且只針對傾斜部分的資料做資料擴展,增加的資源消耗有限,
劣勢 :如果傾斜Key非常多,則另一側資料膨脹非常大,此方案不適用,而且此時對傾斜Key與非傾斜Key分開處理,需要掃描資料集兩遍,增加了開銷,
注意:具有傾斜Key的RDD資料集中,key的數量比較少

4.6 JOIN操作中,兩個資料集都比較大,有很多Key的資料分布不均勻
解決方案 :隨機前綴和擴容RDD進行join
適用場景 :如果在進行join操作時,RDD中有大量的key導致資料傾斜,那么進行分拆key也沒什么意義,
實作思路 :將該RDD的每條資料都打上一個n以內的隨機前綴,同時對另外一個正常的RDD進行擴容,將每條資料都擴容成n條資料,擴容出來的每條資料都依次打上一個0~n的前綴,最后將兩個處理后的RDD進行join即可,和上一種方案是盡量只對少數傾斜key對應的資料進行特殊處理,由于處理程序需要擴容RDD,因此上一種方案擴容RDD后對記憶體的占用并不大;而這一種方案是針對有大量傾斜key的情況,沒法將部分key拆分出來進行單獨處理,因此只能對整個RDD進行資料擴容,對記憶體資源要求很高,
優點 :對join型別的資料傾斜基本都可以處理,而且效果也相對比較顯著,性能提升效果非常不錯,
缺點 :該方案更多的是緩解資料傾斜,而不是徹底避免資料傾斜,而且需要對整個RDD進行擴容,對記憶體資源要求很高,
實踐經驗 :曾經開發一個資料需求的時候,發現一個join導致了資料傾斜,優化之前,作業的執行時間大約是60分鐘左右;使用該方案優化之后,執行時間縮短到10分鐘左右,性能提升了6倍,
注意 :將傾斜Key添加1-N的隨機前綴,并將被Join的資料集相應的擴大N倍(需要將1-N數字添加到每一條資料上作為前綴)

4.7 資料集中少數幾個key資料量很大,不重要,其他資料均勻
解決方案 :過濾少數傾斜Key
適用場景 :如果發現導致傾斜的key就少數幾個,而且對計算本身的影響并不大的話,那么很適合使用這種方案,比如99%的key就對應10條資料,但是只有一個key對應了100萬資料,從而導致了資料傾斜,
優點 :實作簡單,而且效果也很好,可以完全規避掉資料傾斜,
缺點 :適用場景不多,大多數情況下,導致傾斜的key還是很多的,并不是只有少數幾個,
實踐經驗 :在專案中我們也采用過這種方案解決資料傾斜,有一次發現某一天Spark作業在運行的時候突然OOM了,追查之后發現,是Hive表中的某一個key在那天資料例外,導致資料量暴增,因此就采取每次執行前先進行采樣,計算出樣本中資料量最大的幾個key之后,直接在程式中將那些key給過濾掉,
說下RDD的寬依賴和窄依賴
可靈活回答:
1)Spark的寬依賴和窄依賴,為什么要這么劃分?
RDD和它依賴的parent RDD(s)的關系有兩種不同的型別,窄依賴(narrow dependency)和寬依賴(wide dependency)
1)窄依賴指的是每一個parent RDD的Partition最多被子RDD的一個Partition使用

2)寬依賴指的是多個子RDD的Partition會依賴同一個parent RDD的Partition

Flink
Flink的Exactly Once語意怎么保證
可靈活回答:
1)Flink怎么保證精準一次消費?
2)Flink如何實作Exactly Once?
3)Flink如何保證僅一次語意?
4)Flink的端到端Exactly Once?
Flink跟其他的流計算引擎相比,最突出或者做的最好的就是狀態的管理,什么是狀態呢?比如我們在平時的開發中,需要對資料進行count,sum,max等操作,這些中間的結果(即是狀態)是需要保存的,因為要不斷的更新,這些值或者變數就可以理解為是一種狀態,拿讀取kafka為例,我們需要記錄資料讀取的位置(即是偏移量),并保存offest,這時offest也可以理解為是一種狀態,
Flink是怎么保證容錯恢復的時候保證資料沒有丟失也沒有資料的冗余呢?checkpoint是使Flink 能從故障恢復的一種內部機制,檢查點是 Flink 應用狀態的一個一致性副本,包括了輸入的讀取位點,在發生故障時,Flink 通過從檢查點加載應用程式狀態來恢復,并從恢復的讀取位點繼續處理,就好像什么事情都沒發生一樣,Flink的狀態存盤在Flink的內部,這樣做的好處就是不再依賴外部系統,降低了對外部系統的依賴,在Flink的內部,通過自身的行程去訪問狀態變數,同時會定期的做checkpoint持久化,把checkpoint存盤在一個分布式的持久化系統中,如果發生故障,就會從最近的一次checkpoint中將整個流的狀態進行恢復,
下面通過Flink從Kafka中獲取資料,來說下怎么管理offest實作exactly-once的,
Apache Flink中實作的Kafka消費者是一個有狀態的算子(operator),它集成了Flink的檢查點機制,它的狀態是所有Kafka磁區的讀取偏移量,當一個檢查點被觸發時,每一個磁區的偏移量都被存到了這個檢查點中,Flink的檢查點機制保證了所有operator task的存盤狀態都是一致的,這里的“一致的”是什么意思呢?意思是它們存盤的狀態都是基于相同的輸入資料,當所有的operator task成功存盤了它們的狀態,一個檢查點才算完成,因此,當從潛在的系統故障中恢復時,系統提供了excatly-once的狀態更新語意,
下面我們將一步步地介紹Apache Flink中的 Kafka消費位點是如何做檢查點的,在本文的例子中,資料被存在了Flink的JobMaster中,值得注意的是,在POC或生產用例下,這些資料最好是能存到一個外部檔案系統(如HDFS或S3)中,
第一步: 如下所示,一個Kafka topic,有兩個partition,每個partition都含有 “A”,“B”,“C”,”D”,“E”5條訊息,我們將兩個partition的偏移量(offset)都設定為0,

第二步: Kafka comsumer(消費者)開始從 partition 0 讀取訊息,訊息“A”正在被處理,第一個 consumer 的 offset 變成了1,

第三步: 訊息“A”到達了Flink Map Task,兩個 consumer都開始讀取他們下一條訊息(partition0讀取“B”,partition1讀取“A”),各自將offset更新成2和1,同時,Flink的 JobMaster開始在source觸發了一個檢查點,

第四步: 接下來,由于source觸發了檢查點,Kafka consumer創建了它們狀態的第一個快照(”offset = 2, 1”),并將快照存到了Flink的 JobMaster 中,Source 在訊息“B”和“A”從partition 0 和 1 發出后,發了一個 checkpoint barrier,Checkopint barrier 用于各個 operator task 之間對齊檢查點,保證了整個檢查點的一致性,訊息“A”到達了 Flink Map Task,而上面的 consumer 繼續讀取下一條訊息(訊息“C”),

第五步:
Flink Map Task收齊了同一版本的全部 checkpoint barrier后,那么就會將它自己的狀態也存盤到JobMaster,同時,consumer會繼續從Kafka讀取訊息,

第六步: Flink Map Task完成了它自己狀態的快照流程后,會向Flink JobMaster匯報它已經完成了這個checkpoint,當所有的task都報告完成了它們的狀態checkpoint后,JobMaster就會將這個checkpoint標記為成功,從此刻開始,這個 checkpoint就可以用于故障恢復了,值得一提的是,Flink并不依賴Kafka offset從系統故障中恢復,

故障恢復 在發生故障時(比如,某個worker掛了),所有的operator task會被重啟,而他們的狀態會被重置到最近一次成功的checkpoint,Kafka source分別從offset 2和1重新開始讀取訊息(因為這是完成的checkpoint中存的offset),當作業重啟后,我們可以期待正常的系統操作,就好像之前沒有發生故障一樣,如下圖所示:

Flink的checkpoint是基于Chandy-Lamport演算法的分布式一致性快照,如果想更加深入的了解Flink的checkpoint可以去了解一下這個演算法,
資料倉庫
資料倉庫分層(層級劃分),每層做什么
CIF 層次架構(資訊工廠)通過分層將不同的建模方案引入到不同的層次中,CIF 將資料倉庫分為四層,如圖所示:

這里再給一張專案里面的數倉分層架構

分層優點:復雜問題簡單化、清晰資料結構(方便管理)、增加資料的復用性、隔離原始資料(解耦)
ODS(Operational Data Store):
操作資料存盤層 ,往往是業務資料庫表格的一對一映射,將業務資料庫中的表格在 ODS 重新建立,資料完全一致;
DWD(Data Warehouse Detail):
資料明細層 ,在 DWD 進行資料的清洗、脫敏、統一化等操作,DWD 層的資料是干凈并且具有良好一致性的資料;
DWS(Data Warehouse Service):
服務資料層(公共匯總層) ,在DWS層進行輕度匯總,為DM層中的不同主題提供公用的匯總資料;
DM(Data Market):
資料集市層 ,DM層針對不同的主題進行統計報表的生成,
其它型別
Saprk Streaming和Flink的區別
可靈活回答 :
1)Saprk和Flink的區別
2)Flink和Spark對于批處理的區別?
3)Spark Streaming相比Flink的優劣勢
這個問題是一個非常宏觀的問題,因為兩個框架的不同點非常之多,但是在面試時有非常重要的一點一定要回答出來:Flink是標準的實時處理引擎,基于事件驅動,而Spark Streaming是微批(Micro-Batch)的模型,
下面我們就分幾個方面介紹兩個框架的主要區別:
1)從流處理的角度來講 ,Spark基于微批量處理,把流資料看成是一個個小的批處理資料塊分別處理,所以延遲性只能做到秒級,而Flink基于每個事件處理,每當有新的資料輸入都會立刻處理,是真正的流式計算,支持毫秒級計算,由于相同的原因,Spark只支持基于時間的視窗操作(處理時間或者事件時間),而Flink支持的視窗操作則非常靈活,不僅支持時間視窗,還支持基于資料本身的視窗(另外還支持基于time、count、session,以及data-driven的視窗操作),開發者可以自由定義想要的視窗操作,
2)從SQL 功能的角度來講 ,Spark和Flink分別提供SparkSQL和Table APl提供SQL
3)互動支持 ,兩者相比較,Spark對SQL支持更好,相應的優化、擴展和性能更好,而Flink在SQL支持方面還有很大提升空間,
4)從迭代計算的角度來講 ,Spark對機器學習的支持很好,因為可以在記憶體中快取中間計算結果來加速機器學習演算法的運行,但是大部分機器學習演算法其實是一個有環的資料流,在Spark中,卻是用無環圖來表示,而Flink支持在運行時間中的有環資料流,從而可以更有效的對機器學習演算法進行運算,
5)從相應的生態系統角度來講 ,Spark的社區無疑更加活躍,Spark可以說有著Apache旗下最多的開源貢獻者,而且有很多不同的庫來用在不同場景,而Flink由于較新,現階段的開源社區不如Spark活躍,各種庫的功能也不如Spark全面,但是Flink還在不斷發展,各種功能也在逐漸完善,
基礎轉自 https://manor.blog.csdn.net/
原文鏈接:
https://mp.weixin.qq.com/s/2Dzv8uPlvEZz7d_jgB4WPg
侵刪
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/293129.html
標籤:其他
上一篇:史上最全 RabbitMQ入門教程,從零開始帶你深入♂學習(二)——RabbitMQ安裝和使用
下一篇:Kafka之Fetch offset xxx is out of range for partition xxx,resetting offset情況總結
