直接貼面試題:
怎么保證數據 kafka 里的數據安全?
答:
- 生產者數據的不丟失kafka 的 ack 機制:
- 在 kafka 發送數據的時候,每次發送消息都會有一個確認反饋機制,確保消息正常的能夠被收到。
- 如果是同步模式:ack 機制能夠保證數據的不丟失,如果 ack 設置為 0,風險很大,一般不建議設置為 0
- 如果是異步模式:通過 buffer 來進行控制數據的發送,有兩個值來進行控制,時間閾值與消息的數量閾值,如果 buffer 滿了數據還沒有發送出去,如果設置的是立即清理模式,風險很大,一定要設置為阻塞模式結論:producer 有丟數據的可能,但是可以通過配置保證消息的不丟失
5.消費者數據的不丟失通過 offset commit 來保證數據的不丟失,kafka 自己記錄了每次消費的 offset 數值,下次繼續消費的時候,接着上次的 offset 進行消費即可。
kafka 的 key 為 null 可以嗎
答:
①kafka producer 發送消息的時候,可以指定 key,這個 key 的作用是為消息選擇存儲分區,key 可以為空,當指定 key 且不為空的時候,kafka 是根據 key 的 hash 值與分區數取模來決定數據存儲到那個分區
②當 key=null 時,kafka 是先從緩存中取分區號,然后判斷緩存的值是否為空,如果不為空,就將消息存到這個分區,否則重新計算要存儲的分區,並將分區號緩存起來,供下次使用。
③ kafka 定 義 了 一 個 全 局 變 量 , 這 個 變 量 值 是 配 置 參 數 中 的topic.metadata.refresh.interval.ms 設置的值,也就是說在這個時間內,key=null 的消息都會往緩存起來的這個分區存儲,當時緩存過時之后,就會重新計算分區號,將計算結果緩存起來。也就是說在key為null的情況下,Kafka並不是每條消息都隨機選擇一個Partition;而是每隔 topic.metadata.refresh.interval.ms 才會隨機選擇一次!
kafka 為什么要分多個 partition?
答:Kafka 可以將主題划分為多個分區(Partition),會根據分區規則選擇把消息存儲到哪個分區中,只要如果分區規則設置的合理,那么所有的消息將會被均勻的分布到不同的分區中,這樣就實現了負載均衡和水平擴展。另外,多個訂閱者可以從一個或者多個分區中同時消費數據,以支撐海量數據處理能力:
Kafka 底層如何存儲?
Kafka 中的 message 是以 topic 為基本單位進行組織的,不同的 topic 之間是相互獨立的。每個 topic 又可以分為不同的 partition,每個 partition 存儲一部分的 message 信息。 Partition 是以文件的形式存儲在文件系統中,比如,創建了一個名為 test 的 topic,其有 5 個 partition,那么在 Kafka 的數據目錄中(由配置文件中的 log.dirs 指定的)中就會有這樣 5 個 目 錄 : test-0 , test-1 , test-2 , test-3 , test-4 , 其 命 名 規 則 為,,里面存儲的分別就是這 5 個 partition 的數據。Partition中的每條 Message 由 offset 來表示它在這個 partition 中的偏移量,這個 offset 不是該Message 在 partition 數據文件中的實際存儲位置,而是邏輯上一個值,它唯一確定了partition 中的一條 Message。因此,可以認為 offset 是 partition 中 Message 的 id。partition 中的每條 Message 包含了以下三個屬性:offset / MessageSize / data。
flume 與 kafka 區別
(1)kafka 和 flume 都是日志系統。kafka 是分布式消息中間件,自帶存儲,提供 push 和 pull 存取數據功能,是一個非常通用的系統,可以有許多生產者和很多的消費者共享多個主題 Topics。flume 分為 agent(數據采集器)[source channel sink]。是管道流方式,提供了很多的默認實現,讓用戶通過參數部署,及擴展 API.
(2)kafka 做日志緩存應該是更為合適的,但是 flume 的數據采集部分做的很好,可以定制很多數據源,減少開發量。所以比較流行 flume+kafka 模式,如果為了利用 flume 寫hdfs 的能力,也可以采用 kafka+flume 的方式。
kafka 的數據存在內存還是磁盤?為什么說它吞吐量大?怎么保證數不丟失?
Kafka 的數據最終是落地到磁盤上的。存數據會先存到一個 Topic 主題之下,一個 Topic 可以認為是一類消息,每個 topic 將被分成多個 partition(區),每個 partition 在存儲層面是append log 文件。任何發布到此 partition 的消息都會被直接追加到 log 文件的尾部,每條消息在文件中的位置稱為 offset(偏移量),offset 為一個 long 型數字,它是唯一標記一條消息。為了保證數據不丟失,需要將存儲到每個 partion 上的數據進行備份,並且備份的數據其他的多台服務器上,每個 partition 都有一個 server 為"leader";leader 負責所有的讀寫操作,如果 leader 失效,那么將會有其他 follower 來接管(成為新的 leader);follower 只是單調的和 leader 跟進,同步消息即可..由此可見作為 leader 的 server 承載了全部的請求壓力,因此從集群的整體考慮,有多少個 partitions 就意味着有多少個"leader",kafka 會將"leader"均衡的分散在每個實例上,來確保整體的性能穩定.
Kafka 如何手動取數據?
kafka 的可以接受的數據來源非常廣泛,可以是服務器日志,也可以是數據庫中的數據,甚至你可以自己編寫 python 腳本往 kafka 發送自己構造的數據。kafka 是一個開源產品,提供 api 接口,常見的就是 post 到 kafka 所在機器的 ip+port/url。 他是一個產品,不是一個庫。
有很多消息隊列技術,為什么選擇 kafka?
Kafka 是分布式的消息隊列系統,數據放在分區中,可並發執行,先進先出,數據有序,有producers 生產和 consumers 消費順序kafka 集群有多個 Broker 服務器組成,每個類型的消息被定義為 topic。先有 topic 主題后有分區,分區散列在不同的節點上同一 topic 內部的消息按照一定的 key 和算法被分區(partition)存儲在不同的 Broker 上。消息生產者 producer 和消費者 consumer 可以在多個 Broker 上生產/消費 topicKafka 遵循主從架構由 Zookeeper 維護,只保證單分區內的數據有序(offset 保證數據的有序性)對於每個 partition 都有副本
kafka 是一個分布式的消息系統。那為什么要在我們的數據處理平台中使用這樣的一個消息系統呢?消息系統能給我們帶來什么樣的好處呢??
(1) 解耦
在項目啟動之初來預測將來項目會碰到什么需求,是極其困難的。消息系統在處理過程中間插入了一個隱含的、基於數據的接口層,兩邊的處理過程都要實現這一接口。這允許你獨立的擴展或修改兩邊的處理過程,只要確保它們遵守同樣的接口約束。
(2) 冗余
有些情況下,處理數據的過程會失敗。除非數據被持久化,否則將造成丟失。消息隊列把數據進行持久化直到它們已經被完全處理,通過這一方式規避了數據丟失風險。許多消息隊列所采用的"插入-獲取-刪除"范式中,在把一個消息從隊列中刪除之前,需要你的處理系統明確的指出該消息已經被處理完畢,從而確保你的數據被安全的保存直到你使用完畢。
(3) 擴展性
因為消息隊列解耦了你的處理過程,所以增大消息入隊和處理的頻率是很容易的,只要另外增加處理過程即可。不需要改變代碼、不需要調節參數。擴展就像調大電力按鈕一樣簡單。
(4) 靈活性 & 峰值處理能力
在訪問量劇增的情況下,應用仍然需要繼續發揮作用,但是這樣的突發流量並不常見;如果為以能處理這類峰值訪問為標准來投入資源隨時待命無疑是巨大的浪費。使用消息隊列能夠使關鍵組件頂住突發的訪問壓力,而不會因為突發的超負荷的請求而完全崩潰。
(5) 順序保證
在大多使用場景下,數據處理的順序都很重要。大部分消息隊列本來就是排序的,並且能保證數據會按照特定的順序來處理。Kafka 保證一個 Partition 內的消息的有序性。
(6) 緩沖
在任何重要的系統中,都會有需要不同的處理時間的元素。例如,加載一張圖片比應用過濾器花費更少的時間。消息隊列通過一個緩沖層來幫助任務最高效率的執行———寫入隊列的處理會盡可能的快速。該緩沖有助於控制和優化數據流經過系統的速度。
Kafka消費過的消息如何再消費?
1、kafka消費消息的offffset是定義在zookeeper中的
2、如果想重復消費kafka的消息,可以在redis中自己記錄offffset的checkpoint點(n個)
3、當想重復消費消息時,通過讀取redis中的checkpoint點進行zookeeper的offffset重設
4、這樣就可以達到重復消費消息的目的了
kafka的運行原理:
1 請求元數據,(開始的時候metadata中沒有元數據信息)
2 Sender networkclient 向kafkacluster 中的 brokerserver中獲取元數據的信息
3 對metadata更新topic的元數據 ,topic的元數據及相關分區,每個分區對應所在的機器
對record進行分區,Metadata的元數據中有topic topic中的有分區 用來維護topic的元數據信
4 Record進行分區,partitioner分區,默認default的分區,如果record有分區信號, 則按照分區信號進行分區,如果沒有分區信號,record中的value為 (key: value)類型,以key的hash值進行分區, 如果非key、value類型的,則進行輪詢分區
5 講分區完的數據進入到recordaccumulator往后進行追加,根據分區類型。會有一定的判斷,當數據量達到一定的數量的時候,將數據發往kafka集群中去,(為了使得性能更好一點,不是來一條數據就發,先將數據放入到recordaccumulator內存中,網絡有開銷。來一條數據先放入produce的內存中去,——
6 根據規則拿到需要發送的records ( 規則: 數據量的大小,以及拿到分區所在的node中。)
7 將相應的分區數據發送到node。由sender進行。
Kafka數據安全性體現在哪?
1.生產者數據的不丟失
kafka的ack機制:在kafka發送數據的時候,每次發送消息都會有一個確認反饋機制,確保消息正常的能夠被收到,其中狀態有0,1,-1。
如果是同步模式:ack機制能夠保證數據的不丟失,如果ack設置為0,風險很大,一般不建議設置為0。即使設置為1,也會隨着leader宕機丟失數據。
producer.type=sync
request.required.acks=1
如果是異步模式:也會考慮ack的狀態,除此之外,異步模式下的有個buffffer,通過buffffer來進行控制數據的發送,有兩個值來進行控制,時間閾值與消息的數量閾值,如果buffffer滿了數據還沒有發送出去,有個選項是配置是否立即清空buffffer。可以設置為-1,永久阻塞,也就數據不再生產。
異步模式下,即使設置為-1。也可能因為程序員的不科學操作,操作數據丟失,比如kill -9,但這
是特別的例外情況。
producer.type=async
request.required.acks=1
queue.buffering.max.ms=5000
queue.buffering.max.messages=10000
queue.enqueue.timeout.ms = -1
batch.num.messages=200
結論:producer有丟數據的可能,但是可以通過配置保證消息的不丟失。
2.消費者數據的不丟失
通過offffset commit 來保證數據的不丟失,kafka自己記錄了每次消費的offffset數值,下次繼續消費的時候,會接着上次的offffset進行消費。
而offffset的信息在kafka0.8版本之前保存在zookeeper中,在0.8版本之后保存到topic中,即使消費者在運行過程中掛掉了,再次啟動的時候會找到offffset的值,找到之前消費消息的位置,接着消費,由於offffset的信息寫入的時候並不是每條消息消費完成后都寫入的,所以這種情況有可能會造成重復消費,
但是不會丟失消息。
唯一例外的情況是,我們在程序中給原本做不同功能的兩個consumer組設置KafkaSpoutConfifig.bulider.setGroupid的時候設置成了一樣的groupid,這種情況會導致這兩個組共享同一份數據,就會產生組A消費partition1,partition2中的消息,組B消費partition3的消息,這樣每個組消費的消息都會丟失,都是不完整的。 為了保證每個組都獨享一份消息數據,groupid一定不要重復才行。
3.kafka集群中的broker的數據不丟失
每個broker中的partition我們一般都會設置有replication(副本)的個數,生產者寫入的時候首先根據分發策略(有partition按partition,有key按key,都沒有輪詢)寫入到leader中,follower(副本)再跟leader同步數據,這樣有了備份,也可以保證消息數據的不丟失。