1 簡介
1.1 Redis在單機、單節點、單實體下存在的問題
- 單機故障
- 記憶體容量有限
- 訪問壓力
Redis主從架構主要解決的問題:單機故障和訪問壓力,通過主從架構可以將訪問流量分攤到多臺服務器上,加上哨兵機制實作主從架構的高可用,主從架構將主節點資料復制到從節點即資料的冗余備份原理,所以不能解決記憶體容量的問題,記憶體容量可以通過Redis集群解決,
1.2 主從架構概述

主從復制,是指將一臺 Redis 服務器的資料(master 主節點),復制到其他的 Redis 服務器( slave 從節點),資料的復制是單向的,只能由主節點到從節點,
默認情況下,每臺 redis 服務器都是主節點,且一個主節點可以有多個從節點,但一個從節點只能有一個主節點,
1.3 主從復制作用
- 資料冗余:主從復制實作了資料的熱備份,是持久化之外的一種資料冗余方式;
- 故障恢復:當主節點出現問題時,可以由從節點提供服務,實作快速的故障恢復;實際上是一種服務的冗余,
- 負載均衡:在主從復制的基礎上,配合讀寫分離,寫資料時應用連接主節點,讀資料時應用連接從節點,分擔服務器負載;尤其是在寫少讀多的場景下,通過多個從節點分擔讀負載,可以大大提高 Redis 服務器的并發量,
- 高可用:主從復制是哨兵模式和集群能夠實施的基礎,
2 主從復制實作
2.1 環境準備
- CentOS7 3臺
- 192.168.88.110 埠6379 主機名q110(下面統一簡稱為主機名)
- 192.168.88.111 埠6379 主機名q111(下面統一簡稱為主機名)
- 192.168.88.112 埠6379 主機名q112(下面統一簡稱為主機名)
- Redis-6.2.6
2.2 網路拓撲圖

2.3 Redis安裝
3臺服務器安裝Redis6.2.6
官網
中文
Redis安裝包解壓完成后,詳細安裝目錄可以查看README.md
# 1. 安裝gcc
yum install gcc
# 2. 下載安裝包
wget https://download.redis.io/releases/redis-6.2.6.tar.gz
tar -xf redis-6.2.6.tar.gz
# 3. 編譯
cd redis-6.2.6 && make
cd src && make install PREFIX=/usr/local/redis
# 4. 配置環境變數
vi /etc/profile
# 添加環境變數
export REDIS_HOME=/usr/local/redis
export PATH=$PATH:$REDIS_HOME/bin
source /etc/profile
# 5. 根據Redis官方提供的腳本一鍵安裝
cd ../../redis-6.2.6/utils
./install_server.sh
運行第5步報錯,錯誤資訊如下:

注釋掉install_server.sh 中報錯部分后重新執行install_server.sh

# 可執行多次,物理機中可以有多個Redis實體,通過port區分
./install_server.sh
# 根據提示內容按需修改,不修改直接回車確認

執行完成后redis實體默認已啟動,配置及日志檔案路徑上圖也有輸出,

2.4 配置主從復制
從節點開啟主從配置,有 3 種方式:
- 組態檔:在組態檔加入 slave < masterip > < masterport >
- 啟動命令:redis-server 啟動命令后加入 --slave < masterip > < masterport >
- 客戶端命令:Redis 服務器啟動后,直接通過客戶端執行命令:slave < masterip > < masterport >
本文通過常用的組態檔加入,
Master節點修改配置:
修改/etc/redis/6379.conf 中的bind,默認只能本機訪問,需添加2臺salve 節點ip,
Slave節點修改:
修改q111和q112兩臺都需要修改
- 修改/etc/redis/6379.conf 中的bind,默認只能本機訪問,需添加2臺salve 節點ip,
bind 192.168.88.100 - 配置主節點IP和埠
vi /etc/redis/6379.conf
# 修改,如果主節點存在用戶名和密碼也需要配置上
replicaof 192.168.88.110 6379

重啟3臺從redis服務
systemctl restart redis_6379
驗證
通過查看Master Redis日志可以看到已經將RDB同步到磁盤并發送給Salve節點,

查看Slave Redis日志可以看到已經從Master節點將RDB同步到磁盤

注意: Slave在同步Master節點RDB資料時會先洗掉自己的RDB檔案,
通過客戶端連接后在Master節點set 一個key 后 在Slave節點get 該key可以看到資料已經同步,
q112

q111

至此,主從復制已配置完畢,目前主從配置存在疑問:
當Slave down掉后,重新啟動,是從Master從新拉全全量RDB還是增量資料?
3 主從資料同步原理
3.1 測驗資料同步
3.1.1 Slave與Master首次建立主從
首次建立主從會全量同步,可查看2.4日志,
3.1.2 建立主從后Slave斷開一段時間后重新啟動
從上面2.4測驗可以看到當Slave跟隨Master時,會將RDB檔案同步并清除自己所有資料,重新加載Master的RDB資料,我們可以在Slave已經與Master建立好主從關系后(資料已經同步)再將Slave關掉,在Slave關閉期間,往Master中添加資料,然后再重新啟動Slave,
查看Slave啟動日志:

查看RDB源檔案:

從Slave RDB源檔案中可以看到,已經有保存repla-id 即MasterID,從日志中可以看到,當Slave在與Master已經建立主從關系情況下,宕機重啟后并不會將Master資料全量同步,這與首次建立主從關系有不同,
3.1.3 測驗AOF開啟
上面的測驗3.1.2 可以看出可能是因為RDB中已經存在了Master repla-id所有再次啟動時不會全量同步,我們再測下將Slave開啟AOF開啟后,同樣在關閉Slave期間Master增加資料后再啟動Slave,
- 主機q112中執行
# 關閉Redis
systemctl stop redis_6379
# 修改配置
vi /etc/redis/6379.conf
# 開啟AOF,組態檔中修改以下內容
appendonly yes

- Master中增加一些資料
- 重啟Slave查看啟動日志

通過日志中可以看在,在已經與Master建立了主從情況下并且開啟AOF后,重新啟動也會將全量資料同步到本地及記憶體,為了確實是否是第一次開啟AOF才會全量同步,可以將此2.5.2實驗再重試一次,得到的結論是一樣的即:Redis主從中Slave開啟AOF后每次重啟會加載Master全量資料,里面具體原理是什么呢?
3.2 主從復制原理
3.2.1 資料同步原理
從節點通過發送psync命令請求同步資料,此時根據主從節點當前狀態的不同,同步方式可能是全量復制或部分復制,
- 全量復制:用于初次復制或其他無法進行部分復制的情況,將主節點中的所有資料都發送給從節點,是一個非常重型的操作,如果從節點開啟了AOF,則會觸發bgrewriteaof的執行,從而保證AOF檔案更新至主節點的最新狀態;
- 部分復制:用于網路中斷等情況后的復制,只將中斷期間主節點執行的寫命令發送給從節點,與全量復制相比更加高效,需要注意的是,如果網路中斷時間過長,導致主節點沒有能夠完整地保存中斷期間執行的寫命令,則無法進行部分復制,仍使用全量復制,
Redis使用一對Replicaion ID, offset來唯一識別Master節點資料集的版本,要理解這個“版本“的概念需要認識Redis的以下三個概念:
- Replication ID(復制ID):每個Redis的主節點都用一個隨機生成的字串來表示在某一時刻其內部存盤資料的狀態,“某一時刻”可以理解為其成為master角色的那一刻,由原始碼可知在第一個從節點加入時,Redis初始化了復制ID,
- offset(復制偏移量):主從模式下,主節點會持續不斷的向從節點傳播引起資料集更改的命令,offset所表示的是主節點向從節點傳遞命令位元組總數,它不是孤立存在的,需要配合復制積壓緩沖區才能作業,
- backlog(復制積壓緩沖區):它是一個環形緩沖區,用來存盤主節點向從節點傳遞的命令,它的大小是固定的,可存盤的命令有限,超出部分將會被洗掉,它即可用于部分同步,也可用于命令傳播階段的命令重推,

上圖說明:
- 圖示Redis角色為Master,其復制ID(replid)為xxxx,當前的復制偏移量(offset)為1010;
- 它有一個復制積壓緩沖區(backlog),容量(backlog_size)為100,backlog起點相對于offset的偏移量(backlog_off)為1000,當前backlog存盤的命令位元組數(backlog_hislen)為11個,對應了backlog中【1000,1010】偏移量范圍內的位元組;
- offset始終與backlog中最后一個位元組的偏移量相同,
上圖分析: - Redis-1:replid和offset為默認值,說明它從未與主節點進行過同步操作,所以是進行全量同步;
- Redis-2:replid主從節點一致,slave_offset>=backlog_off并且slave_offset<offset,說明該從節點丟失的資料可以通過復制積壓緩沖區找回,所以可以進行部分同步;
- Redis-3:replid主從節點一致,slave_offset<backlog_off,說明該節點丟失的資料過多,通過復制積壓緩沖區無法找回,所以是進行全量同步;
- Redis-4:replid主從節點一致,之前不是與當前節點進行主從復制,所以是進行全量同步;
總結:部分同步其實是以全量同步為基礎(得到復制ID),用復制積壓緩沖區中的快取命令做命令重放的增量同步邏輯,不過受制于復制積壓緩沖區的容量,它可容忍的范圍是有限的,這與持久化機制的AOF混合持久化如出一轍,也與mysql中主從復制的Binlog思路不謀而合,
3.2.2 命令的執行
Master-Slave建立主從關系后,當Master執行完寫操作命令后,會通過psync把寫命令追加至復制積壓緩沖區,然后異步地發送給slave,slave接收命令并執行,同時更新slave維護的復制偏移量offset,

復制積壓緩沖區是由主節點維護的、固定長度的、先進先出(FIFO)佇列,默認大小1MB(通過配置repl-backlog-size),例如如果網路中斷的平均時間是60s,而主節點平均每秒產生的寫命令(特定協議格式)所占的位元組數為100KB,則復制積壓緩沖區的平均需求為6MB,保險起見,可以設定為12MB,來保證絕大多數斷線情況都可以使用部分復制,
從節點將offset發送給主節點后,主節點根據offset和緩沖區大小決定能否執行部分復制:
- 如果offset偏移量之后的資料,仍然都在復制積壓緩沖區里,則執行部分復制;
- 如果offset偏移量之后的資料已不在復制積壓緩沖區中(資料已被擠出),則執行全量復制,
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/433313.html
標籤:其他
