對于高負載應用來說,復制(replication)是不可或缺的一個特性,復制可以讓其他服務器擁有一個不斷地更新的數(shù)據(jù)副本,從而使得擁有副本數(shù)據(jù)的服務器可以用于處理客戶端發(fā)送的讀請求。關系型數(shù)據(jù)庫通常會使用一個主服務器(master)向多個從服務器(slave)發(fā)送更行,并使用從服務器來處理所有讀請求。Redis也采用了同樣的方法來實現(xiàn)自己的復制特性,并將其用作擴展性能的一種手段。
復制相關配置選項
之前說過,當從服務器連接主服務器時,主服務器會執(zhí)行BGSAVE操作,因此要求主服務器的快照持久化功能正常。配置slaveof host port選項即可連接主服務器。下面來測試下:
再安裝一個Redis,直接拷貝之前的安裝好的文件夾即可,本人安裝的兩個Redis路徑為/opt/redis-3.2.4、/opt/redis-replication
123cd /optsudo cp -r redis-3.2.4 redis-replicationsudo chmod -R 777 redis-replication修改redis-replication的redis.conf文件,改兩個配置port和slaveof
12port 6380slaveof localhost 6379啟動redis-3.2.4
12345678cd /opt/redis-3.2.4./src/redis-server ./redis.conf//啟動交互式命令行并添加兩個key./src/redis-cli127.0.0.1:6379> set key1 helloOK127.0.0.1:6379> set key2 worldOK啟動redis-replication
12345678cd /opt/redis-replication./src/redis-server ./redis.conf//啟動交互式命令行./src/redis-cli -h localhost -p 6380//查看數(shù)據(jù),6380端口的Redis服務上也有key1和key2了localhost:6380> keys *1) "key2"2) "key1"測試數(shù)據(jù)更新推送
12345678//主服務添加key3127.0.0.1:6379> set key3 !OK//從服務收到數(shù)據(jù)更新localhost:6380> keys *1) "key3"2) "key2"3) "key1"
對于一個正在運行的Redis服務器,可以發(fā)送SLAVEOF no one命令來讓服務器終止復制操作,不再接受主服務器的數(shù)據(jù)更新;也可以通過發(fā)送SLAVEOF host port命令來讓服務器開始復制一個新的主服務器,這個就不測試了,了解下有這個功能。
Redis復制的啟動過程
從服務器連接主服務器時,主服務器會創(chuàng)建一個快照文件并將其發(fā)送至從服務器,但這只是主從復制執(zhí)行過程的其中一步,下面列舉出復制過程中Redis所有的行為:
步驟 | 主服務器操作 | 從服務器操作 |
---|---|---|
1 | 等待命令進入 | 連接(或者重連接)主服務器,發(fā)送SYNC命令 |
2 | 開始執(zhí)行BGSAVE,并使用緩沖區(qū)記錄BGSAVE之后執(zhí)行的所有寫命令 | 根據(jù)配置選項來決定時繼續(xù)使用現(xiàn)在的數(shù)據(jù)來處理客戶端命令,還是向發(fā)送請求的客戶端返回錯誤 |
3 | BGSAVE執(zhí)行完畢,向從服務器發(fā)送快照文件,并在發(fā)送期間繼續(xù)使用緩沖區(qū)記錄杯知行的寫命令 | 丟棄所有舊的數(shù)據(jù),開始載入主服務器發(fā)來的快照文件 |
4 | 快照文件發(fā)送完畢,開始向從服務器發(fā)送存儲在緩沖區(qū)里面的寫命令 | 完成對快照文件的解釋操作,像往常一樣開始接受命令請求 |
5 | 緩沖區(qū)存儲的寫命令發(fā)送完畢;從現(xiàn)在開始,沒執(zhí)行一個寫命令,就像從服務器發(fā)送相同的寫命令 | 執(zhí)行主服務器發(fā)來的所有存儲在緩沖區(qū)里面的寫命令;從現(xiàn)在開始,接收并執(zhí)行主服務器傳來的每個寫命令 |
由上述步驟可以看出,有必要給Redis主服務器留30%~45%的內存用于執(zhí)行BGSAVE命令和創(chuàng)建記錄寫命令的緩沖區(qū)。另外,從服務器還有一點需要注意的是,從服務器在進行同步時,會清空自己的所有數(shù)據(jù),因為第3步中,從服務器會丟棄所有舊數(shù)據(jù)。
注:Redis不支持主主復制(master-master replication)lian
當多個從服務器嘗試連接同一個主服務器的時候,就會出現(xiàn)下表所示的兩種情況中的其中一種:
當有新的從服務器連接主服務器時 | 主服務器的操作 |
---|---|
上述步驟3尚未執(zhí)行 | 所有從服務器都會接收相同的快照文件和相同的緩沖區(qū)寫命令 |
上述步驟3正在執(zhí)行或者已經(jīng)執(zhí)行 | 當主服務器與較早進行連接的從服務器執(zhí)行完復制所需的5個步驟之后,主服務器會與新連接的從服務器執(zhí)行一次新的步驟1至步驟5 |
由此可以看出多個從服務器的同步對網(wǎng)絡的開銷挺大的,有可能會影響到主服務器接收寫命令,甚至是與主服務器位于同一網(wǎng)絡中的其他硬件。
主從鏈
上面講到創(chuàng)建多個從服務器可能造成網(wǎng)絡不可用,此時可以使用另外一個解決方案,從服務器擁有自己的從服務器,并由此形成主從鏈(master/slave chaining)。當讀請求的重要性明顯高于寫請求的重要性,并且讀請求的數(shù)量需求遠遠超出一臺Redis服務器可以處理的范圍時,用戶就需要添加新的從服務器來處理讀請求,隨著負載不斷上升,主服務器可能會無法快速地更新所有從服務器。為了緩解這個問題,可以創(chuàng)建一個由Redis主/從節(jié)點(master/slave node)組成的中間層來分擔主服務器的復制工作,如下圖所示:
按照上圖的樹狀結構,只有3臺從服務器和主服務器通信,其他都向從服務器同步數(shù)據(jù),分散了網(wǎng)絡開銷。如果12臺從服務器都向主服務器同步數(shù)據(jù)的話,想想也覺得有點牽強了。