Redis主備複製

weixin_33896726發表於2015-11-19

     Redis 支援 Master-Slave(主從)模式,Redis Server 可以設定為另一個 Redis Server 的主機(從機),從機定期從主機拿資料。特殊的,一個從機同樣可以設定為一個 Redis Server 的主機,這樣一來 Master-Slave 的分佈看起來就是一個有向無環圖,形成 Redis Server 叢集,無論是主機還是從機都是 Redis Server,都可以提供服務。

 

     在配置後,主機Master可負責讀寫服務從機Slave只負責讀。Redis 提高這種配置方式,為的是讓其支援資料的弱一致性,即最終一致性。redis 複製在 master 這一端是非阻塞的,也就是說在和 slave 同步資料的時候,master 仍然可以執行客戶端的操作命令而不受其影響。

二、redis主從複製特點

1、同一個Master可以擁有多個Slaves。

2、Master下的Slave還可以接受同一架構中其它slave的連結與同步請求,實現資料的級聯複製,即Master->Slave->Slave模式;

3、Master以非阻塞的方式同步資料至slave,這將意味著Master會繼續處理一個或多個slave的讀寫請求;

4、Slave端同步資料也可以修改為非阻塞是的方式,當slave在執行新的同步時,它仍可以用舊的資料資訊來提供查詢;否則,當slave與master失去聯絡時,slave會返回一個錯誤給客戶端;

5、主從複製具有可擴充套件性,即多個slave專門提供只讀查詢與資料的冗餘,Master端專門提供寫操作;

6、通過配置禁用Master資料持久化機制,將其資料持久化操作交給Slaves完成,避免在Master中要有獨立的程式來完成此操作。

三、redis主從複製原理

 

1、當啟動一個Slave程式後,它會向Master傳送一個SYNC Command,請求同步連線。無論是第一次連線還是重新連線,Master都會啟動一個後臺程式,將資料快照儲存到資料檔案中,同時Master會記錄所有修改資料的命令並快取在資料檔案中;

2、後臺程式完成快取操作後,Master就傳送資料檔案(dump.rdb)給Slave,Slave端將資料檔案儲存到硬碟上,然後將其在載入到記憶體中,接著Master就會所有修改資料的操作,將其傳送給Slave端。

3、若Slave出現故障導致當機,恢復正常後會自動重新連線,Master收到Slave的連線後,將其完整的資料檔案傳送給Slave,如果Mater同時收到多個Slave發來的同步請求,Master只會在後臺啟動一個程式儲存資料檔案,然後將其傳送給所有的Slave,確保Slave正常。

Redis複製工作原理:

1. 如果設定了一個Slave,無論是第一次連線還是重連到Master,它都會發出一個SYNC命令;

2. 當Master收到SYNC命令之後,會做兩件事:

    a) Master執行BGSAVE,即在後臺儲存資料到磁碟(rdb快照檔案);

    b) Master同時將新收到的寫入和修改資料集的命令存入緩衝區(非查詢類);

3. 當Master在後臺把資料儲存到快照檔案完成之後,Master會把這個快照檔案傳送給Slave,而Slave則把記憶體清空後,載入該檔案到記憶體中;

4. 而Master也會把此前收集到緩衝區中的命令,通過Reids命令協議形式轉發給Slave,Slave執行這些命令,實現和Master的同步;

5. Master/Slave此後會不斷通過非同步方式進行命令的同步,達到最終資料的同步一致;

6. 需要注意的是Master和Slave之間一旦發生重連都會引發全量同步操作。但在2.8之後版本,也可能是部分同步操作。

部分複製 2.8開始,當Master和Slave之間的連線斷開之後,他們之間可以採用持續複製處理方式代替採用全量同步。 Master端為複製流維護一個記憶體緩衝區(in-memory backlog),記錄最近傳送的複製流命令;同時,Master和Slave之間都維護一個複製偏移量(replication offset)和當前Master伺服器ID(Master run id)。當網路斷開,Slave嘗試重連時: a. 如果MasterID相同(即仍是斷網前的Master伺服器),並且從斷開時到當前時刻的歷史命令依然在Master的記憶體緩衝區中存在,則Master會將缺失的這段時間的所有命令傳送給Slave執行,然後複製工作就可以繼續執行了; b. 否則,依然需要全量複製操作;

rdb複製弊端請參見:http://my.oschina.net/hanruikai/blog/308007?fromerr=VJsCzCcq           

四、redis主從配置

    實現主從複製僅需要修改Slave對應的redis.conf檔案中的如下引數,Master中的此引數不需要修改:

slaveof <master ip> <port>  

slaveof 192.168.126.137   6379

IP和埠為Master的IP和埠

     replication在redis.conf的配置選項:

     #slaveof [masterip] [masterport]  設定master的ip和port #masterauth [master-password]     如果master需要auth,在此設定password
     #slave-serve-stale-data yes       如果slave與master的連線斷開,該選項決定slave是否繼續提供服務
     #slave-read-only yes              slave是否是隻讀的 #repl-ping-slave-period 10        master端ping slave端的時間間隔,時刻檢測slave連線的有效
     #repl-timeout 60                  replication連線的超時時間
     #slave-priority 100               slave的權重,用於redis sentinel模式中,如果master down,權重大的slave接替master

    replication是redis提供的複製功能,用於master提供給slave的資料同步。 slave在連線master後,master端會在後臺啟動一個程式進行rdb檔案的建立,當檔案建立完成後,傳送給slave端,slave端收到後,會通過rdb檔案完成對master的複製。

具體示例如下:

先開啟三個終端,然後起三個例項,分別用三個 client 去連線它們:

A:src $ ./redis-server --port 10000 --daemonize yes

A:src $ ./redis-cli -p 10000

埠10000的做 master。

slave 01:

A:src $ ./redis-server --port 10001 --daemonize yes

A:src $ ./redis-cli -p 10001

slave 02:

A:src $ ./redis-server --port 10002 --daemonize yes

A:src $ ./redis-cli -p 10002

上面只是讓它們的例項啟動了並用客戶端去連線它,並沒有設定主從關係。在 slave 01 和 slave 02 上執行下面的命令:

127.0.0.1:10001> slaveof 127.0.0.1 10000

OK

127.0.0.1:10001> 

這樣就設定好了主從關係。我們來試試有沒有效果。

127.0.0.1:10001> get testkey001

(nil)

127.0.0.1:10001> 

這個時候是沒有值的。

master 上執行:

127.0.0.1:10000> set testkey001 testvalue001

OK

127.0.0.1:10000> 

然後看看 slave 上有沒有:

127.0.0.1:10001> get testkey001

"testvalue001"

127.0.0.1:10001> 

127.0.0.1:10002> get testkey001

"testvalue001"

127.0.0.1:10002> 

當你設定了主從關係後,slave 在第一次連線或者重新連線 master 時,slave 都會傳送一條同步指令給 master ;

master 接到指令後,開始啟動後臺儲存程式儲存資料,接著收集所有的資料修改指令。後臺儲存完了,master 就把這份資料傳送給 slave,slave 先把資料儲存到磁碟,然後把它載入到記憶體中,master 接著就把收集的資料修改指令一行一行的發給 slave,slave 接收到之後重新執行該指令,這樣就實現了資料同步。

slave 在與 master 失去聯絡後,自動的重新連線。如果 master 收到了多個 slave 的同步請求,它會執行單個後臺儲存來為所有的 slave 服務。

相關文章