Kafka叢集搭建及必知必會

馬哥教育發表於2020-11-07

Kafka叢集部署並啟動

在本文中將從演示如何搭建一個Kafka叢集開始,然後簡要介紹一下關於Kafka叢集的一些基礎知識點。但本文僅針對叢集做介紹,對於Kafka的基本概念不做過多說明,這裡假設讀者擁有一定的Kafka基礎知識。

首先,我們需要了解Kafka叢集的一些機制:

  • Kafka是天然支援叢集的,哪怕是一個節點實際上也是叢集模式
  • Kafka叢集依賴於Zookeeper進行協調,並且在早期的Kafka版本中很多資料都是存放在Zookeeper的
  • Kafka節點只要註冊到同一個Zookeeper上就代表它們是同一個叢集的
  • Kafka通過brokerId來區分叢集中的不同節點

Kafka的叢集拓撲圖如下:

Kafka叢集中的幾個角色:

  • Broker:一般指Kafka的部署節點
  • Leader:用於處理訊息的接收和消費等請求,也就是說producer是將訊息push到leader,而consumer也是從leader上去poll訊息
  • Follower:主要用於備份訊息資料,一個leader會有多個follower

在本例中,為了更貼近實際的部署情況,使用了四臺虛擬機器作演示:

機器IP作用角色brokerId
192.168.99.1部署Kafka節點broker server0
192.168.99.2部署Kafka節點broker server1
192.168.99.3部署Kafka節點broker server2
192.168.99.4部署Zookeeper節點叢集協調者

Zookeeper安裝

Kafka是基於Zookeeper來實現分散式協調的,所以在搭建Kafka節點之前需要先搭建好Zookeeper節點。而Zookeeper和Kafka都依賴於JDK,我這裡已經事先安裝好了JDK:

[root@192.168.99.4 ~]# java --version
java 11.0.5 2019-10-15 LTS
Java(TM) SE Runtime Environment 18.9 (build 11.0.5+10-LTS)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.5+10-LTS, mixed mode)
[root@txy-server2 ~]#

準備好JDK環境後,到Zookeeper的官網下載地址,複製下載連結:

  • https://zookeeper.apache.org/releases.html#download

然後到Linux中使用wget命令進行下載,如下:

[root@192.168.99.4 ~]# cd /usr/local/src
[root@192.168.99.4 /usr/local/src]# wget https://mirror.bit.edu.cn/apache/zookeeper/zookeeper-3.6.1/apache-zookeeper-3.6.1-bin.tar.gz

解壓下載好的壓縮包,並將解壓後的目錄移動和重新命名:

[root@192.168.99.4 /usr/local/src]# tar -zxvf apache-zookeeper-3.6.1-bin.tar.gz
[root@192.168.99.4 /usr/local/src]# mv apache-zookeeper-3.6.1-bin ../zookeeper

進入到Zookeeper的配置檔案目錄,將zoo_sample.cfg這個示例配置檔案拷貝一份並命名為zoo.cfg,這是Zookeeper預設的配置檔名稱:

[root@192.168.99.4 /usr/local/src]# cd ../zookeeper/conf/
[root@192.168.99.4 /usr/local/zookeeper/conf]# ls
configuration.xsl  log4j.properties  zoo_sample.cfg
[root@192.168.99.4 /usr/local/zookeeper/conf]# cp zoo_sample.cfg zoo.cfg

修改一下配置檔案中的dataDir配置項,指定一個磁碟空間較大的目錄:

[root@192.168.99.4 /usr/local/zookeeper/conf]# vim zoo.cfg
# 指定Zookeeper的資料儲存目錄,類比於MySQL的dataDir
dataDir=/data/zookeeper
[root@192.168.99.4 /usr/local/zookeeper/conf]# mkdir -p /data/zookeeper

如果只是學習使用的話,這一步其實可以忽略,採用預設配置即可
接下來就可以進入bin目錄,使用啟動指令碼來啟動Zookeeper了,如下示例:

[root@192.168.99.4 /usr/local/zookeeper/conf]# cd ../bin/
[root@192.168.99.4 /usr/local/zookeeper/bin]# ./zkServer.sh start
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
[root@192.168.99.4 /usr/local/zookeeper/bin]#

啟動完成後,可以通過檢視是否正常監聽埠號來判斷是否啟動成功,如下則是啟動成功了:

[root@192.168.99.4 ~]# netstat -lntp |grep 2181
tcp6       0      0 :::2181       :::*         LISTEN      7825/java
[root@192.168.99.4 ~]#

如果你的機器開啟了防火牆的話,則需要開放Zookeeper的埠,否則其他節點無法註冊上來:

[root@192.168.99.4 ~]# firewall-cmd --zone=public --add-port=2181/tcp --permanent
[root@192.168.99.4 ~]# firwall-cmd --reload

Kafka安裝

安裝完Zookeeper後,接下來就可以安裝Kafka了,同樣的套路首先去Kafka的官網下載地址,複製下載連結:

  • https://zookeeper.apache.org/releases.html#download

然後到Linux中使用wget命令進行下載,如下:

[root@192.168.99.1 ~]# cd /usr/local/src
[root@192.168.99.1 /usr/local/src]# wget https://mirror.bit.edu.cn/apache/kafka/2.5.0/kafka_2.13-2.5.0.tgz

解壓下載好的壓縮包,並將解壓後的目錄移動和重新命名:

[root@192.168.99.1 /usr/local/src]# tar -xvf kafka_2.13-2.5.0.tgz
[root@192.168.99.1 /usr/local/src]# mv kafka_2.13-2.5.0 ../kafka

進入Kafka的配置檔案目錄,修改配置檔案:

[root@192.168.99.1 /usr/local/src]# cd ../kafka/config/
[root@192.168.99.1 /usr/local/kafka/config]# vim server.properties
# 指定該節點的brokerId,同一叢集中的brokerId需要唯一
broker.id=0
# 指定監聽的地址及埠號,該配置項是指定內網ip
listeners=PLAINTEXT://192.168.99.1:9092
# 如果需要開放外網訪問,則在該配置項指定外網ip
advertised.listeners=PLAINTEXT://192.168.99.1:9092
# 指定kafka日誌檔案的儲存目錄
log.dirs=/usr/local/kafka/kafka-logs
# 指定zookeeper的連線地址,若有多個地址則用逗號分隔
zookeeper.connect=192.168.99.4:2181
[root@192.168.99.1 /usr/local/kafka/config]# mkdir /usr/local/kafka/kafka-logs

在完成配置檔案的修改後,為了方便使用Kafka的命令指令碼,我們可以將Kafka的bin目錄配置到環境變數中:

[root@192.168.99.1 ~]# vim /etc/profile
export KAFKA_HOME=/usr/local/kafka
export PATH=$PATH:$KAFKA_HOME/bin
[root@192.168.99.1 ~]# source /etc/profile  # 讓配置生效

這樣就可以使用如下命令啟動Kafka了:

[root@192.168.99.1 ~]# kafka-server-start.sh /usr/local/kafka/config/server.properties &

執行以上命令後,啟動日誌會輸出到控制檯,可以通過日誌判斷是否啟動成功,也可以通過檢視是否監聽了9092埠來判斷是否啟動成功:

[root@192.168.99.1 ~]# netstat -lntp |grep 9092
tcp6    0     0 192.168.99.1:9092     :::*      LISTEN     31943/java
[root@192.168.99.1 ~]#

同樣的,開啟了防火牆的話,還需要開放相應的埠號:

[root@192.168.99.1 ~]# firewall-cmd --zone=public --add-port=9092/tcp --permanent
[root@192.168.99.1 ~]# firwall-cmd --reload

到此為止,我們就完成了第一個Kafka節點的安裝,另外兩個節點的安裝步驟也是一樣的,只需要修改一下配置檔案中的brokerId和監聽的ip就好了。所以我這裡直接將該節點中的Kafka目錄拷貝到另外兩臺機器上:

[root@192.168.99.1 ~]# rsync -av /usr/local/kafka 192.168.99.2:/usr/local/kafka
[root@192.168.99.1 ~]# rsync -av /usr/local/kafka 192.168.99.3:/usr/local/kafka

然後修改一下這兩個節點的brokerId和監聽的ip:

[root@192.168.99.2 /usr/local/kafka/config]# vim server.properties
# 修改brokerId
broker.id=1
# 指定監聽的地址及埠號,該配置項是指定內網ip
listeners=PLAINTEXT://192.168.99.2:9092
# 如果需要開放外網訪問,則在該配置項指定外網ip
advertised.listeners=PLAINTEXT://192.168.99.2:9092
[root@192.168.99.2 /usr/local/kafka/config]# 
[root@192.168.99.3 /usr/local/kafka/config]# vim server.properties
# 修改brokerId
broker.id=2
# 指定監聽的地址及埠號,該配置項是指定內網ip
listeners=PLAINTEXT://192.168.99.3:9092
# 如果需要開放外網訪問,則在該配置項指定外網ip
advertised.listeners=PLAINTEXT://192.168.99.3:9092
[root@192.168.99.3 /usr/local/kafka/config]# 

配置修改完成後,按之前所介紹的步驟啟動這兩個節點。啟動成功後進入Zookeeper中,在/brokers/ids下有相應的brokerId資料代表叢集搭建成功:

[root@192.168.99.4 ~]# /usr/local/zookeeper/bin/zkCli.sh
[zk: localhost:2181(CONNECTED) 4] ls /brokers/ids
[0, 1, 2]
[zk: localhost:2181(CONNECTED) 5]

Kafka副本集

關於Kafka的副本集:

  • Kafka副本集是指將日誌複製多份,我們知道Kafka的資料是儲存在日誌檔案中的,這就相當於資料的備份、冗餘
  • Kafka可以通過配置設定預設的副本集數量
  • Kafka可以為每個Topic設定副本集,所以副本集是相對於Topic來說的
  • 一個Topic的副本集可以分佈在多個Broker中,當一個Broker掛掉了,其他的Broker上還有資料,這就提高了資料的可靠性,這也是副本集的主要作用。

我們都知道在Kafka中的Topic只是個邏輯概念,實際儲存資料的是Partition,所以真正被複制的也是Partition。如下圖:

關於副本因子:

  • 副本因子其實決定了一個Partition的副本數量,例如副本因子為1,則代表將Topic中的所有Partition按照Broker的數量複製一份,並分佈到各個Broker上

副本分配演算法如下:

  • 將所有N Broker和待分配的i個Partition排序
  • 將第i個Partition分配到第(i mod n)個Broker上
  • 將第i個Partition的第j個副本分配到第((i + j) mod n)個Broker上

Kafka節點故障原因及處理方式

Kafka節點(Broker)故障的兩種情況:

  • Kafka節點與Zookeeper心跳未保持視為節點故障
  • 當follower的訊息落後於leader太多也會視為節點故障

Kafka對節點故障的處理方式:

  • Kafka會對故障節點進行移除,所以基本不會因為節點故障而丟失資料
  • Kafka的語義擔保也很大程度上避免了資料丟失
  • Kafka會對訊息進行叢集內平衡,減少訊息在某些節點熱度過高

Kafka Leader選舉機制簡介

Kafka叢集之Leader選舉:

  • 如果有接觸過其他一些分散式元件就會了解到大部分元件都是通過投票選舉來在眾多節點中選舉出一個leader,但在Kafka中沒有采用投票選舉來選舉leader
  • Kafka會動態維護一組Leader資料的副本(ISR)
  • Kafka會在ISR中選擇一個速度比較快的設為leader

“巧婦難為無米之炊”:Kafka有一種無奈的情況,就是ISR中副本全部當機。對於這種情況,Kafka預設會進行unclean leader選舉。Kafka提供了兩種不同的方式進行處理:

  1. 等待ISR中任一Replica恢復,並選它為Leader
  • 等待時間較長,會降低可用性,或ISR中的所有Replica都無法恢復或者資料丟失,則該Partition將永不可用
  1. 選擇第一個恢復的Replica為新的Leader,無論它是否在ISR中
  • 並未包含所有已被之前Leader Commit過的訊息,因此會造成資料丟失,但可用性較高

Leader選舉配置建議:

  • 禁用unclean leader選舉
  • 手動設定最小ISR

關於ISR更詳細的內容可以參考:

  • https://www.jianshu.com/p/ff296d51385a
  • https://blog.csdn.net/qq_37502106/article/details/80271800

原文連結:https://www.jianshu.com/p/cc0b90636715 作者:端碗吹水

相關文章