序言
說明下安裝環境.在centos7上安裝Kafka集羣環境.
Kafka 依賴Java環境,所以需要提前配置.Kafka有自帶的Zookeeper,但是一般不用.
Zookeeper集羣環境安裝請看另一篇文章.這裏只描述kafka的環境搭建.
名詞解釋
- Broker——Kafka集羣包含一個或多個服務器,這種服務器被稱爲broker ;
- Topic——每條發佈到Kafka集羣的消息都有一個類別,這個類別被稱爲Topic。(物理上不同Topic的消息分開存儲,邏輯上一個Topic的消息雖然保存於一個或多個broker上但用戶只需指定消息的Topic即可生產或消費數據而不必關心數據存於何處)
- Partition——Partition是物理上的概念,每個Topic包含一個或多個Partition.
- Producer——負責發佈消息到Kafka broker
- Consumer——消息消費者,向Kafka broker讀取消息的客戶端。
- Consumer Group——每個Consumer屬於一個特定的Consumer Group(可爲每個Consumer指定group name,若不指定group name則屬於默認的group)。
Kafka的topic可以看做是一個記錄流 ("/orders", "/user-signups"),每個topic都有一個日誌,它存儲在磁盤上。
每個topic又被分成多個partition(區),每個partition在存儲層面是append log文件,任何發佈到partition的消息都會被直接追加到日誌文件的尾部,Kafka Producer API用於生成數據記錄流,Kafka Consumer API用於使用Kafka的記錄流。
topic與日誌相關聯,日誌是存儲在磁盤上的數據結構,Kafka將producer的記錄附加到topic日誌的末尾。topic日誌由分佈在多個文件上的許多分區組成,這些文件可以分佈在多個Kafka集羣節點上。Kafka在集羣的不同節點上分發topic日誌分區,以實現具有水平可伸縮性的高性能。Spreading 分區有助於快速寫入數據,Kafka將分區複製到許多節點以提供故障轉移。
關於Kafka集羣建通信的問題
在Kafka集羣中會有一個或者多個broker,其中有一個broker會被選舉爲控制器(Kafka Controller),它負責管理整個集羣中所有分區和副本的狀態。當某個分區的leader副本出現故障時,由控制器負責爲該分區選舉新的leader副本。當檢測到某個分區的ISR集合發生變化時,由控制器負責通知所有broker更新其元數據信息。當使用kafka-topics.sh腳本爲某個topic增加分區數量時,同樣還是由控制器負責分區的重新分配。
這裏請注意 kafka集羣其實有兩種類型的Leader,切都是由zookeeper選舉產生的.即:Broker的Controller,Partition的Leader.
關於Kafka的高可用性
引入Replication之後,同一個Partition可能會有多個Replica,而這時需要在這些Replication之間選出一個Leader,Producer和Consumer只與這個Leader交互,其它Replica作爲Follower從Leader中複製數據。
因爲需要保證同一個Partition的多個Replica之間的數據一致性(其中一個宕機後其它Replica必須要能繼續服務並且即不能造成數據重複也不能造成數據丟失)。如果沒有一個Leader,所有Replica都可同時讀/寫數據,那就需要保證多個Replica之間互相(N×N條通路)同步數據,數據的一致性和有序性非常難保證,大大增加了Replication實現的複雜性,同時也增加了出現異常的機率。而引入Leader後,只有Leader負責數據讀寫,Follower只向Leader順序Fetch數據(N條通路),系統更加簡單且高效。
爲了更好的做負載均衡,Kafka儘量將所有的Partition均勻分配到整個集羣上。一個典型的部署方式是一個Topic的Partition數量大於Broker的數量。同時爲了提高Kafka的容錯能力,也需要將同一個Partition的Replica儘量分散到不同的機器。實際上,如果所有的Replica都在同一個Broker上,那一旦該Broker宕機,該Partition的所有Replica都無法工作,也就達不到HA的效果。同時,如果某個Broker宕機了,需要保證它上面的負載可以被均勻的分配到其它倖存的所有Broker上。
Producer在發佈消息到某個Partition時,先通過ZooKeeper找到該Partition的Leader,然後無論該Topic的Replication Factor爲多少,Producer只將該消息發送到該Partition的Leader。Leader會將該消息寫入其本地Log。每個Follower都從Leader pull數據。這種方式上,Follower存儲的數據順序與Leader保持一致。Follower在收到該消息並寫入其Log後,向Leader發送ACK。一旦Leader收到了ISR中的所有Replica的ACK,該消息就被認爲已經commit了,Leader將增加HW並且向Producer發送ACK。
爲了提高性能,每個Follower在接收到數據後就立馬向Leader發送ACK,而非等到數據寫入Log中。因此,對於已經commit的消息,Kafka只能保證它被存於多個Replica的內存中,而不能保證它們被持久化到磁盤中,也就不能完全保證異常發生後該條消息一定能被Consumer消費。
Consumer讀消息也是從Leader讀取,只有被commit過的消息纔會暴露給Consumer。
安裝集羣
下載kafka,並解壓.
[root@localhost cuiyaonan]# wget https://mirrors.tuna.tsinghua.edu.cn/apache/kafka/2.3.0/kafka_2.11-2.3.0.tgz
[root@[email protected] kafka]# tar -zxvf kafka_2.11-2.3.0.tgz
[root@[email protected] kafka]# cp -rf kafka_2.11-2.3.0 kafka-01
[root@[email protected] kafka]# cp -rf kafka_2.11-2.3.0 kafka-02
[root@[email protected] kafka]# cp -rf kafka_2.11-2.3.0 kafka-03
然後依次修改config/server.properties
# kafka服務器監聽IP和端口,這裏也可以寫域名,只要能解析就行
listeners=PLAINTEXT://192.168.2.63:9092
# 三臺服務器的ID不能相同,第一臺是1,第二臺是2,第三臺是3
broker.id=1
# 日誌路徑 依次類推k1,k2,k3
log.dirs=/home/cuiyaonan/kafka/logs/k1
# Zookeeper連接參數
zookeeper.connect=192.168.2.64:2181,192.168.2.64:2182,192.168.2.64:2183
另外其他的配置信息如下:
broker.id=0 #當前機器在集羣中的唯一標識,和zookeeper的myid性質一樣
port=19092 #當前kafka對外提供服務的端口默認是9092
host.name=192.168.7.100 #這個參數默認是關閉的,在0.8.1有個bug,DNS解析問題,失敗率的問題。
num.network.threads=3 #這個是borker進行網絡處理的線程數
num.io.threads=8 #這個是borker進行I/O處理的線程數
log.dirs=/opt/kafka/kafkalogs/ #消息存放的目錄,這個目錄可以配置爲“,”逗號分割的表達式,上面的
num.io.threads要大於這個目錄的個數這個目錄,如果配置多個目錄,新創建的topic他把消息持久化的地方是,當前以逗號分割的目錄中,那個分區數最少就放那一個
socket.send.buffer.bytes=102400 #發送緩衝區buffer大小,數據不是一下子就發送的,先回存儲到緩衝區了到達一定的大小後在發送,能提高性能
socket.receive.buffer.bytes=102400 #kafka接收緩衝區大小,當數據到達一定大小後在序列化到磁盤
socket.request.max.bytes=104857600 #這個參數是向kafka請求消息或者向kafka發送消息的請請求的最大數,這個值不能超過java的堆棧大小
num.partitions=1 #默認的分區數,一個topic默認1個分區數
log.retention.hours=168 #默認消息的最大持久化時間,168小時,7天
message.max.byte=5242880 #消息保存的最大值5M
default.replication.factor=2 #kafka保存消息的副本數,如果一個副本失效了,另一個還可以繼續提供服務
replica.fetch.max.bytes=5242880 #取消息的最大直接數
log.segment.bytes=1073741824 #這個參數是:因爲kafka的消息是以追加的形式落地到文件,當超過這個值的時候,kafka會新起一個文件
log.retention.check.interval.ms=300000 #每隔300000毫秒去檢查上面配置的log失效時間
(log.retention.hours=168 ),到目錄查看是否有過期的消息如果有,刪除
log.cleaner.enable=false #是否啓用log壓縮,一般不用啓用,啓用的話可以提高性能
zookeeper.connect=192.168.7.100:12181,192.168.7.101:12181,192.168.7.107:1218
#設置zookeeper的連接端口
依次啓動kafka
[root@[email protected] bin]# ./kafka-server-start.sh -daemon ../config/server.properties
創建與查看Topic
創建命令如下,其中zookeeper 如果是集羣隨便一個就行
[root@cuiyaonan2000 bin]# ./kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 3 --partitions 3 --topic testTopic
查看命令如下(換了個zookeeper查看)
[root@cuiyaonan2000 bin]# ./kafka-topics.sh --list --zookeeper localhost:2182