什么是Redis的主從復制
主從復制囱挑,是指將一臺Redis服務(wù)器的數(shù)據(jù),復制到其他的Redis服務(wù)器旨枯。前者稱為主節(jié)點(master)独悴,后者稱為從節(jié)點(slave)例书;數(shù)據(jù)的復制是單向的,只能由主節(jié)點到從節(jié)點绵患。
默認情況下雾叭,每臺Redis服務(wù)器都是主節(jié)點;且一個主節(jié)點可以有多個從節(jié)點(或沒有從節(jié)點)落蝙,但一個從節(jié)點只能有一個主節(jié)點织狐。
主從復制的作用
主從復制是Redis高可用的基礎(chǔ),主要的作用的故障恢復筏勒。當主節(jié)點出現(xiàn)問題時移迫,可以由從節(jié)點提供服務(wù),實現(xiàn)快速的故障恢復
主從復制的開啟
主從復制的開啟管行,完全是在從節(jié)點發(fā)起的厨埋;不需要我們在主節(jié)點做任何事情
在從服務(wù)器的配置文件中加入:
slaveof <masterip> <masterport>
主從復制的測試
在同一臺機器是部署主節(jié)點和從節(jié)點
在centos安裝redis
yum install redis
默認的配置文件在/etc/redis.conf
啟動時報錯,根據(jù)日志里的提示修改
把下面的命令添加到/etc/sysctl.conf 文件:
vm.overcommit_memory = 1
net.core.somaxconn = 2048
把下面的命令添加到/etc/rc.local 文件:
echo never > /sys/kernel/mm/transparent_hugepage/enabled
重啟系統(tǒng)
部署
master的配置文件修改:
復制/etc/redis.conf到/etc/redis/6379.conf
修改6379.conf文件
daemonize yes
啟動:
redis-server /etc/redis/6379.conf
查看日志:
tail -f /var/log/redis/redis.log
slave的配置文件修改
復制/etc/redis/6379.conf到/etc/redis/6380.conf
修改:
port 6380
daemonize yes
pidfile /var/run/redis_6380.pid
dbfilename slave_dump.rdb
appendfilename "slave_appendonly.aof"
slaveof 127.0.0.1 6379
啟動:
redis-server /etc/redis/6380.conf
測試
連接上主節(jié)點
[root@VM_0_4_centos ~]# redis-cli -h 127.0.0.1 -p 6379
127.0.0.1:6379> get hello
(nil)
127.0.0.1:6379> set hello world
OK
連接上從節(jié)點
[root@VM_0_4_centos ~]# redis-cli -h 127.0.0.1 -p 6380
127.0.0.1:6380> get hello
"world"
可以看到從機上有主機同步過來的數(shù)據(jù)
主從復制原理
全量復制
1.主節(jié)點收到全量復制的命令后捐顷,執(zhí)行bgsave荡陷,在后臺生成RDB文件,并使用復制緩沖區(qū)記錄從現(xiàn)在開始執(zhí)行的所有寫命令
2.主節(jié)點的bgsave執(zhí)行完成后迅涮,將RDB文件發(fā)送給從節(jié)點
3.從節(jié)點首先清除自己的舊數(shù)據(jù)废赞,然后載入接收的RDB文件,將數(shù)據(jù)庫狀態(tài)更新至主節(jié)點執(zhí)行bgsave時的數(shù)據(jù)庫狀態(tài)
4.主節(jié)點將前述復制緩沖區(qū)中的所有寫命令發(fā)送給從節(jié)點叮姑,從節(jié)點執(zhí)行這些寫命令唉地,將數(shù)據(jù)庫狀態(tài)更新至主節(jié)點的最新狀態(tài)
5.如果從節(jié)點開啟了AOF,則會觸發(fā)bgrewriteaof的執(zhí)行传透,從而保證AOF文件更新至主節(jié)點的最新狀態(tài)
通過全量復制的過程可以看出耘沼,全量復制是非常重型的操作:
(1)主節(jié)點通過bgsave命令fork子進程進行RDB持久化,該過程是非常消耗CPU朱盐、內(nèi)存(頁表復制)群嗤、硬盤IO的;
(2)主節(jié)點通過網(wǎng)絡(luò)將RDB文件發(fā)送給從節(jié)點兵琳,對主從節(jié)點的帶寬都會帶來很大的消耗
(3)從節(jié)點清空老數(shù)據(jù)骚烧、載入新RDB文件的過程是阻塞的,無法響應(yīng)客戶端的命令闰围;如果從節(jié)點執(zhí)行bgrewriteaof,也會帶來額外的消耗
部分復制
- 復制偏移量
主節(jié)點和從節(jié)點分別維護一個復制偏移量(offset)既峡,代表的是主節(jié)點向從節(jié)點傳遞的字節(jié)數(shù)羡榴;主節(jié)點每次向從節(jié)點傳播N個字節(jié)數(shù)據(jù)時,主節(jié)點的offset增加N运敢;從節(jié)點每次收到主節(jié)點傳來的N個字節(jié)數(shù)據(jù)時校仑,從節(jié)點的offset增加N忠售。
- 復制積壓緩沖區(qū)
是由主節(jié)點維護的、固定長度的迄沫、先進先出(FIFO)隊列稻扬,默認大小1MB;當主節(jié)點開始有從節(jié)點時創(chuàng)建羊瘩,其作用是備份主節(jié)點最近發(fā)送給從節(jié)點的數(shù)據(jù)泰佳。注意,無論主節(jié)點有一個還是多個從節(jié)點尘吗,都只需要一個復制積壓緩沖區(qū)逝她。
- 服務(wù)器運行ID(runid)
每個Redis節(jié)點(無論主從),在啟動時都會自動生成一個隨機ID(每次啟動都不一樣)睬捶,由40個隨機的十六進制字符組成黔宛;runid用來唯一識別一個Redis節(jié)點。
主從節(jié)點初次復制時擒贸,主節(jié)點將自己的runid發(fā)送給從節(jié)點臀晃,從節(jié)點將這個runid保存起來;當斷線重連時介劫,從節(jié)點會將這個runid發(fā)送給主節(jié)點徽惋;主節(jié)點根據(jù)runid判斷能否進行部分復制:
如果從節(jié)點保存的runid與主節(jié)點現(xiàn)在的runid相同,說明主從節(jié)點之前同步過蜕猫,主節(jié)點會繼續(xù)嘗試使用部分復制(到底能不能部分復制還要看offset和復制積壓緩沖區(qū)的情況)寂曹;
如果從節(jié)點保存的runid與主節(jié)點現(xiàn)在的runid不同,說明從節(jié)點在斷線前同步的Redis節(jié)點并不是當前的主節(jié)點回右,只能進行全量復制隆圆。
psync命令的執(zhí)行過程
(1)首先,從節(jié)點根據(jù)當前狀態(tài)翔烁,決定如何調(diào)用psync命令:
如果從節(jié)點之前未執(zhí)行過slaveof或最近執(zhí)行了slaveof no one渺氧,則從節(jié)點發(fā)送命令為psync ? -1,向主節(jié)點請求全量復制蹬屹;
如果從節(jié)點之前執(zhí)行了slaveof侣背,則發(fā)送命令為psync <runid> <offset>,其中runid為上次復制的主節(jié)點的runid慨默,offset為上次復制截止時從節(jié)點保存的復制偏移量贩耐。
(2)主節(jié)點根據(jù)收到的psync命令,及當前服務(wù)器狀態(tài)厦取,決定執(zhí)行全量復制還是部分復制:
如果主節(jié)點版本低于Redis2.8潮太,則返回-ERR回復,此時從節(jié)點重新發(fā)送sync命令執(zhí)行全量復制
如果主節(jié)點版本夠新,且runid與從節(jié)點發(fā)送的runid相同铡买,且從節(jié)點發(fā)送的offset之后的數(shù)據(jù)在復制積壓緩沖區(qū)中都存在更鲁,則回復+CONTINUE,表示將進行部分復制奇钞,從節(jié)點等待主節(jié)點發(fā)送其缺少的數(shù)據(jù)即可澡为;
如果主節(jié)點版本夠新,但是runid與從節(jié)點發(fā)送的runid不同景埃,或從節(jié)點發(fā)送的offset之后的數(shù)據(jù)已不在復制積壓緩沖區(qū)中(在隊列中被擠出了)媒至,則回復+FULLRESYNC <runid> <offset>,表示要進行全量復制纠亚,其中runid表示主節(jié)點當前的runid塘慕,offset表示主節(jié)點當前的offset,從節(jié)點保存這兩個值蒂胞,以備使用图呢。