4.主從複製的原理git
總所周知 Redis 之因此火由於它有着讀取速度快、可持久化的優勢。Redis 的持久化保證了斷電或重啓數據不會丟失。但僅僅這樣是不夠的,持久化是將數據按期寫入磁盤中,萬一哪一天這一臺服務器掛掉了,那全部數據依舊會丟失。爲了解決這個單點故障問題,因此就有了主從複製。redis
主從複製就是將一臺 Redis 服務器的數據自動地複製到其餘 Redis 服務器上。一臺服務器出故障的機率很高,可是多臺服務器同時出故障的機率就很低了吧。所謂主從主從,固然是有主服務器(Master)和從服務器(Slave),一個 Master 能夠將數據複製到多個 Slave,可是特別注意的是,複製是單向的,只能從 Master 到 Slave。一個 Master 能夠有多個 Slave,一個 Slave 也能夠有多個 Slave,可是一個 Slave 只能從屬一個 Master。以下圖這樣就是錯誤的。api
既然主從複製有這些做用,那在實際應用中會用在哪些場景呢?緩存
這種模式在實際應用中仍是比較少見的其實,一主一從主要是實現讀寫分離和容災恢復。考慮到成本的問題,因此採用兩臺服務器,一個 Redis 服務器 Master 負責讀操做,並按期的複製到另個一服務器 Slave。Slave 服務器負責讀寫操做。在項目中配置的時候配置兩個 Redis 鏈接。安全
一主多從有能夠分爲幾種,以下圖:bash
這種就是全部的 Slave 都從 Master 中進行復制,這樣的好處是 配置簡單,全部的 Slave 都只用關係 Master 就行了,可是要考慮到其實複製也是會侵佔 CPU 內存的,全部的 Slave 都從 Master 複製,可能增大 Master 的負荷。服務器
再來看看下圖:微信
這種模式也是一主多從,可是和上面的全部的 Slave 都從 Master 複製不同。它是使一個到兩個 Slave 從 Master 直接複製,其餘的 Slave 從這兩個 Slave 中複製。存在層級關係。這樣的好處的下降的 Master 服務器的負荷,可是這樣會致使若是中間某個 Slave 掛掉了,那依附於它的全部 Slave 都不能用了。架構
上面以及搭建了一個主從複製的樣例,是一主兩從的,那是怎麼 Redis 是怎麼具體實現的呢?併發
在將原理以前,先來看看主從複製的幾個概念。啓動 Master 後:
127.0.0.1:6379> info server
# Server
redis_version:4.0.9
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:514e9a11b2a67dfc
redis_mode:standalone
os:Linux 5.0.0-23-generic x86_64
arch_bits:64
multiplexing_api:epoll
atomicvar_api:atomic-builtin
gcc_version:7.4.0
process_id:19688
run_id:136de716105e54294144003a881ba29cdfbccfb2
tcp_port:6379
uptime_in_seconds:4515
uptime_in_days:0
hz:10
lru_clock:5556386
executable:/usr/local/redis/etc/redis-server
config_file:/usr/local/redis/etc/redis.conf複製代碼
這個 run_id 就是 Redis 服務的惟一標識,重啓 Redis 服務號,這個 run_id 會改變,多個 Redis 客戶端鏈接到同一個服務端,其 run_id 是同樣的,也就是說 run_id 指的是服務端的 id:
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=192.168.252.53,port=6389,state=online,offset=5541,lag=1
slave1:ip=192.168.252.53,port=6399,state=online,offset=5541,lag=0
master_replid:f0c89aa8040dfe869de82ee623a1212240456d76
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:5541
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:5541複製代碼
其中 repl_backlog_size 複製緩存區大小,默認大小爲 1M,若是 mater_repl_offset 在這個範圍內,就看是部分複製,不然就開始全量複製。
先看下圖,圖畫的不是很好見諒。
既然是部分複製,那就是 Slave 已經知道了 Master 的 run_id 和 offset,因此發送 psync 命令帶上這兩個參數,Master 就知道這是部分複製,而後經過偏移量將須要複製的數據發送給 Slave。
主從複製的過程當中既用到了全量複製也用到了部分複製,兩者是相互配合使用的。看下面的流程圖:
還有一點須要注意的是,若是 Master 重啓了,那麼它的 run_id 發生了改變,那麼依賴它的 Slave 都會進行一次全量複製後在進行部分複製。
以爲不錯能夠點個贊支持一下!
更多技術文章請關注微信公衆號:以Java架構贏天下