DLedger技術實際上首先他自己就有一個CommitLog機制,你把數據交給他,他會寫入CommitLog磁盤文件裡去,這是他能幹的第一件事情。
所以首先我們在下面的圖裡可以看到,如果基于DLedger技術來實現Broker高可用架構,實際上就是用DLedger先替換掉原來Broker自己管理的CommitLog,由DLedger來管理CommitLog。
然後Broker還是可以基于DLedger管理的CommitLog去構建出來機器上的各個ConsumeQueue磁盤文件。
1、DLedger是如何基于Raft協議選舉Leader Broker的?
簡單來說,三台Broker機器啟動的時候,他們都會投票自己作為Leader,然後把這個投票發送給其他Broker。
我們舉一個例子,Broker01是投票給自己的,Broker02是投票給自己的,Broker03是投票給自己的,他們都把自己的投票發送給了别人。
此時在第一輪選舉中,Broker01會收到别人的投票,他發現自己是投票給自己,但是Broker02投票給Broker02自己,Broker03投票給Broker03自己,似乎每個人都很自私,都在投票給自己,所以第一輪選舉是失敗的。
接着每個人會進入一個随機時間的休眠,比如說Broker01休眠3秒,Broker02休眠5秒,Broker03休眠4秒。
此時Broker01必然是先蘇醒過來的,他蘇醒過來之後,直接會繼續嘗試投票給自己,并且發送自己的選票給别人。
接着Broker03休眠4秒後蘇醒過來,他發現Broker01已經發送來了一個選票是投給Broker01自己的,此時他自己因為沒投票,所以會尊重别人的選擇,就直接把票投給Broker01了,同時把自己的投票發送給别人。
Broker02醒來跟Broker03一樣,此時所有人都會收到三張投票,都是投給Broker01的,那麼Broker01收到了大多數的投票,就會當選為Leader。
這就是Raft協議中選舉leader算法的簡單描述,簡單來說,他确保有人可以成為Leader,核心機制就是一輪選舉不出來Leader的話,就讓大家随機休眠一下,先蘇醒過來的人會投票給自己,其他人蘇醒過後發現自己收到選票了,就會直接投票給那個人。
2、DLedger是如何基于Raft協議進行多副本同步的?數據同步會分為兩個階段,一個是uncommitted階段,一個是commited階段。
首先Leader Broker上的DLedger收到一條數據之後,會标記為uncommitted狀态,然後他會通過自己的DLedgerServer組件把這個uncommitted數據發送給Follower Broker的DLedgerServer。
接着Follower Broker的DLedgerServer收到uncommitted消息之後,必須返回一個ack給Leader Broker的DLedgerServer,然後如果Leader Broker收到超過半數的Follower Broker返回ack之後,就會将消息标記為committed狀态。
然後Leader Broker上的DLedgerServer就會發送commited消息給Follower Broker機器的DLedgerServer,讓他們也把消息标記為comitted狀态。
RocketMQ高性能底層技術1、RocketMQ 是如何基于Netty擴展出高性能網絡通信架構的?比如對于處理發送消息請求而言,就會把請求轉交給SendMessage線程池,而且如果大家還有一點點印象的話,其實在之前講集群部署的時候,我們講到過這個SendMessage線程是可以配置的,你配置的越多,自然處理消息的吞吐量越高。
為什麼這套網絡通信框架會是高性能以及高并發的?
1、Reactor主線程在端口上監聽Producer建立連接的請求,建立長連接
2、Reactor線程池并發的監聽多個連接的請求是否到達
3、Worker請求并發的對多個請求進行預處理
4、業務線程池并發的對多個請求進行磁盤讀寫業務操作
2、基于mmap技術 pagecache技術實現高性能的文件讀寫首先,RocketMQ底層對CommitLog、ConsumeQueue之類的磁盤文件的讀寫操作,基本上都會采用mmap技術來實現。如果具體到代碼層面,就是基于JDK NIO包下的MappedByteBuffer的map()函數,來先将一個磁盤文件(比如一個CommitLog文件,或者是一個ConsumeQueue文件)映射到内存裡來,建立映射的時候,并沒有任何的數據拷貝操作,其實磁盤文件還是停留在那裡,隻不過他把物理上的磁盤文件的一些地址和用戶進程私有空間的一些虛拟内存地址進行了一個映射。
另外這裡給大家說明白的一點是,這個mmap技術在進行文件映射的時候,一般有大小限制,在1.5GB~2GB之間,所以RocketMQ才讓CommitLog單個文件在1GB,ConsumeQueue文件在5.72MB,不會太大。接着就可以對這個MappedByteBuffer執行寫入操作了,寫入的時候他會直接進入PageCache中,然後過一段時間之後,由os的線程異步刷入磁盤中,此時才會發生一次拷貝。
接着如果我們要從磁盤文件裡讀取數據呢?那麼此時就會判斷一下,當前你要讀取的數據是否在PageCache裡?如果在的話,就可以直接從PageCache裡讀取了!但是如果PageCache裡沒有你要的數據,那麼此時就會從磁盤文件裡加載數據到PageCache中去,也隻會發生一次拷貝,如下圖
通過上述優化,才真正能實現一個效果,就是寫磁盤文件的時候都是進入PageCache的,保證寫入高性能;同時盡可能多地通過mmap madvise的映射後預熱機制,把磁盤文件裡的數據盡可能多的加載到PageCache裡來,後續對CosumeQueue、CommitLog進行讀取的時候,才能盡可能從内存裡讀取數據。
,更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!