深入探討redis:主從復制

前言

如果某個服務器程序,只部署在一個物理服務器上就可能會面臨一下問題(單點問題)

  • 可用性問題,如果這個機器掛了,那么對應的客戶端服務也相繼斷開
  • 性能/支持的并發量有限

所以為了解決這些問題,就要引入分布式系統,在分布式系統中,會在多臺服務器上部署redis服務,從而形成一個redis集群,此時就可以讓這個集群給整個分布式系統提供更穩定有效的服務。

redis存在多種部署方式

  1. 主從模式
  2. 主從+哨兵模式
  3. 集群模式

主從模式

介紹

在若干個redis節點(物理服務器)中,有的節點被作為主節點,有的則作為從節點分別部署在redis-server進程中,從節點上的數據跟隨主節點上的數據變化并保持一致。也就是說如果主節點上保存了一些數據,那么就要將這些數據復制一份出來給從節點,當主節點對這些數據有修改時,從節點也要進行對應的修改,并且從節點上的數據是不能主動或直接修改的,只能讀取數據。

//從節點也可以看作是主節點的副本。

通過引入從節點,讓我們的服務器有了更多的硬件資源,后續如果有客戶端來進行讀取數據,就可以在所有節點中隨機挑選一個進行讀取,因為從節點的數據和主節點的數據是保持一致的,也就可以互相分擔更多的請求量,從而提高了服務器的性能

而且引入多臺服務器,也能大大提高服務器的穩定性,當有一臺機器掛了的時候,還可以訪問其他服務器,如果是主節點掛了,那么影響的也只是寫操作,讀操作依然可以通過從節點進行(主節點只有一個)。但是這種方式只能提高讀操作的效率和穩定性,對于寫操作因為只能在主節點上完成所以并沒有什么提高。

通過單機實現主從模式

雖然主從模式需要多臺服務器才能部署,但是我們可以通過在一臺機器上,開啟多個redis進程服務來模擬一個主從模式,但是這些進程的端口號必須不同。

這里我們來模擬部署一個主節點兩個從節點

首先先復制兩個配置文件,在配置文件中配置不同的redis端口

mkdir redis-conf
cp /etc/redis/redis.conf ./slave1.conf
cp /etc/redis/redis.conf ./slave2.conf

接著配置端口號

這個daemonize表示讓redis按照后臺進程的方式來運行

最后運行redis服務器

vim slave1.conf
vim slave2.conf
redis-server ./slave1.conf
redis-server ./slave2.conf

可以看到三個端口都成功運行,但是這只是三個redis服務器,互相獨立并沒有構成主從結構,想要實現主從結構還需要進一步配置

想要配置成主從結構,需要使用slaveof

  1. 在配置文件中加入slaveof (masterHost) (masterPort)隨redis啟動時生效
  2. 在redis-server啟動命令時加入 --slaveof (masterHost) (masterPort)隨redis關閉
  3. 直接使用redis命令:slaveof?(masterHost) (masterPort)

這里我們使用配置文件的方式

將兩個文件都加上該配置,配置完之后需要重新啟動redis,這里世界使用kill -9

netstat -anp | grep redis
kill -9 3748325 3748331

不過這種停止redis-server的方式是和之前直接運行redis-server命令的方式搭配,如果使用的是service redis-server start 的方式啟動,就必須使用service redis-server stop停止,因為使用service redis-server start的方式啟動的進程,如果使用kill -9殺掉之后,這個redis-server進程會立刻自動重啟

?

當重新啟動后會看到多了幾個tcp連接,這些連接就代表著主從節點直接的連接,每兩個是一對。主節點就相當于服務器,從節點就相當于客戶端。

//另外一個連接則是單獨啟動redis-cli來和redis主節點建立的連接

我們來看看到底有沒有連上

可以看到我們在6379端口插入的key,在6380依然可以查看到 并且在6380端口不能進行寫操作,說明我們已經構建了一個主從模式。

查看redis節點信息

info replication

?主節點信息

  • role:表示是主節點還是從節點
  • connected_slaves:表示該主節點有幾個從節點
  • slave:ip:表示從節點地址
  • port:表示從節點端口號
  • state:表示從節點在線狀態
  • offset: 表示主節點和從節點之間同步數據的進度
  • lag:表示延遲

從節點信息

可以看到從節點也有?connected_slaves表示從節點也可以有自己的從節點,主從結構不一定就是一個主機連多臺從節點,每個從節點也可以再連其他從節點。

斷開主從連接

slaveof no one

直接使用這個命令,就會斷開當前的主從關系,當從節點斷開主節點時,雖然已經不屬于這個從節點了,但是里面的數據是不會被刪除的,只是后面主節點的數據再發生更改,這個從節點就不會再同步數據了。

主節點

從節點

從信息中可以看到主從節點的關系已經斷開,接下來我們實現是否還能同步數據

數據已經無法同步

因為6379和6380已經不是主從節點,所以我們就可以更換6380的主節點

看以看到已經成功把6380的主節點更換成6381,主從模式的結構也發生了改變

此時6380端口的redis服務的數據又和6379一致了,不過雖然此時的6381看起來像是6380的主節點,但是實際上并不是,他仍然是一個從節點不能進行寫操作,只是作為6380同步數據的來源。

//剛才通過slaveof修改了主從結構,但是此處的主從結構修改是臨時的,如果重啟了redis服務器,仍然會變成剛開始的結構,因為我們的配置文件里所配置的結構就是和剛開始的結構一樣。

拓撲結構

一主一從

一主一從結構是最簡單的復制拓撲結構,用于主節點出現故障時向從節點提供故障轉移支持。

這種結構可以幫主節點分擔讀數據請求,但是如果寫數據請求太多,此時也是會給主節點造成不小的壓力,可以通過關閉主節點的AOF,只在從節點上開啟。也就是只讓主節點進行寫內存操作,這樣就可以減小主節點的壓力。

但是這樣的設定有一個問題,如果主節點掛了,不能讓他自動重啟,因為如果自動重啟了,此時因為沒有AOF文件,就會導致主節點數據丟失,并且因為主從復制,就會把從節點的數據也給刪了。所以當主節點掛了之后,應該讓主節點先在從節點那里獲取AOF文件后,在啟動。

一主多從(星形結構)

一種多從的結構方式,可以使節點讀寫分離,當有大量讀請求時可以將請求分攤給各個從節點,還可以讓一個從節點專門處理一些比較復雜的讀操作以此來提高整體穩定性。

但是主節點上的數據改變時,需要把數據同時同步給所以從節點,也就意味著,隨著從節點個數的增加,每次同步數據都會帶來更大的開銷。而且主從節點之間需要通過網絡通信,這就要求主節點有更大的帶寬,進而提高整體設備的成本。

樹形主從結構

通過這樣的結果就可以讓主節點有固定的從節點,可以通過從節點來對其他從節點的數據進行同步,但是相應的同步的效率也會變低

主從復制原理?

主從復制流程

  1. 保存主節點信息,開始配置主從同步關系后,從節點只保存主節點的地址信息
  2. 主從節點建立tcp連接(三次握手),從節點內部通過每秒運行的定時任務,維護復制相關邏輯,當定時任務發現存在存在新的主節點后,會嘗試與主節點建立基于tcp的網絡連接,如果連接失敗,定時任務會無限重試直到連接成功或者用戶停止主從復制。
  3. 發送ping命令,驗證主節點是否正常工作
  4. 如果redis主節點設置了密碼(requirepass參數),就要驗證權限,從節點通過配置masterauth參數來設置密碼。
  5. 同步數據集,主節點會把當前的所有數據全部發送給從節點,這步也是耗時最大的,分為全量同步和部分同步
  6. 命令持續復制,從節點復制主節點數據后,主節點會持續把命令發給從節點,從節點執行修改命令,確保主從數據一致

redis提供了psync replicationid offset命令來完成數據同步,不過一般這個命令是由服務器建立tcp連接后自動執行。

replicationid

這個id是由主節點生成的,每次服務器重啟主節點的replicationid都會不同,并且每個主節點有兩個id,id1和id2,但是一般只是用id1,從節點和主節點建立關系就會獲取主節點的replicationid。另外當從節點通過一些心跳包確定主節點已經掛了的話,就會自己成為主節點,并且給自己生成一個replicationid,但是此時這個節點會通過id2任然記住之前的主節點的id,等到主節點上線后這個節點就可以通過id2再找到原來的主節點

?offset 偏移量

主節點和從節點上都會維護offset偏移量,主節點的偏移量就是,主節點會有很多修改操作,每個命令都會占用幾個字節,主節點就會把這些字節累加。從節點的偏移量就描述了同步數據的進度,如果從節點和主節點的replicationid和offset偏移量都一樣,就可以認為主從節點數據一致。

psync流程?

從節點發送psync命令給主節點,主節點會根據psync的參數(id和offset)以及自身數據情況決定響應情況。

  • FULLRESYNC:全量數據同步
  • CONTINFU:增量數據同步
  • -ERR:比較老版本的redis不支持psync

psync可以從主節點獲取全部數據也可以獲得部分數據主要看參數offset,如果是-1(默認)的話就是獲取全量數據,如果是一個具體的值就是部分復制而且從當前偏移量開始復制,不過也不是從節點想從哪個地方復制就從那個地方復制,主節點也會根據實際判斷。

什么時候全量復制

  • 首次和主節點進行數據同步
  • 主節點不方便進行部分復制

什么時候部分復制

  • 從節點已經從主節點上復制過數據了,因為一些原因斷開連接了,從節點需要重新從主節點這邊同步數據,此時因為從節點上已經有數據了所以只需要復制一部分就行

全量復制流程

1)從節點發送psync命令向主節點要數據,因為是第一次進行復制則psync參數就是(?,-1)表示進行全量復制。

2)主節點收到命令解析后回復FULLRESYNC響應

3)從節點收到響應后會保存主節點的運行信息

4)之后主節點會自動執行bgsave命令,進行快照操作完成持久化,并復制出一個新的rdb文件。(因為從節點的數據和主節點的數據要求完全同步,所以必須使用新的rdb文件以保證數據的實時性)

5)主節點將新復制的rdb文件傳輸給從節點(因為復制rdb文件是一個較高消耗的操作,而且這次是全量復制所以要傳輸的數據也比較多,所以整體過程較為耗時。就會導致在這個過程中會有新的修改命令,那么我們從節點接收到的rdb文件就不是最新的了)

6)因為無法保證傳輸的rdb文件是最新的,所以主節點會將復制和傳輸rdb文件期間接收到的寫命令放入一個緩沖區,當從節點保存完rdb文件后,主節點就會將緩沖區中的數據傳輸給從節點,這些數據任然是按照rdb的二進制格式追加到從節點的rdb文件中,以保證主從節點數據的完全一致。

7)從節點清除自身的舊數據

8)從節點加載rdb文件

9)如果從節點開啟了AOF,那么在加載的時候就會產生大量的aof日志,因為全量復制的數據量很大就會出現很多冗余的日志,因此這里就會執行bgrewriteaof,將aof文件里該刪的刪,該合并的合并,對文件進行一個整理。

無硬盤模式全量復制

在剛剛的流程中主節點復制一份新的rdb文件目的就是為了,將數據傳輸給從節點,那么為了節省開銷,就可以省去這個讀寫硬盤的操作(復制rdb),直接將數據通過網絡傳輸給從節點,這樣就節省了一次復制rdb的時間,從節點接收到數據后也是寫入到rdb文件然后加載數據,那么將這個過程也省略掉,直接把收到的數據進行加載,這樣就又省了一系列讀寫硬盤的操作

部分復制流程

當主從節點都正常工作一段時間后,此時從節點已經有了主節點的復制,如果在某一時刻因為網絡抖動,或者其他原因主從節之間的連接斷開了的話,后續再連接上就只需要進行部分復制(具體連接過程上文有提到)。

1)如果主從節點斷開的時間超過repi-timeout設定的時間,那么主節點就認為從節點斷開了

2)從節點在斷開連接時依然會響應命令,但是由于這些復制命令發不出去都會放在一個積壓緩沖區里(一個用數組實現的環形隊列)

3)重新連接后,從節點會根據之前保存的主節點的replicationid和offset通過psync的參數發送給主節點?

4)主節點接收到psync命令后會對replicationid和offset(描繪的就是主從節點的復制進度)進行判斷,如果replicationid不是自己的replicationid主節點就會認為這個從節點是新連接上的就會進行全量復制,如果replicationid正確則進行部分復制。判斷offset的值,主要是判斷從節點當前的復制進度是多少,如果從節點當前缺失的部分剛好是積壓緩沖區里的數據,就可以直接將這部分數據復制過去,如果不是則需要將之前缺失的數據也復制過去,最后主節點還要響應CONTINUE表示這是一次部分復制。

實時復制

從節點已經和主節點同步好了數據,但是主節點依然會又源源不斷的新的請求,主節點的數據改變,從節點的數據也就要改變。

主從節點之間會通過TCP建立長連接,然后主節點會把自己收到的修改數據的請求通過連接發送給從節點,從節點在根據這些請求修改自己的數據。(如果主從結構是樹型的那么發送的過程就會較為耗時)

因為在實時復制時,主從節點需要保證連接的穩定,就會通過心跳機制來確定對方是否正常在線。

  • 主節點:默認是每10s給從節點發送一個ping命令,從節點收到后就會返回pong
  • 從節點:默認每個1s就給主節點發送一個特殊的請求,就會通知主節點自己當前的復制進度offset

總結?

全量復制的部分復制都是在從節點第一次連接主節點時進行的,如果以前沒連過就進行全量復制,如果連接過又斷開的就進行部分復制,也就是說全量復制和部分復制都是給從節點進行一個初始化的。而后續的主從節點間數據的同步則是通過實時復制。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/83039.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/83039.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/83039.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

MacOS安裝Docker Desktop并漢化

1. 安裝Docker Desktop 到Docker Desktop For Mac下載對應系統的Docker Desktop 安裝包,下載后安裝,沒有賬號需要注冊,然后登陸即可。 2. 漢化 前往漢化包下載鏈接下載對應系統的.asar文件 然后將安裝好的文件覆蓋原先的文件app.asar文件…

索引的選擇與Change Buffer

1. 索引選擇與Change Buffer 問題引出:普通索引 vs 唯一索引 ——如何選擇? 在實際業務中,如果一個字段的值天然具有唯一性(如身份證號),并且業務代碼已確保無重復寫入,那就存在兩種選擇&…

lua注意事項

感覺是lua的一大坑啊,它還不如函數內部就局部變量呢 注意函數等內部,全部給加上local得了

【多線程初階】死鎖的產生 如何避免死鎖

文章目錄 關于死鎖一.死鎖的三種情況1.一個線程,一把鎖,連續多次加鎖2.兩個線程,兩把鎖3.N個線程,M把鎖 --哲學家就餐問題 二.如何避免死鎖死鎖是如何構成的(四個必要條件)打破死鎖 三.死鎖小結 關于死鎖 一.死鎖的三種情況 1.一個線程,一把鎖,連續多次加鎖 -->由synchroni…

【NLP基礎知識系列課程-Tokenizer的前世今生第二課】NLP 中的 Tokenizer 技術發展史

從詞表到子詞:Tokenizer 的“進化樹” 我們常說“語言模型是理解人類語言的工具”,但事實上,模型能不能“理解”,關鍵要看它接收到了什么樣的輸入。而 Tokenizer,就是這一輸入階段的設計者。 在 NLP 的發展歷程中&am…

Rust 學習筆記:循環和迭代器的性能比較

Rust 學習筆記:循環和迭代器的性能比較 Rust 學習筆記:循環和迭代器的性能比較示例 1示例 2總結 Rust 學習筆記:循環和迭代器的性能比較 示例 1 我們運行一個基準測試,將《福爾摩斯探案集》的全部內容加載到一個字符串中&#x…

pod創建和控制

一、引言 ?主題?:pod以及控制器模式中的Deployment作用。?控制器模式:使用一種API對象(如Deployment)管理另一種API對象(如Pod)的方式。 二、容器鏡像與配置文件 ?容器鏡像?:應用開發者…

HTML實戰:愛心圖的實現

設計思路 使用純CSS創建多種風格的愛心 添加平滑的動畫效果 實現交互式愛心生成器 響應式設計適應不同設備 優雅的UI布局和色彩方案 <!DOCTYPE html> <html lang"zh-CN"> <head> <meta charset"UTF-8"> <meta nam…

2022年 中國商務年鑒(excel電子表格版)

2022年 中國商務年鑒&#xff08;excel電子表格版&#xff09;.ziphttps://download.csdn.net/download/2401_84585615/89772883 https://download.csdn.net/download/2401_84585615/89772883 《中國商務年鑒2022》是由商務部國際貿易經濟合作研究院主辦的年度統計資料&#xf…

Redis核心數據結構操作指南:字符串、哈希、列表詳解

注&#xff1a;此為蒼穹外賣學習筆記 Redis作為高性能的鍵值數據庫&#xff0c;其核心價值來自于豐富的數據結構支持。本文將深入解析字符串&#xff08;String&#xff09;、哈希&#xff08;Hash&#xff09;、**列表&#xff08;List&#xff09;**三大基礎結構的操作命令&…

如何以 9 種方式將照片從 iPhone 傳輸到筆記本電腦

您的 iPhone 可能充滿了以照片和視頻形式捕捉的珍貴回憶。無論您是想備份它們、在更大的屏幕上編輯它們&#xff0c;還是只是釋放設備上的空間&#xff0c;您都需要將照片從 iPhone 傳輸到筆記本電腦。幸運的是&#xff0c;有 9 種方便的方法可供使用&#xff0c;同時滿足 Wind…

如何使用Python從MySQL數據庫導出表結構到Word文檔

在開發和維護數據庫的過程中&#xff0c;能夠快速且準確地獲取表結構信息是至關重要的。本文將向您展示一種簡單而有效的方法&#xff0c;利用Python腳本從MySQL數據庫中提取指定表的結構信息&#xff0c;并將其導出為格式化的Word文檔。此方法不僅提高了工作效率&#xff0c;還…

寫作-- 復合句練習

文章目錄 練習 11. 家庭的支持和老師的指導對學生的學術成功有積極影響。2. 缺乏準備和未能適應通常會導致在挑戰性情境中的糟糕表現。3. 吃垃圾食品和忽視鍛煉可能導致嚴重的健康問題,因此人們應注重保持均衡的生活方式。4. 昨天的大雨導致街道洪水泛濫,因此居民們遷往高地以…

QT使用說明

QT環境準備 推薦Ubuntu平臺上使用&#xff0c;配置簡單&#xff0c;坑少。 Ubuntu 20.04 安裝 sudo apt-get install qt5-default -y sudo apt-get install qtcreator -y sudo apt-get install -y libclang-common-8-dev啟動 qtcreatorHelloWorld 打開 Qt Creator。選擇 …

React 第四十九節 Router中useNavigation的具體使用詳解及注意事項

前言 useNavigation 是 React Router 中一個強大的鉤子&#xff0c;用于獲取當前頁面導航的狀態信息。 它可以幫助開發者根據導航狀態優化用戶體驗&#xff0c;如顯示加載指示器、防止重復提交等。 一、useNavigation核心用途 檢測導航狀態&#xff1a;判斷當前是否正在進行…

列表單獨展開收起同時關閉其余子項的問題優化

如圖所示&#xff0c;當在列表中&#xff0c;需要分別單獨點開子選項時&#xff0c;直接這樣用一個index參數判斷即可&#xff0c;非常簡單方便&#xff0c;只需要滿足點開當前index,然后想同index用null值自動關閉即可

WPF【11_5】WPF實戰-重構與美化(MVVM 實戰)

11-10 【重構】創建視圖模型&#xff0c;顯示客戶列表 正式進入 MVVM 架構的代碼實戰。在之前的課程中&#xff0c; Model 和 View 這部分的代碼重構實際上已經完成了。 Model 就是在 Models 文件夾中看到的兩個文件&#xff0c; Customer 和 Appointment。 而 View 則是所有與…

LangChain-結合魔塔社區modelscope的embeddings實現搜索

首先要安裝modelscope pip install modelscope 安裝完成后測試 from langchain_community.embeddings import ModelScopeEmbeddingsembeddings ModelScopeEmbeddings(model_id"iic/nlp_gte_sentence-embedding_chinese-base")text "這是一個測試句子"…

可定制化貨代管理系統,適應不同業務模式需求!

在全球化貿易的浪潮下&#xff0c;貨運代理行業扮演著至關重要的角色。然而&#xff0c;隨著市場競爭的日益激烈&#xff0c;貨代企業面臨著越來越多的挑戰&#xff1a;客戶需求多樣化、業務流程復雜化、運營成本上升、利潤空間壓縮……這些挑戰迫使貨代企業不斷尋求創新和突破…

Lyra學習筆記2 GFA_AddComponents與ULyraPlayerSpawningManagerComponent

目錄 前言GameFeatureAction_AddComponentsULyraPlayerSpawningManagerComponent緩存所有PlayerStart位置選擇位置 前言 1.以control模式為例 2.比較散&#xff0c;想單獨拿出一篇梳理下Experience的流程 GameFeatureAction_AddComponents 這部分建議看 《InsideUE5》GameFeatu…