2.RocketMQ的安裝與啟動
一、基本概念
1 訊息(Message)
訊息是指,訊息系統所傳輸資訊的物理載體,生產和消費資料的最小單位,每條訊息必須屬於一個主題。
2 主題(Topic)
Topic表示一類訊息的集合,每個主題包含若干條訊息,每條訊息只能屬於一個主題,是RocketMQ進行訊息訂閱的基本單位。 topic:message 1:n message:topic 1:1
一個生產者可以同時傳送多種Topic的訊息;而一個消費者只對某種特定的Topic感興趣,即只可以訂閱 和消費一種Topic的訊息。 producer:topic 1:n consumer:topic 1:1
3 標籤(Tag)
為訊息設定的標籤,用於同一主題下區分不同型別的訊息。來自同一業務單元的訊息,可以根據不同業務目的在同一主題下設定不同標籤。標籤能夠有效地保持程式碼的清晰度和連貫性,並優化RocketMQ提供的查詢系統。消費者可以根據Tag實現對不同子主題的不同消費邏輯,實現更好的擴充套件性。
Topic是訊息的一級分類,Tag是訊息的二級分類。
- Topic:貨物
- tag=上海
- tag=江蘇
- tag=浙江
------- 消費者 -----
- topic=貨物 tag = 上海
- topic=貨物 tag = 上海|浙江
- topic=貨物 tag = *
4 佇列(Queue)
儲存訊息的物理實體。一個Topic中可以包含多個Queue,每個Queue中存放的就是該Topic的訊息。一個Topic的Queue也被稱為一個Topic中訊息的分割槽(Partition)。
一個Topic的Queue中的訊息只能被一個消費者組中的一個消費者消費。一個Queue中的訊息不允許同一個消費者組中的多個消費者同時消費。
在學習參考其它相關資料時,還會看到一個概念:分片(Sharding)。分片不同於分割槽。在RocketMQ中,分片指的是存放相應Topic的Broker。每個分片中會創建出相應數量的分割槽,即Queue,每個Queue的大小都是相同的。
5 訊息標識(MessageId/Key)
RocketMQ中每個訊息擁有唯一的MessageId,且可以攜帶具有業務標識的Key,以方便對訊息的查詢。不過需要注意的是,MessageId有兩個:在生產者send()訊息時會自動生成一個MessageId(msgId),當訊息到達Broker後,Broker也會自動生成一個MessageId(offsetMsgId)。msgId、offsetMsgId與key都稱為訊息標識。
- msgId:由producer端生成,其生成規則為:producerIp + 程序pid + MessageClientIDSetter類的ClassLoader的hashCode +當前時間 + AutomicInteger自增計數器
- offsetMsgId:由broker端生成,其生成規則為:brokerIp + 物理分割槽的offset(Queue中的偏移量)
- key:由使用者指定的業務相關的唯一標識
二、系統架構
RocketMQ架構上主要分為四部分構成:
1 Producer
訊息生產者,負責生產訊息。Producer通過MQ的負載均衡模組選擇相應的Broker叢集佇列進行訊息投 遞,投遞的過程支援快速失敗並且低延遲。
例如,業務系統產生的日誌寫入到MQ的過程,就是訊息生產的過程
再如,電商平臺中使用者提交的秒殺請求寫入到MQ的過程,就是訊息生產的過程
RocketMQ中的訊息生產者都是以生產者組(Producer Group)的形式出現的。生產者組是同一類生產者的集合,這類Producer傳送相同Topic型別的訊息。一個生產者組可以同時傳送多個主題的訊息。
2 Consumer
訊息消費者,負責消費訊息。一個訊息消費者會從Broker伺服器中獲取到訊息,並對訊息進行相關業務處理。
例如,QoS系統從MQ中讀取日誌,並對日誌進行解析處理的過程就是訊息消費的過程。
再如,電商平臺的業務系統從MQ中讀取到秒殺請求,並對請求進行處理的過程就是訊息消費的過程。
RocketMQ中的訊息消費者都是以消費者組(Consumer Group)的形式出現的。消費者組是同一類消費者的集合,這類Consumer消費的是同一個Topic型別的訊息。消費者組使得在訊息消費方面,實現負載均衡(將一個Topic中的不同的Queue平均分配給同一個Consumer Group的不同的Consumer,注意,並不是將訊息負載均衡)和容錯(一個Consmer掛了,該Consumer Group中的其它Consumer可以接著消費原Consumer消費的Queue)的目標變得非常容易。
消費者組中Consumer的數量應該小於等於訂閱Topic的Queue數量。如果超出Queue數量,則多出的Consumer將不能消費訊息。
不過,一個Topic型別的訊息可以被多個消費者組同時消費。
注意,
- 1 )消費者組只能消費一個Topic的訊息,不能同時消費多個Topic訊息
- 2 )一個消費者組中的消費者必須訂閱完全相同的Topic
3 Name Server
功能介紹
NameServer是一個Broker與Topic路由的註冊中心,支援Broker的動態註冊與發現。
RocketMQ的思想來自於Kafka,而Kafka是依賴了Zookeeper的。所以,在RocketMQ的早期版本,即在MetaQ v1.0與v2.0版本中,也是依賴於Zookeeper的。從MetaQ v3.0,即RocketMQ開始去掉了Zookeeper依賴,使用了自己的NameServer。
主要包括兩個功能:
Broker管理:
接受Broker叢集的註冊資訊並且儲存下來作為路由資訊的基本資料;提供心跳檢測機制,檢查Broker是否還存活。路由資訊管理:
每個NameServer中都儲存著Broker叢集的整個路由資訊和用於客戶端查詢的佇列資訊。Producer和Conumser通過NameServer可以獲取整個Broker叢集的路由資訊,從而進行訊息的投遞和消費。
路由註冊
NameServer通常也是以叢集的方式部署,不過,NameServer是無狀態的,即NameServer叢集中的各個節點間是無差異的,各節點間相互不進行資訊通訊。那各節點中的資料是如何進行資料同步的呢?在Broker節點啟動時,輪詢NameServer列表,與每個NameServer節點建立長連線,發起註冊請求。在NameServer內部維護著一個Broker列表,用來動態儲存Broker的資訊。
注意,這是與其它像zk、Eureka、Nacos等註冊中心不同的地方。
這種NameServer的無狀態方式,有什麼優缺點:
優點:NameServer叢集搭建簡單,擴容簡單。
缺點:對於Broker,必須明確指出所有NameServer地址。否則未指出的將不會去註冊。也正因為如此,NameServer並不能隨便擴容。因為,若Broker不重新配置,新增的NameServer對於Broker來說是不可見的,其不會向這個NameServer進行註冊。
Broker節點為了證明自己是活著的,為了維護與NameServer間的長連線,會將最新的資訊以心跳包的方式上報給NameServer,每 30 秒傳送一次心跳。心跳包中包含 BrokerId、Broker地址(IP+Port)、Broker名稱、Broker所屬叢集名稱等等。NameServer在接收到心跳包後,會更新心跳時間戳,記錄這個Broker的最新存活時間。
路由剔除
由於Broker關機、宕機或網路抖動等原因,NameServer沒有收到Broker的心跳,NameServer可能會將其從Broker列表中剔除。
NameServer中有一個定時任務,每隔 10 秒就會掃描一次Broker表,檢視每一個Broker的最新心跳時間戳距離當前時間是否超過 120 秒,如果超過,則會判定Broker失效,然後將其從Broker列表中剔除。
擴充套件:對於RocketMQ日常運維工作,例如Broker升級,需要停掉Broker的工作。OP需要怎麼做?
OP需要將Broker的讀寫許可權禁掉。一旦client(Consumer或Producer)向broker傳送請求,都會收到broker的NO_PERMISSION響應,然後client會進行對其它Broker的重試。
當OP觀察到這個Broker沒有流量後,再關閉它,實現Broker從NameServer的移除。
OP:運維工程師
SRE:Site Reliability Engineer,現場可靠性工程師
路由發現
RocketMQ的路由發現採用的是Pull模型。當Topic路由資訊出現變化時,NameServer不會主動推送給客戶端,而是客戶端定時拉取主題最新的路由。預設客戶端每 30 秒會拉取一次最新的路由。
擴充套件:
1 )Push模型:推送模型。其實時性較好,是一個“釋出-訂閱”模型,需要維護一個長連線。而長連線的維護是需要資源成本的。該模型適合於的場景:
* 實時性要求較高
* Client數量不多,Server資料變化較頻繁
2 )Pull模型:拉取模型。存在的問題是,實時性較差。
3 )Long Polling模型:長輪詢模型。其是對Push與Pull模型的整合,充分利用了這兩種模型的優勢,遮蔽了它們的劣勢。
客戶端NameServer選擇策略
這裡的客戶端指的是Producer與Consumer
客戶端在配置時必須要寫上NameServer叢集的地址,那麼客戶端到底連線的是哪個NameServer節點呢?客戶端首先會生產一個隨機數,然後再與NameServer節點數量取模,此時得到的就是所要連線的節點索引,然後就會進行連線。如果連線失敗,則會採用round-robin策略,逐個嘗試著去連線其它節點。
首先採用的是隨機策略
進行的選擇,失敗後採用的是輪詢策略
。
擴充套件:Zookeeper Client是如何選擇Zookeeper Server的?
簡單來說就是,經過兩次Shufæe,然後選擇第一臺Zookeeper Server。
詳細說就是,將配置檔案中的zk server地址進行第一次shufæe,然後隨機選擇一個。這個選擇出的一般都是一個hostname。然後獲取到該hostname對應的所有ip,再對這些ip進行第二次shufæe,從shufæe過的結果中取第一個server地址進行連線。
4 Broker
功能介紹
Broker充當著訊息中轉角色,負責儲存訊息、轉發訊息。Broker在RocketMQ系統中負責接收並存儲從生產者傳送來的訊息,同時為消費者的拉取請求作準備。Broker同時也儲存著訊息相關的元資料,包括消費者組消費進度偏移offset、主題、佇列等。
Kafka 0.8版本之後,offset是存放在Broker中的,之前版本是存放在Zookeeper中的。
模組構成
下圖為Broker Server的功能模組示意圖。
Remoting Module
:整個Broker的實體,負責處理來自clients端的請求。而這個Broker實體則由以下模組構成。
Client Manager:
客戶端管理器。負責接收、解析客戶端(Producer/Consumer)請求,管理客戶端。例如,維護Consumer的Topic訂閱資訊
Store Service:
儲存服務。提供方便簡單的API介面,處理訊息儲存到物理硬碟和訊息查詢功能。
HA Service:
高可用服務,提供Master Broker 和 Slave Broker之間的資料同步功能。
Index Service:
索引服務。根據特定的Message key,對投遞到Broker的訊息進行索引服務,同時也提供根據Message Key對訊息進行快速查詢的功能。
叢集部署
為了增強Broker效能與吞吐量,Broker一般都是以叢集形式出現的。各叢集節點中可能存放著相同Topic的不同Queue。不過,這裡有個問題,如果某Broker節點宕機,如何保證資料不丟失呢?其解決方案是,將每個Broker叢集節點進行橫向擴充套件,即將Broker節點再建為一個HA叢集,解決單點問題。
Broker節點叢集是一個主從叢集,即叢集中具有Master與Slave兩種角色。Master負責處理讀寫操作請求,Slave負責對Master中的資料進行備份。當Master掛掉了,Slave則會自動切換為Master去工作。所以這個Broker叢集是主備叢集。一個Master可以包含多個Slave,但一個Slave只能隸屬於一個Master。Master與Slave 的對應關係是通過指定相同的BrokerName、不同的BrokerId 來確定的。BrokerId為 0 表示Master,非 0 表示Slave。每個Broker與NameServer叢集中的所有節點建立長連線,定時註冊Topic資訊到所有NameServer。
5 工作流程
具體流程
-
1 )啟動NameServer,NameServer啟動後開始監聽埠,等待Broker、Producer、Consumer連線。
-
2 )啟動Broker時,Broker會與所有的NameServer建立並保持長連線,然後每 30 秒向NameServer定時傳送心跳包。
-
3 )傳送訊息前,可以先建立Topic,建立Topic時需要指定該Topic要儲存在哪些Broker上,當然,在建立Topic時也會將Topic與Broker的關係寫入到NameServer中。不過,這步是可選的,也可以在傳送訊息時自動建立Topic。
-
4 )Producer傳送訊息,啟動時先跟NameServer叢集中的其中一臺建立長連線,並從NameServer中獲取路由資訊,即當前傳送的Topic訊息的Queue與Broker的地址(IP+Port)的對映關係。然後根據演算法策略從隊選擇一個Queue,與佇列所在的Broker建立長連線從而向Broker發訊息。當然,在獲取到路由資訊後,Producer會首先將路由資訊快取到本地,再每 30 秒從NameServer更新一次路由資訊。
-
5 )Consumer跟Producer類似,跟其中一臺NameServer建立長連線,獲取其所訂閱Topic的路由資訊,然後根據演算法策略從路由資訊中獲取到其所要消費的Queue,然後直接跟Broker建立長連線,開始消費其中的訊息。Consumer在獲取到路由資訊後,同樣也會每 30 秒從NameServer更新一次路由資訊。不過不同於Producer的是,Consumer還會向Broker傳送心跳,以確保Broker的存活狀態。
Topic的建立模式
手動建立Topic時,有兩種模式:
- 叢集模式:該模式下建立的Topic在該叢集中,所有Broker中的Queue數量是相同的。
- Broker模式:該模式下建立的Topic在該叢集中,每個Broker中的Queue數量可以不同。
自動建立Topic時,預設採用的是Broker模式,會為每個Broker預設建立 4 個Queue。
讀/寫佇列
從物理上來講,讀/寫佇列是同一個佇列。所以,不存在讀/寫佇列資料同步問題。讀/寫佇列是邏輯上進行區分的概念。一般情況下,讀/寫佇列數量是相同的。
例如,建立Topic時設定的寫佇列數量為 8 ,讀佇列數量為 4 ,此時系統會建立 8 個Queue,分別是0 1 2 3 4 5 6 7。Producer會將訊息寫入到這 8 個佇列,但Consumer只會消費0 1 2 3這 4 個佇列中的訊息,4 5 6 7 中的訊息是不會被消費到的。
再如,建立Topic時設定的寫佇列數量為 4 ,讀佇列數量為 8 ,此時系統會建立 8 個Queue,分別是0 1 2 3 4 5 6 7。Producer會將訊息寫入到0 1 2 3 這 4 個佇列,但Consumer只會消費0 1 2 3 4 5 6 7這 8 個佇列中的訊息,但是4 5 6 7中是沒有訊息的。此時假設Consumer Group中包含兩個Consumer,Consumer1消費0 1 2 3,而Consumer2消費4 5 6 7。但實際情況是,Consumer2是沒有訊息可消費的。
也就是說,當讀/寫佇列數量設定不同時,總是有問題的。那麼,為什麼要這樣設計呢?
其這樣設計的目的是為了,方便Topic的Queue的縮容。
例如,原來建立的Topic中包含 16 個Queue,如何能夠使其Queue縮容為 8 個,還不會丟失訊息?可以動態修改寫佇列數量為 8 ,讀佇列數量不變。此時新的訊息只能寫入到前 8 個佇列,而消費都消費的卻是16 個佇列中的資料。當發現後 8 個Queue中的訊息消費完畢後,就可以再將讀佇列數量動態設定為 8 。整個縮容過程,沒有丟失任何訊息。
perm用於設定對當前建立Topic的操作許可權: 2 表示只寫, 4 表示只讀, 6 表示讀寫。
三、單機安裝與啟動
1 準備工作
軟硬體需求
系統要求是 64 位的,JDK要求是1.8及其以上版本的。
下載RocketMQ安裝包
將下載的安裝包上傳到Linux。
解壓。
2 、修改初始記憶體
修改runserver.sh
使用vim命令開啟bin/runserver.sh檔案。現將這些值修改為如下:
修改runbroker.sh
使用vim命令開啟bin/runbroker.sh檔案。現將這些值修改為如下:
3 、啟動
啟動NameServer
nohup sh bin/mqnamesrv &
tail -f ~/logs/rocketmqlogs/namesrv.log
如果出現mq啟動報錯ERROR: Please set the JAVA_HOME variable in your environment, We need java(x64)! !!
ln -s /usr/local/jdk1.8.0_191/bin/javac /usr/bin/javac
ln -s /usr/local/jdk1.8.0_191/bin/jar /usr/bin/jar
ln -s /usr/local/jdk1.8.0_191/bin/java /bin/java
啟動broker
nohup sh bin/mqbroker -n localhost:9876 &
tail -f ~/logs/rocketmqlogs/broker.log
4 、傳送/接收訊息測試
傳送訊息
export NAMESRV_ADDR=localhost:9876
sh bin/tools.sh org.apache.rocketmq.example.quickstart.Producer
接收訊息
sh bin/tools.sh org.apache.rocketmq.example.quickstart.Consumer
5 、關閉Server
無論是關閉name server還是broker,都是使用bin/mqshutdown命令。
[root@mqOS rocketmq]# sh bin/mqshutdown broker
The mqbroker(1740) is running...
Send shutdown request to mqbroker(1740) OK
[root@mqOS rocketmq]# sh bin/mqshutdown namesrv
The mqnamesrv(1692) is running...
Send shutdown request to mqnamesrv(1692) OK
[2]+ 退出 143 nohup sh bin/mqbroker -n localhost:9876
四、 控制檯的安裝與啟動
RocketMQ有一個視覺化的dashboard,通過該控制檯可以直觀的檢視到很多資料。
1 下載
下載地址:https://github.com/apache/rocketmq-externals/releases
2 修改配置
修改其src/main/resources中的application.properties配置檔案。
- 原來的埠號為 8080 ,修改為一個不常用的
- 指定RocketMQ的name server地址
3 新增依賴
在解壓目錄rocketmq-console的pom.xml中新增如下JAXB依賴。
JAXB,Java Architechture for Xml Binding,用於XML繫結的Java技術,是一個業界標準,是一項可以根據XML Schema生成Java類的技術。
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-core</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>
4 打包
在rocketmq-console目錄下執行maven的打包命令。
5 啟動
6 訪問
五、叢集搭建理論
1 資料複製與刷盤策略
複製策略
複製策略是Broker的Master與Slave間的資料同步方式。分為同步複製與非同步複製:
- 同步複製:訊息寫入master後,master會等待slave同步資料成功後才向producer返回成功ACK
- 非同步複製:訊息寫入master後,master立即向producer返回成功ACK,無需等待slave同步資料成功
非同步複製策略會降低系統的寫入延遲,RT變小,提高了系統的吞吐量
刷盤策略
刷盤策略指的是broker中訊息的落盤方式,即訊息傳送到broker記憶體後訊息持久化到磁碟的方式。分為同步刷盤與非同步刷盤.
- 同步刷盤:當訊息持久化到broker的磁碟後才算是訊息寫入成功。
- 非同步刷盤:當訊息寫入到broker的記憶體後即表示訊息寫入成功,無需等待訊息持久化到磁碟。
1 )非同步刷盤策略會降低系統的寫入延遲,RT變小,提高了系統的吞吐量
2 )訊息寫入到Broker的記憶體,一般是寫入到了PageCache
3 )對於非同步 刷盤策略,訊息會寫入到PageCache後立即返回成功ACK。但並不會立即做落盤操作,而是當PageCache到達一定量時會自動進行落盤。
2 Broker叢集模式
根據Broker叢集中各個節點間關係的不同,Broker叢集可以分為以下幾類:
單Master
只有一個broker(其本質上就不能稱為叢集)。這種方式也只能是在測試時使用,生產環境下不能使用,因為存在單點問題。
多Master
broker叢集僅由多個master構成,不存在Slave。同一Topic的各個Queue會平均分佈在各個master節點上。
- 優點:配置簡單,單個Master宕機或重啟維護對應用無影響,在磁碟配置為RAID10時,即使機器宕機不可恢復情況下,由於RAID10磁碟非常可靠,訊息也不會丟(非同步刷盤丟失少量訊息,同步刷盤一條不丟),效能最高;
- 缺點:單臺機器宕機期間,這臺機器上未被消費的訊息在機器恢復之前不可訂閱(不可消費),訊息實時性會受到影響。
以上優點的前提是,這些Master都配置了RAID磁碟陣列。如果沒有配置,一旦出現某Master宕機,則會發生大量訊息丟失的情況。
多Master多Slave模式-非同步複製
broker叢集由多個master構成,每個master又配置了多個slave(在配置了RAID磁碟陣列的情況下,一個master一般配置一個slave即可)。master與slave的關係是主備關係,即master負責處理訊息的讀寫請求,而slave僅負責訊息的備份與master宕機後的角色切換。
非同步複製即前面所講的複製策略
中的非同步複製策略
,即訊息寫入master成功後,master立即向producer返回成功ACK,無需等待slave同步資料成功。
該模式的最大特點之一是,當master宕機後slave能夠自動切換
為master。不過由於slave從master的同步具有短暫的延遲(毫秒級),所以當master宕機後,這種非同步複製方式可能會存在少量訊息的丟失問題。
Slave從Master同步的延遲越短,其可能丟失的訊息就越少
對於Master的RAID磁碟陣列,若使用的也是非同步複製策略,同樣也存在延遲問題,同樣也可能會丟失訊息。但RAID陣列的祕訣是微秒級的(因為是由硬碟支援的),所以其丟失的資料量會更少。
多Master多Slave模式-同步雙寫
該模式是多Master多Slave模式
的同步複製
實現。所謂同步雙寫
,指的是訊息寫入master成功後,master會等待slave同步資料成功後才向producer返回成功ACK,即master與slave都要寫入成功後才會返回成功ACK,也即雙寫
。該模式與非同步複製模式相比
,優點是訊息的安全性更高,不存在訊息丟失的情況。但單個訊息的RT略高,從而導致效能要略低(大約低10%)。
該模式存在一個大的問題:對於目前的版本,Master宕機後,Slave不會自動切換
到Master。
最佳實踐
一般會為Master配置RAID10磁碟陣列,然後再為其配置一個Slave。即利用了RAID10磁碟陣列的高效、安全性,又解決了可能會影響訂閱的問題。
1 )RAID磁碟陣列的效率要高於Master-Slave叢集。因為RAID是硬體支援的。也正因為如此,所以RAID陣列的搭建成本較高。
2 )多Master+RAID陣列,與多Master多Slave叢集的區別是什麼?
1.多Master+RAID陣列,其僅僅可以保證資料不丟失,即不影響訊息寫入,但其可能會影響到訊息的訂閱。但其執行效率要遠高於多Master多Slave叢集
2.多Master多Slave叢集,其不僅可以保證資料不丟失,也不會影響訊息寫入。其執行效率要低於多Master+RAID陣列
六、磁碟陣列RAID(補充)
1 RAID歷史
1988 年美國加州大學伯克利分校的 D. A. Patterson 教授等首次在論文 “A Case of Redundant Array of Inexpensive Disks” 中提出了 RAID 概念 ,即廉價冗餘磁碟陣列
( Redundant Array of Inexpensive Disks )。由於當時大容量磁碟比較昂貴, RAID 的基本思想是將多個容量較小、相對廉價的磁碟進行有機組合,從而以較低的成本獲得與昂貴大容量磁碟相當的容量、效能、可靠性。隨著磁碟成本和價格的不斷降低, “廉價” 已經毫無意義。因此, RAID 諮詢委員會( RAID Advisory Board, RAB )決定用“ 獨立 ” 替代 “ 廉價 ” ,於時 RAID 變成了獨立磁碟冗餘陣列
( Redundant Array of Independent Disks )。但這僅僅是名稱的變化,實質內容沒有改變。
記憶體:32m 6.4G(IBM 10.1G)
2 RAID等級
RAID 這種設計思想很快被業界接納, RAID 技術作為高效能、高可靠的儲存技術,得到了非常廣泛的應用。 RAID 主要利用映象、資料條帶和資料校驗三種技術來獲取高效能、可靠性、容錯能力和擴充套件性,根據對這三種技術的使用策略和組合架構,可以把 RAID 分為不同的等級,以滿足不同資料應用的需求。
D. A. Patterson 等的論文中定義了 RAID0 ~ RAID6 原始 RAID 等級。隨後儲存廠商又不斷推出 RAID7、 RAID10、RAID01 、 RAID50 、 RAID53 、 RAID100 等 RAID 等級,但這些並無統一的標準。目前業界與學術界公認的標準是 RAID0 ~ RAID6 ,而在實際應用領域中使用最多的 RAID 等級是 RAID0 、RAID1 、 RAID3 、 RAID5 、 RAID6 和 RAID10。
RAID 每一個等級代表一種實現方法和技術,等級之間並無高低之分。在實際應用中,應當根據使用者的資料應用特點,綜合考慮可用性、效能和成本來選擇合適的 RAID 等級,以及具體的實現方式。
3 關鍵技術
映象技術
映象技術是一種冗餘技術,為磁碟提供資料備份功能,防止磁碟發生故障而造成資料丟失。對於 RAID而言,採用映象技術最典型地的用法就是,同時在磁碟陣列中產生兩個完全相同的資料副本,並且分佈在兩個不同的磁碟上。映象提供了完全的資料冗餘能力,當一個數據副本失效不可用時,外部系統仍可正常訪問另一副本,不會對應用系統執行和效能產生影響。而且,映象不需要額外的計算和校驗,故障修復非常快,直接複製即可。映象技術可以從多個副本進行併發讀取資料,提供更高的讀 I/O 效能,但不能並行寫資料,寫多個副本通常會導致一定的 I/O 效能下降。
映象技術提供了非常高的資料安全性,其代價也是非常昂貴的,需要至少雙倍的儲存空間。高成本限制了映象的廣泛應用,主要應用於至關重要的資料保護,這種場合下的資料丟失可能會造成非常巨大的損失。
資料條帶技術
資料條帶化技術是一種自動將 I/O操作負載均衡到多個物理磁碟上的技術。更具體地說就是,將一塊連續的資料分成很多小部分並把它們分別儲存到不同磁碟上。這就能使多個程序可以併發訪問資料的多個不同部分,從而獲得最大程度上的 I/O 並行能力,極大地提升效能。
資料校驗技術
資料校驗技術是指, RAID 要在寫入資料的同時進行校驗計算,並將得到的校驗資料儲存在 RAID 成員磁碟中。校驗資料可以集中儲存在某個磁碟或分散儲存在多個不同磁碟中。當其中一部分資料出錯時,就可以對剩餘資料和校驗資料進行反校驗計算重建丟失的資料。
資料校驗技術相對於映象技術的優勢在於節省大量開銷,但由於每次資料讀寫都要進行大量的校驗運算,對計算機的運算速度要求很高,且必須使用硬體 RAID 控制器。在資料重建恢復方面,檢驗技術比映象技術複雜得多且慢得多。
4 RAID分類
從實現角度看, RAID 主要分為軟 RAID、硬 RAID 以及混合 RAID 三種。
軟 RAID
所有功能均有作業系統和 CPU 來完成,沒有獨立的 RAID 控制處理晶片和 I/O 處理晶片,效率自然最低。
硬 RAID
配備了專門的 RAID 控制處理晶片和 I/O 處理晶片以及陣列緩衝,不佔用 CPU 資源。效率很高,但成本也很高。
混合 RAID
具備 RAID 控制處理晶片,但沒有專門的I/O 處理晶片,需要 CPU 和驅動程式來完成。效能和成本在軟RAID 和硬 RAID 之間。
5 常見RAID等級詳解
JBOD
JBOD ,Just a Bunch of Disks,磁碟簇。表示一個沒有控制軟體提供協調控制的磁碟集合,這是 RAID區別與 JBOD 的主要因素。 JBOD 將多個物理磁碟串聯起來,提供一個巨大的邏輯磁碟。
JBOD 的資料存放機制是由第一塊磁碟開始按順序往後儲存,當前磁碟儲存空間用完後,再依次往後面的磁碟儲存資料。 JBOD 儲存效能完全等同於單塊磁碟,而且也不提供資料安全保護。
其只是簡單提供一種擴充套件儲存空間的機制,JBOD可用儲存容量等於所有成員磁碟的儲存空間之和
JBOD 常指磁碟櫃,而不論其是否提供 RAID 功能。不過,JBOD並非官方術語,官方稱為Spanning。
RAID0
RAID0 是一種簡單的、無資料校驗的資料條帶化技術
。實際上不是一種真正的 RAID ,因為它並不提供任何形式的冗餘策略。 RAID0 將所在磁碟條帶化後組成大容量的儲存空間,將資料分散儲存在所有磁碟中,以獨立訪問方式實現多塊磁碟的並讀訪問。
理論上講,一個由 n 塊磁碟組成的 RAID0 ,它的讀寫效能是單個磁碟效能的 n 倍,但由於匯流排頻寬等多種因素的限制,實際的效能提升低於理論值。由於可以併發執行 I/O 操作,匯流排頻寬得到充分利用。再加上不需要進行資料校驗,RAID0 的效能在所有 RAID 等級中是最高的
。
RAID0 具有低成本、高讀寫效能、 100% 的高儲存空間利用率等優點,但是它不提供資料冗餘保護,一旦資料損壞,將無法恢復。
應用場景:對資料的順序讀寫要求不高,對資料的安全性和可靠性要求不高,但對系統性能要求很高的場景。
RAID0與JBOD相同點:
1 )儲存容量:都是成員磁碟容量總和
2 )磁碟利用率,都是100%,即都沒有做任何的資料冗餘備份
RAID0與JBOD不同點:
1 )JBOD:資料是順序存放的,一個磁碟存滿後才會開始存放到下一個磁碟
2 )RAID:各個磁碟中的資料寫入是並行的,是通過資料條帶技術寫入的。其讀寫效能是JBOD的n倍
RAID1
RAID1 就是一種映象技術
,它將資料完全一致地分別寫到工作磁碟和映象磁碟,它的磁碟空間利用率為 50% 。 RAID1 在資料寫入時,響應時間會有所影響,但是讀資料的時候沒有影響。 RAID1 提供了最佳的資料保護,一旦工作磁碟發生故障,系統將自動切換到映象磁碟,不會影響使用。
RAID1是為了增強資料安全性使兩塊磁碟資料呈現完全映象,從而達到安全性好、技術簡單、管理方便。 RAID1 擁有完全容錯的能力,但實現成本高。
應用場景:對順序讀寫效能要求較高,或對資料安全性要求較高的場景。
RAID10
RAID10是一個RAID1與RAID0的組合體,所以它繼承了RAID0的快速和RAID1的安全。簡單來說就是,先做條帶,再做映象。發即將進來的資料先分散到不同的磁碟,再將磁碟中的資料做映象。
RAID01
RAID01是一個RAID0與RAID1的組合體,所以它繼承了RAID0的快速和RAID1的安全。簡單來說就是,先做映象再做條帶。即將進來的資料先做映象,再將映象資料寫入到與之前資料不同的磁碟,即再做條帶。
RAID10要比RAID01的容錯率再高,所以生產環境下一般是不使用RAID01的。
序號 主機名/IP IP 功能 BROKER角色
1 rocketmqOS1 192.168.59.164 NameServer + Broker Master1 + Slave2
2 rocketmqOS2 192.168.59.165 NameServer + Broker Master2 + Slave1
七、叢集搭建實踐
1 叢集架構
這裡要搭建一個雙主雙從非同步複製的Broker叢集。為了方便,這裡使用了兩臺主機來完成叢集的搭建。這兩臺主機的功能與broker角色分配如下表。
序號 | 主機名/IP | IP | 功能 | BROKER角色 |
---|---|---|---|---|
1 | rocketmqOS1 | 192.168.59.164 | NameServer + Broker | Master1 + Slave2 |
2 | rocketmqOS1 | 192.168.59.165 | NameServer + Broker | Master2 + Slave1 |
2 克隆生成rocketmqOS1
克隆rocketmqOS主機,並修改配置。指定主機名為rocketmqOS1。
3 修改rocketmqOS1配置檔案
配置檔案位置
要修改的配置檔案在rocketMQ解壓目錄的conf/2m-2s-async目錄中。
修改broker-a.properties
將該配置檔案內容修改為如下:
# 指定整個broker叢集的名稱,或者說是RocketMQ叢集的名稱
brokerClusterName=
# 指定master-slave叢集的名稱。一個RocketMQ叢集可以包含多個master-slave叢集
brokerName=broker-a
# master的brokerId為 0
brokerId= 0
# 指定刪除訊息儲存過期檔案的時間為凌晨 4 點
deleteWhen= 04
# 指定未發生更新的訊息儲存檔案的保留時長為 48 小時, 48 小時後過期,將會被刪除
fileReservedTime= 48
# 指定當前broker為非同步複製master
brokerRole=ASYNC_MASTER
# 指定刷盤策略為非同步刷盤
flushDiskType=ASYNC_FLUSH
# 指定Name Server的地址
namesrvAddr=192.168.59.164:9876;192.168.59.165:9876
修改broker-b-s.properties
將該配置檔案內容修改為如下:
其它配置
brokerClusterName=DefaultCluster
# 指定這是另外一個master-slave叢集
brokerName=broker-b
# slave的brokerId為非 0
brokerId=1
deleteWhen=04
fileReservedTime=48
# 指定當前broker為slave
brokerRole=SLAVE
flushDiskType=ASYNC_FLUSH
namesrvAddr=192.168.59.164:9876;192.168.59.165:9876
# 指定Broker對外提供服務的埠,即Broker與producer與consumer通訊的埠。預設10911 。由於當前主機同時充當著master1與slave2,而前面的master1使用的是預設埠。這裡需要將這兩個埠加以區分,以區分出master1與slave2
listenPort= 11911
# 指定訊息儲存相關的路徑。預設路徑為~/store目錄。由於當前主機同時充當著master1與slave2,master1使用的是預設路徑,這裡就需要再指定一個不同路徑
storePathRootDir=~/store-s
storePathCommitLog=~/store-s/commitlog
storePathConsumeQueue=~/store-s/consumequeue
storePathIndex=~/store-s/index
storeCheckpoint=~/store-s/checkpoint
abortFile=~/store-s/abort
除了以上配置外,這些配置檔案中還可以設定其它屬性。
#指定整個broker叢集的名稱,或者說是RocketMQ叢集的名稱
brokerClusterName=rocket-MS
#指定master-slave叢集的名稱。一個RocketMQ叢集可以包含多個master-slave叢集
brokerName=broker-a
#0 表示 Master,>0 表示 Slave
brokerId=0
#nameServer地址,分號分割
namesrvAddr=nameserver1:9876;nameserver2:9876
#預設為新建Topic所建立的佇列數
defaultTopicQueueNums=4
#是否允許 Broker 自動建立Topic,建議生產環境中關閉
autoCreateTopicEnable=true
#是否允許 Broker 自動建立訂閱組,建議生產環境中關閉
autoCreateSubscriptionGroup=true
#Broker對外提供服務的埠,即Broker與producer與consumer通訊的埠
listenPort=10911
#HA高可用監聽埠,即Master與Slave間通訊的埠,預設值為listenPort+1
haListenPort=10912
#指定刪除訊息儲存過期檔案的時間為凌晨 4 點
deleteWhen=04
#指定未發生更新的訊息儲存檔案的保留時長為 48 小時, 48 小時後過期,將會被刪除
fileReservedTime=48
#指定commitLog目錄中每個檔案的大小,預設1G
mapedFileSizeCommitLog=1073741824
#指定ConsumeQueue的每個Topic的每個Queue檔案中可以存放的訊息數量,預設30w條
mapedFileSizeConsumeQueue=300000
#在清除過期檔案時,如果該檔案被其他執行緒所佔用(引用數大於 0 ,比如讀取訊息),此時會阻止此次刪除任務,同時在第一次試圖刪除該檔案時記錄當前時間戳。該屬性則表示從第一次拒絕刪除後開始計時,該檔案最多可以保留的時長。在此時間內若引用數仍不為 0 ,則刪除仍會被拒絕。不過時間到後,檔案將被強制刪除
destroyMapedFileIntervalForcibly=120000
#指定commitlog、consumequeue所在磁碟分割槽的最大使用率,超過該值,則需立即清除過期檔案
diskMaxUsedSpaceRatio=88
#指定store目錄的路徑,預設在當前使用者主目錄中
storePathRootDir=/usr/local/rocketmq-all-4.5.0/store
#commitLog目錄路徑
storePathCommitLog=/usr/local/rocketmq-all-4.5.0/store/commitlog
#consumeueue目錄路徑
storePathConsumeQueue=/usr/local/rocketmq-all-4.5.0/store/consumequeue
#index目錄路徑
storePathIndex=/usr/local/rocketmq-all-4.5.0/store/index
#checkpoint檔案路徑
storeCheckpoint=/usr/local/rocketmq-all-4.5.0/store/checkpoint
#abort檔案路徑
abortFile=/usr/local/rocketmq-all-4.5.0/store/abort
#指定訊息的最大大小
maxMessageSize= 65536
#Broker的角色
# - ASYNC_MASTER 非同步複製Master
# - SYNC_MASTER 同步雙寫Master
# - SLAVE
brokerRole=SYNC_MASTER
#刷盤策略
# - ASYNC_FLUSH 非同步刷盤
# - SYNC_FLUSH 同步刷盤
flushDiskType=SYNC_FLUSH
#發訊息執行緒池數量
sendMessageThreadPoolNums=128
#拉訊息執行緒池數量
pullMessageThreadPoolNums=128
#強制指定本機IP,需要根據每臺機器進行修改。官方介紹可為空,系統預設自動識別,但多網絡卡時IP地址可能讀取錯誤
brokerIP1=192.168.3.105
4 克隆生成rocketmqOS2
克隆rocketmqOS1主機,並修改配置。指定主機名為rocketmqOS2。
5 修改rocketmqOS2配置檔案
對於rocketmqOS2主機,同樣需要修改rocketMQ解壓目錄的conf目錄的子目錄2m-2s-async中的兩個配置檔案。
修改broker-b.properties
將該配置檔案內容修改為如下:
brokerClusterName=DefaultCluster
brokerName=broker-b
brokerId=0
deleteWhen=04
fileReservedTime=48
brokerRole=ASYNC_MASTER
flushDiskType=ASYNC_FLUSH
namesrvAddr=192.168.59.164:9876;192.168.59.165:9876
修改broker-a-s.properties
將該配置檔案內容修改為如下:
brokerClusterName=DefaultCluster
brokerName=broker-a
brokerId=1
deleteWhen=04
fileReservedTime=48
brokerRole=SLAVE
flushDiskType=ASYNC_FLUSH
namesrvAddr=192.168.59.164:9876;192.168.59.165:9876
listenPort=11911
storePathRootDir=~/store-s
storePathCommitLog=~/store-s/commitlog
storePathConsumeQueue=~/store-s/consumequeue
storePathIndex=~/store-s/index
storeCheckpoint=~/store-s/checkpoint
abortFile=~/store-s/abort
6 啟動伺服器
啟動NameServer叢集
分別啟動rocketmqOS1與rocketmqOS2兩個主機中的NameServer。啟動命令完全相同。
nohup sh bin/mqnamesrv &
tail -f ~/logs/rocketmqlogs/namesrv.log
啟動兩個Master
分別啟動rocketmqOS1與rocketmqOS2兩個主機中的broker master。注意,它們指定所要載入的配置檔案是不同的。
nohup sh bin/mqbroker -c conf/2m-2s-async/broker-a.properties &
tail -f ~/logs/rocketmqlogs/broker.log
nohup sh bin/mqbroker -c conf/2m-2s-async/broker-b.properties &
tail -f ~/logs/rocketmqlogs/broker.log
啟動兩個Slave
分別啟動rocketmqOS1與rocketmqOS2兩個主機中的broker slave。注意,它們指定所要載入的配置檔案是不同的。
nohup sh bin/mqbroker -c conf/2m-2s-async/broker-b-s.properties &
tail -f ~/logs/rocketmqlogs/broker.log
nohup sh bin/mqbroker -c conf/2m-2s-async/broker-a-s.properties &
tail -f ~/logs/rocketmqlogs/broker.log
八、mqadmin命令
在mq解壓目錄的bin目錄下有一個mqadmin命令,該命令是一個運維指令,用於對mq的主題,叢集,broker 等資訊進行管理。
1 修改bin/tools.sh
在執行mqadmin命令之前,先要修改mq解壓目錄下bin/tools.sh配置的JDK的ext目錄位置。本機的ext目錄在/usr/java/jdk1.8.0_161/jre/lib/ext
。
使用vim命令開啟tools.sh檔案,並在JAVA_OPT配置的-Djava.ext.dirs這一行的後面新增ext的路徑。
JAVA_OPT="${JAVA_OPT} -server -Xms1g -Xmx1g -Xmn256m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=128m"
JAVA_OPT="${JAVA_OPT} -Djava.ext.dirs=${BASE_DIR}/lib:${JAVA_HOME}/jre/lib/ext:${JAVA_HOME}/lib/ext:/usr/java/jdk1.8.0_161/jre/lib/ext"
JAVA_OPT="${JAVA_OPT} -cp ${CLASSPATH}"
2 執行mqadmin
直接執行該命令,可以看到其可以新增的commands。通過這些commands可以完成很多的功能。
[root@mqOS rocketmq-all-4.8.0-bin-release]# ./bin/mqadmin
The most commonly used mqadmin commands are:
updateTopic Update or create topic
deleteTopic Delete topic from broker and NameServer.
updateSubGroup Update or create subscription group
deleteSubGroup Delete subscription group from broker.
updateBrokerConfig Update broker's config
updateTopicPerm Update topic perm
topicRoute Examine topic route info
topicStatus Examine topic Status info
topicClusterList get cluster info for topic
brokerStatus Fetch broker runtime status data
queryMsgById Query Message by Id
queryMsgByKey Query Message by Key
queryMsgByUniqueKey Query Message by Unique key
queryMsgByOffset Query Message by offset
QueryMsgTraceById query a message trace
printMsg Print Message Detail
printMsgByQueue Print Message Detail
sendMsgStatus send msg to broker.
brokerConsumeStats Fetch broker consume stats data
producerConnection Query producer's socket connection and clientversion
consumerConnection Query consumer's socket connection, client version and subscription
consumerProgress Query consumers's progress, speed
consumerStatus Query consumer's internal data structure
cloneGroupOffset clone offset from other group.
clusterList List all of clusters
topicList Fetch all topic list from name server
updateKvConfig Create or update KV config.
deleteKvConfig Delete KV config.
wipeWritePerm Wipe write perm of broker in all name server
resetOffsetByTime Reset consumer offset by timestamp(without client restart).
updateOrderConf Create or update or delete order conf
cleanExpiredCQ Clean expired ConsumeQueue on broker.
cleanUnusedTopic Clean unused topic on broker.
startMonitoring Start Monitoring
statsAll Topic and Consumer tps stats
allocateMQ Allocate MQ
checkMsgSendRT check message send response time
clusterRT List All clusters Message Send RT
getNamesrvConfig Get configs of name server.
updateNamesrvConfig Update configs of name server.
getBrokerConfig Get broker config by cluster or special broker!
queryCq Query cq command.
sendMessage Send a message
consumeMessage Consume message
updateAclConfig Update acl config yaml file in broker
deleteAccessConfig Delete Acl Config Account in broker
clusterAclConfigVersion List all of acl config version information in cluster
updateGlobalWhiteAddr Update global white address for acl Config File in broker
getAccessConfigSubCommand List all of acl config information in cluster
3 該命令的官網詳解
該命令在官網中有詳細的用法解釋。
https://github.com/apache/rocketmq/blob/master/docs/cn/operation.md