Redis 復(fù)制
Redis
通過持久化技術(shù)(RDB/AOF
)保證即使緩存服務(wù)器重啟數(shù)據(jù)也基本不會丟失挤聘。當(dāng)我們部署一臺單節(jié)點Redis
服務(wù)器時库物,假若磁盤損壞,服務(wù)將會直接不可用政鼠,并且數(shù)據(jù)丟失蚤认,這對應(yīng)用層面來講是絕對不能夠容忍的。為了避免單節(jié)點故障限寞,通常會部署多個副本在不同的服務(wù)器來保證Redis
的高可用性炉媒。Redis
提供了Replication
功能,當(dāng)一臺Master服務(wù)器數(shù)據(jù)更新后昆烁,自動同步到Slave上吊骤。
Master-Slave機(jī)制下,Master負(fù)責(zé)讀寫静尼,Slave一般負(fù)責(zé)讀白粉。默認(rèn)配置Slave是只讀的,如果在Slave上直接進(jìn)行寫操作會報錯誤鼠渺。
(error) READONLY You can't write against a read only slave.
如果希望Slave可以直接進(jìn)行寫操作鸭巴,設(shè)置slave-read-only yes
即可。當(dāng)然建議設(shè)置為no
拦盹。
實踐
創(chuàng)建redis.conf
鹃祖,端口7991為Master
,端口7992為Slave
普舆。
mkdir -p cluster-7991/{config,log,data,pid}
mkdir -p cluster-7992/{config,log,data,pid}
分別為兩個Redis
實例配置文件恬口,將配置文件配置在config
目錄下校读,名為redis.conf
。
port 7991
bind 0.0.0.0
daemonize yes
protected-mode yes
appendonly yes
dir /Users/wujunbin/Work/redis-cluster/cluster-7991/
#repl-diskless-sync yes
port 7992
bind 0.0.0.0
SLAVEOF 127.0.0.1 7991
daemonize yes
protected-mode yes
appendonly yes
dir /Users/wujunbin/Work/redis-cluster/cluster-7992/
#repl-diskless-sync yes
注意在Slave的的配置文件中加入slaveof
用于指定當(dāng)前實力是誰的slave
祖能。
啟動redis-server
redis-server cluster-7991/config/redis.conf &
redis-server cluster-7992/config/redis.conf &
redis-cli
進(jìn)入查看
:~/Work/redis-cluster$redis-cli -p 7991
127.0.0.1:7991> info replication
# Replication
role:master
connected_slaves:1
slave0:ip=127.0.0.1,port=7992,state=online,offset=70,lag=0
master_replid:ee41a261a4aa0c89ffeca4776e23a5598f896c7f
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:70
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:70
connected_salves:1
表明了連接了一個slave節(jié)點歉秫。接下來插入數(shù)據(jù)。
127.0.0.1:7991> set hello world
OK
登錄Slave節(jié)點查看
:~/Work/redis-cluster$redis-cli -p 7992
127.0.0.1:7992> get hello
"world"
127.0.0.1:7992>
成功的取出了數(shù)據(jù)养铸,說明主從配置成功雁芙。
同步原理
首先引用一張圖
主要分為三個階段
-
Slave
發(fā)送sync
命令或者psync
請求初始化。 -
Master
判斷是否增量初始化钞螟。如果不是兔甘,生成dump.rdb
文件,并將該文件傳輸給Slave
鳞滨。如果是洞焙,則將積壓隊列中命令偏移量之后的命令發(fā)送給Slave
。 - 初始化之后
Master
對Slave
進(jìn)行增量更新太援,一旦有更新傳輸寫命令給Slave
節(jié)點闽晦。
Sync和Psync
試想一下Slave
的某個流程:啟動-Master數(shù)據(jù)同步-停止-啟動扳碍。最后一步的啟動提岔,因為Slave
在停止前已經(jīng)接受了Master
的數(shù)據(jù)同步,所以本地是有數(shù)據(jù)的笋敞。所以是不需要將Master
的dump.rdb
全部傳輸給Slave
碱蒙。只需要將Slave
停止之后的所有寫命令在Slave
再次啟動后傳輸給Slave
,即可完成數(shù)據(jù)同步夯巷。Redis
為了完成這一點在Master
維護(hù)了一個命令積壓隊列(默認(rèn)大小1M赛惩,有效時常1個小時)。每一次Master
的寫入命令會放入這個隊列趁餐,并同步寫命令和寫命令在隊列中的偏移量給Slave
喷兼。Slave
除了執(zhí)行寫命令也會記錄這個命令的偏移量。當(dāng)Slave再次啟動時發(fā)送PSYNC + Master Run ID + 命令偏移量
到Master
后雷。Master
收到psync
指令季惯,首先判斷run id
是不是自己,如果是再根據(jù)命令偏移量從隊列中查找臀突。如果找到直接同步偏移量之后的命令給Slave
勉抓。如果偏移量不在隊列中那么無法滿足增量復(fù)制,Master
就會生成dump.rdb
進(jìn)行同步候学。
無硬盤復(fù)制
當(dāng)Redis
使用一主多從的集群架構(gòu)時藕筋,每次和Slave全量同步,Redis
都會執(zhí)行一次快照梳码,同時對硬盤進(jìn)行讀寫隐圾,導(dǎo)致性能下降伍掀。Redis
提供了
repl-diskless-sync yes
參數(shù)。指定后翎承,在復(fù)制初始化時就會直接將生成到dump.rdb
數(shù)據(jù)的內(nèi)容通過網(wǎng)絡(luò)傳輸給Slave
硕盹,而不需要先存儲在磁盤上。
Master崩潰叨咖,Slave切換為Master
當(dāng)Master
崩潰時瘩例,在Slave
中使用SLAVEOF NO ONE
命令將從數(shù)據(jù)庫提升為主數(shù)據(jù)庫繼續(xù)服務(wù)。然后重新啟動崩潰的Reids
實例甸各,該實例就變成了Slave
然后從Master
再次同步數(shù)據(jù)垛贤。