- 首先督禽,以7版本為例,在本機(jī)模擬兩臺(tái)redis总处,為了不影響其他業(yè)務(wù)的使用狈惫,在root下新建一個(gè)test目錄,將所有redis實(shí)例的配置文件復(fù)制到test目錄中鹦马。如:
[root@localhost test]# cp /etc/redis/* ./
- 用vi命令分別為test下配置文件作如下配置胧谈,即開啟RDB(默認(rèn)開啟的),關(guān)閉AOF以及混合模式:
save 3600 1 300 100 60 10000
appendonly no
aof-use-rdb-preamble no
另外為了方便觀察荸频,還可以注釋掉日志的記錄菱肖,讓日志能夠打印到控制臺(tái)上:
# logfile /var/log/redis_6379.log
還可以把服務(wù)方式調(diào)整為前臺(tái)阻塞,這樣可以更清晰的看到業(yè)務(wù)運(yùn)行過程:
daemonize no
:wq
命令退出并保存 - 進(jìn)入到test目錄下后旭从,開啟兩臺(tái)redis-server:
redis-server 6379.conf
redis-server 6380.conf
- 再開啟兩個(gè)客戶端稳强,分別對(duì)應(yīng)著服務(wù)的端口:
redis-cli -p 6379
redis-cli -p 6380
在6379的庫(kù)里分別設(shè)置一些數(shù)據(jù),如:
127.0.0.1:6379> set k1 aaa
OK
127.0.0.1:6379> set k2 bbb
OK
127.0.0.1:6379> set k3 ccc
OK
此時(shí)在6380的庫(kù)里是肯定看不到的和悦,因?yàn)槎哌€沒建立關(guān)聯(lián)退疫。同樣的,6380的數(shù)據(jù)目錄下也沒有任何內(nèi)容摹闽。
[root@localhost 6380]# ll
總用量 0
此時(shí)在6380的客戶端執(zhí)行REPLICAOF 127.0.0.1 6379
:
127.0.0.1:6380> REPLICAOF 127.0.0.1 6379
OK
127.0.0.1:6380>
此時(shí)蹄咖,返回OK代表6380作為從褐健,與6379這個(gè)主已成功建立主從關(guān)系付鹿。
這時(shí)再看6380里的鍵:
127.0.0.1:6380> keys *
1) "k1"
2) "k2"
3) "k3"
127.0.0.1:6380>
數(shù)據(jù)已經(jīng)從6379成功同步過來了。再看6380的數(shù)據(jù)文件夾蚜迅,發(fā)現(xiàn)生成了一個(gè)RDB文件舵匾。
[root@localhost 6380]# ll
總用量 4
-rw-r--r--. 1 root root 200 12月 26 19:08 dump.rdb
[root@localhost 6380]#
用vi命令打開這個(gè)RDB文件,會(huì)發(fā)現(xiàn)基本上都是亂碼谁不,但是有一些數(shù)據(jù)是可以看懂的坐梯,如:
這些aaa,bbb,ccc正是剛才在6379里設(shè)置的值,說明從已經(jīng)把主的數(shù)據(jù)同步過來形成一個(gè)RDB文件了刹帕。
- 接下來分析這個(gè)過程如何發(fā)生吵血。因?yàn)橐呀?jīng)設(shè)置過服務(wù)前臺(tái)阻塞谎替,并且讓前臺(tái)打印日志,所以我們可以對(duì)這些日志作分析蹋辅。
在6380從機(jī)執(zhí)行replicaof 127.0.0.1 6379
命令后钱贯,6380的服務(wù)端會(huì)大致打印出以下日志(附上簡(jiǎn)單翻譯或分析):
1822:S 26 Dec 2022 13:13:49.247 * Before turning into a replica, using my own master parameters to synthesize a cached master: I may be able to synchronize with the new master with just a partial transfer.
在轉(zhuǎn)換為副本之前,使用我自己的主參數(shù)來合成緩存的主文件:我可以通過部分傳輸與新的主文件同步侦另。
1822:S 26 Dec 2022 13:13:49.247 * Connecting to MASTER 127.0.0.1:6379
連接到6379端口的主
1822:S 26 Dec 2022 13:13:49.247 * MASTER <-> REPLICA sync started
“從”開始同步
1822:S 26 Dec 2022 13:13:49.247 * REPLICAOF 127.0.0.1:6379 enabled (user request from 'id=3 addr=127.0.0.1:33098 laddr=127.0.0.1:6380 fd=8 name= age=0 idle=0 flags=N db=0 sub=0 psub=0 ssub=0 multi=-1 qbuf=44 qbuf-free=20430 argv-mem=22 multi-mem=0 rbs=16384 rbp=16384 obl=0 oll=0 omem=0 tot-mem=37678 events=r cmd=replicaof user=default redir=-1 resp=2')
通過一系列的參數(shù)可以成功追隨到6379
1822:S 26 Dec 2022 13:13:49.247 * Non blocking connect for SYNC fired the event.
同步非阻塞觸發(fā)事件
1822:S 26 Dec 2022 13:13:49.248 * Master replied to PING, replication can continue...
主請(qǐng)求建立連接秩命,從可以接收到連接
1822:S 26 Dec 2022 13:13:49.248 * Trying a partial resynchronization (request a21aab7153eeee37a33d1447f928f346c2ec21a5:1).
嘗試部分的重新同步
1822:S 26 Dec 2022 13:13:54.670 * Full resync from master: d52a77884eec992567f8fbacc0c005d12c669c39:195
從主全部重新同步
1822:S 26 Dec 2022 13:13:54.670 * MASTER <-> REPLICA sync: receiving streamed RDB from master with EOF to disk
從接收到了主的RDB流,并保存到磁盤上
1822:S 26 Dec 2022 13:13:54.671 * Discarding previously cached master state.
舍棄之前主緩存的狀態(tài)
1822:S 26 Dec 2022 13:13:54.671 * MASTER <-> REPLICA sync: Flushing old data
清除從里舊的數(shù)據(jù)
1822:S 26 Dec 2022 13:13:54.671 * MASTER <-> REPLICA sync: Loading DB in memory
將數(shù)據(jù)加載到內(nèi)存
1822:S 26 Dec 2022 13:13:54.671 * Loading RDB produced by version 7.0.5
加載到內(nèi)存這個(gè)過程用的是7.0.5版本
1822:S 26 Dec 2022 13:13:54.671 * RDB age 0 seconds
1822:S 26 Dec 2022 13:13:54.671 * RDB memory usage when created 0.99 Mb
數(shù)據(jù)內(nèi)存消耗0.99M
1822:S 26 Dec 2022 13:13:54.671 * Done loading RDB, keys loaded: 2, keys expired: 0.
加載結(jié)束褒傅,一共有兩個(gè)鍵弃锐,沒有過期時(shí)間
1822:S 26 Dec 2022 13:13:54.671 * MASTER <-> REPLICA sync: Finished with success
主從同步到此完成
6379的服務(wù)端會(huì)大致打印出以下日志:
1795:M 26 Dec 2022 13:13:49.248 * Replica 127.0.0.1:6380 asks for synchronization
6380端口的從請(qǐng)求同步數(shù)據(jù)
1795:M 26 Dec 2022 13:13:49.248 * Partial resynchronization not accepted: Replication ID mismatch (Replica asked for 'a21aab7153eeee37a33d1447f928f346c2ec21a5', my replication IDs are 'd52a77884eec992567f8fbacc0c005d12c669c39' and '0000000000000000000000000000000000000000')
1795:M 26 Dec 2022 13:13:49.248 * Delay next BGSAVE for diskless SYNC
未使用磁盤方式去作BGSAVE同步(直接使用網(wǎng)絡(luò)傳輸)
1795:M 26 Dec 2022 13:13:54.669 * Starting BGSAVE for SYNC with target: replicas sockets
開始使用BGSAVE命令給從做同步傳輸
1795:M 26 Dec 2022 13:13:54.669 * Background RDB transfer started by pid 1831
重新啟動(dòng)一個(gè)進(jìn)程1831,做非阻塞的RDB傳輸
1831:C 26 Dec 2022 13:13:54.670 * Fork CoW for RDB: current 4 MB, peak 4 MB, average 4 MB
為RDB做Fork系統(tǒng)調(diào)用殿托,使用Cow寫時(shí)復(fù)制機(jī)制霹菊,當(dāng)前文件大小4M,最多4M支竹,平均4M
1795:M 26 Dec 2022 13:13:54.670 # Diskless rdb transfer, done reading from pipe, 1 replicas still up.
無盤模式RDB傳輸浇辜,從管道中讀取完成,目前有一個(gè)從在等待
1795:M 26 Dec 2022 13:13:54.671 * Background RDB transfer terminated with success
非阻塞RDB成功傳輸?shù)綇?1795:M 26 Dec 2022 13:13:54.671 * Streamed RDB transfer with replica 127.0.0.1:6380 succeeded (socket). Waiting for REPLCONF ACK from slave to enable streaming
RDB文件成功通過網(wǎng)絡(luò)傳輸給從唾戚,等待從的最終返回結(jié)果流
1795:M 26 Dec 2022 13:13:54.671 * Synchronization with replica 127.0.0.1:6380 succeeded
最終成功同步(一定是主接收到了從同步成功的最終返回消息)
一句話總結(jié)柳洋。這種方式下,從在追隨成功之后叹坦,主默認(rèn)通過網(wǎng)絡(luò)直接發(fā)送數(shù)據(jù)的模式(當(dāng)然可以在配置文件中進(jìn)行配置)熊镣,把數(shù)據(jù)發(fā)送給從,從把這些數(shù)據(jù)最終形成一個(gè)RDB文件募书,保存到數(shù)據(jù)文件目錄中绪囱。
- 故障的發(fā)生。
假如從機(jī)掛掉以后莹捡,主機(jī)會(huì)第一時(shí)間收到消息鬼吵,日志中打印為:Connection with replica 127.0.0.1:6380 lost
。
在從機(jī)掛掉這段時(shí)間篮赢,如果主機(jī)中有了新數(shù)據(jù)齿椅,從機(jī)恢復(fù)以后,再次與主機(jī)建立主從關(guān)系启泣,從機(jī)仍然是可以同步到這些新數(shù)據(jù)的涣脚。(原理可以從以上日志文件看出,從在同步成功主數(shù)據(jù)后寥茫,在加載到內(nèi)存之前遣蚀,是要把老的數(shù)據(jù)都清除的,把所有的數(shù)據(jù)再重新同步一遍)。
再假設(shè)一種情況芭梯,在主從關(guān)系正常的情況下险耀,如果把6380數(shù)據(jù)目錄下的RDB文件刪除,那么6380還可以獲得這些鍵嗎玖喘?是可以的胰耗。還是根據(jù)日志的記錄可以看出,再主機(jī)向從機(jī)傳輸完數(shù)據(jù)后芒涡,從機(jī)是會(huì)把這些數(shù)據(jù)加載到內(nèi)存的柴灯。所以仍然可以訪問。
那么這時(shí)如果主機(jī)6379新增了內(nèi)容费尽,那么6380從機(jī)可以直接看到嗎赠群?當(dāng)然可以看到,但是暫時(shí)不會(huì)生成RDB文件旱幼,此時(shí)的同步都是發(fā)生在內(nèi)存層面的查描。還沒有到配置文件中save策略所達(dá)到的時(shí)間或操作筆數(shù)。(注意:雖然配置文件中配置的是save柏卤,但是觸發(fā)的是bgsave的操作)冬三。只有達(dá)到策略配置的要求,或者是從機(jī)第一次與主機(jī)建立關(guān)系缘缚,再或者是發(fā)生故障斷開后重新連接勾笆,才會(huì)自動(dòng)進(jìn)行全局的數(shù)據(jù)同步。
發(fā)生故障的不一定只有從機(jī)桥滨,只機(jī)也會(huì)發(fā)生故障窝爪。如果主機(jī)發(fā)生故障了,最常用的方式就是讓一臺(tái)選定的從機(jī)頂替上去齐媒,作為主機(jī)來用蒲每。可以手動(dòng)來操作喻括,但是最常見的是使用程序來監(jiān)控進(jìn)行故障轉(zhuǎn)移邀杏。具體的下次與AOF或者preamble混合模式結(jié)合再進(jìn)行討論分析。