知識點回顧: 通過上一節課我們初步接觸到了一小部分的docker命令的使用、和redis集群有哪些方式,重點是將到了主從集 群,並通過實例逐步教給大家如何實現一組多從的「主從(Master-Slave)集群模式」,我們的實現結果已經完 成,今天我們來一起學習探討下redis-主從複製原理和部分問題的解決方法,學習本課程前,請學習者務必完成。
現在我們有了上節課搭建主從複製集群的能力,假如我們現在就運用在我們的項目中,因為網路原因和平台數據的錯綜複雜的交互,難免會遇到一些問題,不管什麼情況下我們都不能永遠保證我們所部署的系統或架構不會出現任何問題。因此,為了能夠解決這些常見的問題,對主從的工作原理和數據處理的過程是我們必須必須得掌握的。話不多說,我們先來看一張圖,來幫助大家去理解。
從上面的結構圖中我們不難發現主從複製的過程具體分為三個階段:1、準備階段開始建立連接;2、同步數據;3、傳播命令和六個過程
現在我們來詳細說下這6個過程:
一、準備階段開始建立連接:
這裡就是執行slaveof命令以後,從節點開始嘗試與主節點進行socket連接。
1.保存主節點Master數據信息:
主要是保存MasterHost、MasterPort兩個欄位也就是我們常說的ip地址和埠號【上節課我們配置從節點時,已經告訴大家了,學過上節課的內容大家應該都有所了解】這裡我們在從節點執行下slaveof命令來連接主節點時日誌就會幫我們記錄這樣的過程
在從節點slave 執行以下命令去查看日誌信息: [root@90e5a51dda7f /]# cat /var/log/redis/redis.log 你會看到有下面的截圖內容
注意:slaveof是非同步命令,當從節點完成與主節點連接時會先想客戶端返回成功ok後再次進行複製數據【面試中可能會遇到】
2.建立socket連接:
從節點每秒調用複製定時函數replicationCron()來維護複製相關邏輯,當發現有新的主節點可以連接時,便會根據主節點的ip和埠號進行嘗試建立連接。從節點:為該socket建立一個專門處理複製工作的文件事件處理器,負責後續的複製工作(從節點會建立一個 socket 套接字)。主節點:接收到從節點的socket連接後,為該socket創建相應的客戶端狀態(我們稱之為「即時狀態」),並將從節點看做是連接到主節點的一個客戶端,後面的步驟會以從節點向主節點發送命令請求的形式來進行,也就是說後續的複製動作請求一切都是來自從節點。看下日誌截圖:
3.發送ping命令:
當從節點成為主節點的客戶端後,從節點會發送ping進行連接後首次通信,其中ping的主要目的是:
當主節點返回pong的情況時,說明socket連接成功
請看下面的圖來深化我們的理解:
4、身份驗證:
如果主節點設置了 requirepass 參數,則需要密碼驗證,從節點必須配置 masterauth 參數保證與主節點相同的密碼才能通過驗證;如果驗證失敗複製將終止,從節點重新發起複制流程。
二、數據同步階段:
數據同步階段是主從複製的核心階段,根據主從的狀態不同而複製又分為「全量複製」和「部分複製」兩種,現在我們要理清主從節點之間的關係,在數據同步之前,都是從節點向主節點發起命令請求進行socket連接,連接失敗則返回輪詢重試連接直到連接成功為止。而在同步數據之後,則主節點是從節點的客戶端,開始主機點發起命令請求將寫數據推送到從節點的緩衝區進行複製的動作。
5、同步數據:
主從複製socket連接正常通信後,對於首次建立複製的場景,主節點會把持有的數據全部發送給從節點,這部分操作是耗時最長的步驟;因為數據很龐大的話,會執行大量的數據複製動作,所以會很耗時。
三、傳播命令複製階段:
數據同步階段完成後,主從節點進入命令傳播階段;在這個階段主節點將自己執行的寫命令發送給從節點,從節點接收命令並執行,從而保證主從節點數據的一致性。
注意:首先主從複製中的命令傳播是非同步的過程,即主節點開始想從節點發起寫的命令,並不會等待從節點的回復,因此常說到主從節點數據的一致性其實是很難保證的。
6、數據複製:
當主節點把當前的數據同步給從節點後,便完成了複製的建立流程。接下來就是主節點會持續地把數據以寫命令的方式發送給從節點,保證主從數據一致性。當我們在主節點寫入數據時,我們可以看下從節點的複製動作日誌信息:
講到這裡,我們來做一個比較簡單的實驗也是對大家知識點的擴充,我們寫個shell腳本來做批量的寫動作,這樣做的目的是為了我們的redis緩存數據足夠多,實驗起來會比較方便,效果的數據可視化能讓大家更全面地去理解,全量複製和部分複製的區別,以及問題的解決方向,這裡就不再跟大家詳細講解linux的shell腳本的命令了【這裡我們運行存儲十萬條redis數據】。如果想學學linux基礎請下載下面給大家提供的「鳥哥私房菜」高清PDF的版本
https://pan.baidu.com/s/1x2fvZA-8d0kPa_o2hGo7Ww
密碼:d1ob
執行以下命令 [root@instance-rttngj1u ~]# docker exec -it redis-master bash [root@90e5a51dda7f /]# touch redis.sh&vi redis.sh #!/bin/bash for((i=1;i<100000;i++)) do redis-cli -h 172.60.0.2 -p 6379 set slave${i} ${i} done 再推出保存執行腳本 [root@90e5a51dda7f /]# sh redis.sh 這時我們將會看到很多的ok存儲結果集反饋並顯示。 【下一節課需要用】
上面的命令執行完畢後,我們來介紹下什麼是「全量複製」,什麼是「部分複製」以及「複製偏移量」、「複製積壓緩衝區」的概念:
一、全量複製:
當我們第一次構建大量的數據集或者是初次複製以及其它無法進行部分複製的情況,將主節點中的所有數據都發送給從節點,就是主節點有多少數據統統地複製給從節點,這個過程是一個非常重型的操作,如果數據量較大時,會消耗很多的資源空間的同時對主從節點和網路也會造成很大的開銷,由此可見,全量複製的變態性行為。
二、部分複製:
部分複製要比全量複製人性化一點,少什麼數據就補什麼數據,常常用來處理在主從複製中因網路閃斷等原因造成的數據丟失場景,進而當從節點再次連上主節點後,只要條件允許,主節點就會補發丟失的數據給從節點。因此這種部分補發的數據遠遠小於全量數據,可以有效避免全量複製的過高開銷,但是需要注意的是,如果我們的網路中斷時間過長,導致主節點斷開了連接致使主節點沒有能夠完整地保存中斷期間執行的寫命令,則就無法進行部分複製,任然會去使用全量複製。
三、複製偏移量:
不管何時參與複製的主從節點都會維護自身複製偏移量。主節點(master)在處理完寫入命令後,會把命令的位元組長度做累加記錄,我們可以在redis客戶端執行命令來查看下主節點的數據統計信息master_repl_offset指標
這裡我們不難發現三個從節點的offset與主節點的master_repl_offset偏移量數據信息是相同的,是因為從節點會每秒鐘都會向主節點發起命令給主節點上報自己的複製偏移量,而主節點在接受命令後,會記錄從節點複製偏移量的數值。
同時從節點在接受到主節點發起的命令後,也會累加並記錄自己的複製偏移量數值,其目的我們不難得知就是為了複製主節點的數據信息實現數據的一致性。
四、複製積壓緩衝區,什麼是緩存區,緩存區有幾個呢,作用又是什麼?
答:複製積壓緩衝區是保存在主節點上的一個固定長度的隊列,默認大小為1MB,作用就是當主節點開始有從節點的創建時,積壓緩衝區就會備份主節點最近發給從節點的數據信息。這裡要注意的是無論主節點有一個還是多個從節點,都只需要一個複製積壓緩衝區。在運行複製的第三個階段也就是「命令傳播階段」中,主節點除了將寫命令發送給從節點,還會發送一份給複製積壓緩衝區,作為寫命令的備份。
注意:從節點將offset發送給主節點後,主節點根據offset和緩衝區大小決定能否執行部分複製:
五、圖解:
以上講到了全量複製、部分複製和複製擠壓緩衝區,下面我們繼續結合圖片來理解:
①、全量複製圖解:
複製的全過程解釋:
總結全量複製的開銷:
②、部分複製:
六、伺服器運行的runid:
每個Redis節點(無論主從),在啟動時都會自動生成一個隨機ID(每次啟動都不一樣),由40個隨機的十六進位字元組成;runid用來唯一識別一個Redis節點。 通過info server命令,可以查看節點的runid。如圖:
主從節點初次複製時,主節點將自己的runid發送給從節點,從節點將這個runid保存起來;當斷線重連時,從節點會將這個runid發送給主節點;主節點根據runid判斷能否進行部分複製:如果從節點保存的runid與主節點現在的runid相同,說明主從節點之前同步過,主節點會繼續嘗試使用部分複製(到底能不能部分複製還要看offset和複製積壓緩衝區的情況)如果從節點保存的runid與主節點現在的runid不同,說明從節點在斷線前同步的Redis節點並不是當前的主節點,只能進行全量複製。
從節點配置:
一、讀寫分離:
讀流量分攤到從節點。這是個非常好的特性,如果一個業務只需要讀數據,那麼我們只需要連一台 slave 從機讀數據。
我們都知道雖然讀寫有優勢,能夠讓讀這部分分配給各個 slave 從機,如果不夠,直接加 slave 機器,
但是也會出現以下問題:
1、複製數據延遲:
可能會出現 slave 延遲導致讀寫不一致等問題,當然你也可以使用監控偏移量 offset,如果 offset 超出範圍就切換到 master 上,邏輯切換,而具體延遲多少,可以通過 info replication 的 offset 指標進行排查。
對於無法容忍大量延遲場景,可以編寫外部監控程序(比如consul)監聽主從節點的複製偏移量,當延遲較大時觸發報警或者通知客戶端避免讀取延遲過高的從節點。
模擬網路延遲 docker run --privileged -itd -v /usr/local/redis/conf:/conf --name redis-slave4 --net mynetwork -p 6384:6379 --ip 172.60.0.4 redis2 --privileged Docker容器將擁有訪問主機所有設備的許可權
通過linux下的控流工具,模擬網路延遲,用代碼模擬下,因為對於網路的操作屬於特殊許可權所以需要添加 --privileged 參數 yum install iproute 配置延遲5s tc qdisc add dev eth0 root netem delay 5000ms tc qdisc del dev eth0 root netem delay 5000ms 同時從節點的slave-serve-stale-data參數也與此有關, 它控制這種情況下從節點的表現:如果為yes(默認值), 則從節點仍能夠響應客戶端的命令;如果為no,則從節點只能響應info、slaveof等少數命令。 該參數的設置與應用對數據一致性的要求有關;如果對數據一致性要求很高,則應設置為no。
2、只有N個從節點鏈接的時候才允許寫入:
因為Redis使用的是非同步複製,所以沒有辦法保證從節點確實收到的給定的寫入請求,所以存在一個窗口期的數據丟失的可能性。從節點每秒鐘都會ping主節點,告知它所有的複製流工作了。主節點會記住從每個從節點收到的最新的ping用戶可以給主節點配置一個在等於從節點的數量的最低值和不超過最高值之間的延遲如果至少有N個從節點,如果少於延遲M秒,則寫入將被接受。你可能覺得經最大努力保證數據安全的機制,雖然數據一致性無法保證,但是至少只是幾秒的時間窗口內丟失數據。通常情況下範圍數據丟失可比無範圍數據丟失好多了。如果條件不滿足,主節點將會返回一個錯誤,並且寫入請求將不被接受
min-slaves-to-write <number of slaves> min-slaves-max-lag <number of seconds>
3、如何選擇,要不要讀寫分離:
沒有最合適的方案,只有最合適的場景,讀寫分離需要業務可以容忍一定程度的數據不一致,適合讀多寫少的業務場景,讀寫分離,是為了什麼,主要是因為要建立一主多從的架構,才能橫向任意擴展slave node去支撐更大的讀吞吐量。
4、從節點故障問題:
對於從節點的故障問題,需要在客戶端維護一個可用從節點可用列表,當從節點故障時,立刻切換到其他從節點或主節點,之後講解redis Cluster 時候可以解決這個問題
5、配置不一致:
主機和從機不同,經常導致主機和從機的配置不同,並帶來問題。 數據丟失:主機和從機有時候會發生配置不一致的情況,例如 maxmemory 不一致,如果主機配置 maxmemory 為8G,從機 slave 設置為4G,這個時候是可以用的,而且還不會報錯。但是如果要做高可用,讓從節點變成主節點的時候,就會發現數據已經丟失了,而且無法挽回。
6、規避全量複製:
全量複製指的是當 slave 從機斷掉並重啟後,runid 產生變化而導致需要在 master 主機里拷貝全部數據。這種拷貝全部數據的過程非常耗資源。全量複製是不可避免的,例如第一次的全量複製是不可避免的,這時我們需要選擇小主節點,且maxmemory 值不要過大,這樣就會比較快。同時選擇在低峰值的時候做全量複製。
造成全量複製的原因有:
解決方案:
在一些場景下,可能希望對主節點進行重啟,例如主節點內存碎片率過高,或者希望調整一些只能在啟動時調整的參數。如果使用普通的手段重啟主節點,會使得runid發生變化,可能導致不必要的全量複製。為了解決這個問題,Redis提供了debug reload的重啟方式:重啟後,主節點的runid和offset都不受影響,避免了全量複製。
可以採用樹狀結構降低多個從節點對主節點的消耗從節點採用樹狀樹非常有用,網路開銷交給位於中間層的從節點,而不必消耗頂層的主節點。但是這種樹狀結構也帶來了運維的複雜性,增加了手動和自動處理故障轉移的難度。
由於 Redis 的單線程架構,通常單台機器會部署多個 Redis 實例。當一台機器(machine)上同時部署多個主節點(master)時,如果每個 master 主機只有一台 slave 從機,那麼當機器宕機以後,會產生大量全量複製。這種情況是非常危險的情況,帶寬馬上會被佔用,會導致不可用。
應該把主節點盡量分散在多台機器上,避免在單台機器上部署過多的主節點。當主節點所在機器故障後提供故障轉移機制,避免機器恢復後進行密集的全量複製
本次課程就講到這裡了,=====>下一節課就開始編寫命令測試運行今天的全量複製和部分複製以及延遲問題的實戰。
請大家關注我的專欄,更多的精彩等著你。謝謝。
推薦閱讀: