分佈式消息隊列RocketMQ與Kafka架構上的巨大差異之1 -- 爲什麼RocketMQ要去除ZK依賴?

我們知道,在早期的RocketMQ版本中,是有依賴ZK的。而現在的版本中,是去掉了對ZK的依賴,轉而使用自己開發的NameSrv。

並且這個NameSrv是無狀態的,你可以隨意的部署多臺,其代碼也非常簡單,非常輕量。

那不禁要問了:ZooKeeper是業界用來管理集羣的一個非常常用的中間件,比如Kafka就是依賴的ZK。那爲什麼RocketMQ要自己造輪子,自己做集羣的管理呢?純粹就是再做一個Zookeeper嗎?

本篇試圖通過一個架構上的巨大差異,來闡述爲什麼RocketMQ可以去掉ZK。

Kafka的架構拓撲圖

我們知道,在Kafka中,是1個topic有多個partition,每個partition有1個master + 多個slave。對應如下圖所示:
這裏寫圖片描述

注意:這裏只有3臺機器(b0,b1,b2),每臺機器既是Master,也是Slave。具體來說,比如機器b0,對於partition0來說,它可能是Master;對應partition1來說,它可能又是Slave。

RocketMQ的架構拓撲圖

不同於Kafka裏面,一臺機器同時是Master和Slave。在RocketMQ裏面,1臺機器只能要麼是Master,要麼是Slave。這個在初始的機器配置裏面,就定死了。其架構拓撲圖如下:

這裏寫圖片描述

在這裏,RocketMQ裏面queue這個概念,就對應Kafka裏面partition。

有3個Master, 6個Slave,那對應到物理上面,就是3+6,得9臺機器!!!而不是上面像Kafka一樣,3臺機器。

Master/Slave/Broker概念上的差異

通過上面2張圖,我們已經可以直觀看出2者的巨大差異。反映到概念上,雖然2者都有Master/Slave/Broker這3個概念,但其含義是不一樣的。

Master/Slave概念差異

Kafka: Master/Slave是個邏輯概念,1臺機器,同時具有Master角色和Slave角色。
RocketMQ: Master/Slave是個物理概念,1臺機器,只能是Master或者Slave。在集羣初始配置的時候,指定死的。其中Master的broker id = 0,Slave的broker id > 0。

Broker概念差異

Kafka: Broker是個物理概念,1個broker就對應1臺機器。
RocketMQ:Broker是個邏輯概念,1個broker = 1個master + 多個slave。所以纔有master broker, slave broker這樣的概念。

那這裏,master和slave是如何配對的呢? 答案是通過broker name。具有同1個broker name的master和slave進行配對。

具體到配置裏面,如下:

//機器1的配置
brokerClusterName=DefaultCluster
brokerName=broker-a
brokerId=0
deleteWhen=04
fileReservedTime=48
brokerRole=ASYNC_MASTER
flushDiskType=ASYNC_FLUSH
      //機器2的配置
      brokerClusterName=DefaultCluster
      brokerName=broker-a
      brokerId=1
      deleteWhen=04
      fileReservedTime=48
      brokerRole=SLAVE
      flushDiskType=ASYNC_FLUSH
          //機器3的配置
          brokerClusterName=DefaultCluster
          brokerName=broker-a
          brokerId=2
          deleteWhen=04
          fileReservedTime=48
          brokerRole=SLAVE
          flushDiskType=ASYNC_FLUSH
              >

            這裏機器1和機器2,機器3具有相同的brokerName(broker-a),一個brokerId = 0,另2個brokerId > 0。所以機器1是Master,機器2, 3是Slave。

            所以這裏可以看出:RokcetMQ和Kafka關於這2對概念的定義,剛好是反過來的!Kafka是先有Broker,然後產生出Master/Slave;RokcetMQ是先定義Master/Slave,然後組合出Broker。

            答案:爲什麼可以去ZK?

            從上面對比可以看出,Kafka和RocketMQ在Master/Slave/Broker這個3個概念上的差異。

            這個差異,也就影響到topic, partition這種邏輯概念和Master/Slave/Broker這些物理概念上的映射關係。具體來講就是:

            在Kafka裏面,Maser/Slave是選舉出來的!!!RocketMQ不需要選舉!!!

            在Kafka裏面,Maser/Slave是選舉出來的!!!RocketMQ不需要選舉!!!

            在Kafka裏面,Maser/Slave是選舉出來的!!!RocketMQ不需要選舉!!!

            重要的話說三篇。具體來說,在Kafka裏面,Master/Slave的選舉,有2步:第1步,先通過ZK在所有機器中,選舉出一個KafkaController;第2步,再由這個Controller,決定每個partition的Master是誰,Slave是誰。

            這裏的Master/Slave是動態的,也就是說:當Master掛了之後,會有1個Slave切換成Master。

            而在RocketMQ中,不需要選舉,Master/Slave的角色也是固定的。當一個Master掛了之後,你可以寫到其他Master上,但不會說一個Slave切換成Master。

            這種簡化,使得RocketMQ可以不依賴ZK就很好的管理Topic/queue和物理機器的映射關係了,也實現了高可用。

            這裏,也涉及到了我在上1篇裏,所說的“消息順序”的問題:在Kafka裏面,一個partition必須與1個Master有嚴格映射關係,這個Master掛了,就要從其他Slave裏面選舉出一個Master;而在RocketMQ裏面,這個限制放開了,一個queue對應的Master掛了,它會切到其他Master,而不是非要選舉出來一個。

            說到這,答案基本就知道了:RocketMQ不需要像Kafka那樣有很重的選舉邏輯,它把這個問題簡化了。剩下的就是topic/queue的路由信息,那用個簡單的NameServer就搞定了,很輕量,還無狀態,可靠性也能得到很好保證。

            Topic的創建過程

            下面從使用的角度,看看Kafka和RocketMQ在創建topic的時候,分別都需要指定什麼參數?

            從這些參數也可以看出,2者的topic, partition這種邏輯概念和物理機器之間的映射關係,有很大不同。

            RocketMQ 創建topic的命令

            下面代碼來自UpdateTopicSubCommand這個類,也就是RocketMq創建topic時,調用的類。這裏有幾個關鍵參數,其他參數我省略了:
            b:
            c: //b和c2選1,b是指定topic所在的機器,c是指定topic所在的cluster

            topic: //這個是基本參數,沒什麼好講的

            readQueueNums/writeQueueNums: //隊列個數。缺省2者相等,是8。關於這個readQueueNums/writeQueueNums,是RocketMQ特有的概念,後面再來詳細分析。此處就認爲他們2者相等,是同1個。

                    Option opt = new Option("b", "brokerAddr", true, "create topic to which broker");
                    opt.setRequired(false);
                    options.addOption(opt);
            
                    opt = new Option("c", "clusterName", true, "create topic to which cluster");
                    opt.setRequired(false);
                    options.addOption(opt);
            
                    opt = new Option("t", "topic", true, "topic name");
                    opt.setRequired(true);
                    options.addOption(opt);
            
                    opt = new Option("r", "readQueueNums", true, "set read queue nums");
                    opt.setRequired(false);
                    options.addOption(opt);
            
                    opt = new Option("w", "writeQueueNums", true, "set write queue nums");
                    opt.setRequired(false);
                    options.addOption(opt);
            
                

                Kafka創建topic的命令

                跟RocketMQ相比,有2個同樣的參數:1個是topic,一個是隊列數目,也就是這裏的–partitions。

                bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 3 --partitions 1 --topic my-replicated-topic

                    2者在創建topic時一個顯著的不同

                    Kafka有一個參數replication-factor,也就是指定給1個Master配幾個Slave?

                    RocketMQ有一個參數c,也就是clusterName,來指定這個cluster裏面,所有的Master和Slave的配對(多個master, 多個slave) 對應同1個topic!!!

                    缺省情況下,所有的Master和Slave屬於同1個集羣,也就是上面的3臺機器配置中的第1個參數:brokerClusterName=DefaultCluster。

                    結合上面的架構拓撲圖,我們就可以看出:
                    對於kafka來說,你指定topic,它的partition個數,它的master/slave配比,然後系統自動從所有機器中,爲每個topic_partition分配1個master + 多個slave;

                    對於RokcetMQ來說,你指定topic,它的queue個數,它對應的cluster。然後系統自動建立這個cluster(多個master + 多個slave) 和你的topic之間的映射關係。

                    發表評論
                    所有評論
                    還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
                    相關文章