大数据开发超高频面试题!大厂面试必看!包含Hadoop、zookeeper、Hive、flume、kafka、Hbase、flink、spark、数仓等
大數據開發面試題
包含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
侵刪
總結
以上是生活随笔為你收集整理的大数据开发超高频面试题!大厂面试必看!包含Hadoop、zookeeper、Hive、flume、kafka、Hbase、flink、spark、数仓等的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android 第三方社区,从友盟微社区
- 下一篇: 4K分辨率火狐浏览器宋体过细解决方法