主從同步(主從複製)是 Redis
高可用服務的基石,也是多機執行中最基礎的一個。【相關推薦:Redis視訊教學】
我們把主要儲存資料的節點叫做主節點 (master
),把其他通過複製主節點資料的副本節點叫做從節點 (slave
),如下圖所示:
在 Redis
中一個主節點可以擁有多個從節點,一個從節點也可以是其他伺服器的主節點,如下圖所示:
主從同步的優點
主從同步具有以下三個優點:
Redis
伺服器的宕機恢復節省了寶貴的時間;開啟主從同步
執行中設定從伺服器
在 Redis
執行過程中,我們可以使用 replicaof host port
命令,把自己設定為目標 IP
的從伺服器。
如果主服務設定了密碼,需要在從伺服器輸入主伺服器的密碼,使用 config set masterauth 主服務密碼
命令的方式
在執行完 replicaof
命令之後,從伺服器的資料會被清空,主服務會把它的資料副本同步給從伺服器。
啟動時設定從伺服器
可以使用命令 redis-server --port 6380 --replicaof 127.0.0.1 6379
將自己設定成目標伺服器的從伺服器。
資料同步
完整資料同步
當有新的從伺服器連線時,為了保障多個資料庫的一致性,主伺服器會執行一次 bgsave
命令生成一個 RDB
檔案,然後再以 Socket
的方式傳送給從伺服器,從伺服器收到 RDB
檔案之後再把所有的資料載入到自己的程式中,就完成了一次全量的資料同步。
部分資料同步
在 Redis 2.8
之前每次從伺服器離線再重新上線之前,主伺服器會進行一次完整的資料同步,然後這種情況如果發生在離線時間比較短的情況下,只有少量的資料不同步卻要同步所有的資料是非常笨拙和不划算的,在 Redis 2.8
這個功能得到了優化。
Redis 2.8
的優化方法是當從服務離線之後,主伺服器會把離線之後的寫入命令,儲存在一個特定大小的佇列中,佇列是可以保證先進先出的執行順序的,當從伺服器重寫恢復上線之後,主服務會判斷離線這段時間內的命令是否還在佇列中,如果在就直接把佇列中的資料傳送給從伺服器,這樣就避免了完整同步的資源浪費。
儲存離線命令的佇列大小預設是 1MB,使用者可以自行修改佇列大小的設定項 repl-backlog-size
。
無盤資料同步
在第一次主從連線的時候,會先產生一個 RDB
檔案,再把 RDB
檔案傳送給從伺服器,如果主伺服器是非固態硬碟的時候,系統的 I/O
操作是非常高的。
Redis 2.8.18
新增了無盤複製功能,無盤複製功能不會在本地建立 RDB
檔案,而是會派生出一個子程序,然後由子程序通過 Socket
的方式,直接將 RDB
檔案寫入到從伺服器,這樣主伺服器就可以在不建立 RDB
檔案的情況下,完成與從伺服器的資料同步。
要使用無須複製功能,只需把設定項 repl-diskless-sync
的值設定為 yes
即可,它預設設定值為 no
。
查詢伺服器的角色
使用 role
命令,來查詢當前伺服器的主從角色資訊。
關閉主從同步
可以使用 replicaof no one
命令來停止從伺服器的複製。
執行了 replicaof no one
命令之後,自己就從伺服器變成主伺服器了。
伺服器型別的轉換並不會影響資料,這臺伺服器的資料將會被保留。
注意事項
資料一致性問題
當從伺服器已經完成和主服務的資料同步之後,再新增的命令會以非同步的方式傳送至從伺服器,在這個過程中主從同步會有短暫的資料不一致,如在這個非同步同步發生之前主伺服器宕機了,會造成資料不一致。
從伺服器唯讀性
預設情況下,處於複製模式的主伺服器既可以執行寫操作也可以執行讀操作,而從伺服器則只能執行讀操作。
可以在從伺服器上執行 config set replica-read-only no
命令,使從伺服器開啟寫模式,但需要注意以下幾點:
複製命令的變化
Redis 5.0
之前使用的複製命令是 slaveof
,在 Redis 5.0
之後複製命令才被改為 replicaof
,在高版本(Redis 5+
)中我們應該儘量使用 replicaof
,因為 slaveof
命令可能會被隨時廢棄掉。
主從複製模式,它是屬於
Redis
多機執行的基礎,但這種模式本身存在一個致命的問題,當主節點奔潰之後,需要人工干預才能恢復Redis
的正常使用。我們需要一個自動的工具——
Redis Sentinel
(哨兵模式)來把手動的過程變成自動的,讓Redis
擁有自動容災恢復(failover
)的能力。哨兵就相當於對主從伺服器做一個監視的任務。一旦發現主伺服器宕機了,就迅速啟動相應的規則將某一臺從伺服器升級為主伺服器,無需人工干預,更穩定更快。
Redis Sentinel
的最小分配單位是一主一從。
Redis Sentinel 搭建
使用命令 ./src/redis-sentinel sentinel.conf
來啟動 Sentinel
,在啟動它時必須設定一個 sentinel.conf
檔案,這個組態檔中必須包含監聽的主節點資訊:
sentinel monitor master-name ip port quorum
其中:
master-name
表示給監視的主節點起一個名稱;ip
表示主節點的 IP;port
表示主節點的埠;quorum
表示確認主節點下線的 Sentinel
數量,如果 quorum
設定為 1 表示只要有一臺 Sentinel
判斷它下線了,就可以確認它真的下線了。如果主節點伺服器 Redis
有密碼,sentinel.conf
必須包含以下內容:
sentinel monitor mymaster 127.0.0.1 6379 1 sentinel auth-pass mymaster pwd654321
啟動 Sentinel 叢集
生產環境我們不會只啟動一臺 Sentinel
,因為如果啟動一臺 Sentinel
假如它不幸宕機的話,就不能提供自動容災的服務了,不符合我們高可用的宗旨,所以我們會在不同的物理機上啟動多個 Sentinel
來組成 Sentinel
叢集,來保證 Redis
服務的高可用。
啟動 Sentinel
叢集的方法很簡單,和上面啟動單臺的方式一樣,我們只需要把多個 Sentinel
監聽到一個主伺服器節點,那麼多個 Sentinel
就會自動發現彼此,並組成一個 Sentinel
叢集。
一般情況下 Sentinel
叢集的數量取大於 1 的奇數,quorum
的引數就設定為一半加 1,例如 5 就設定為 3,7 就設定為 4。
兩個概念:主觀下線和客觀下線。
當 Sentinel
叢集中,有一個 Sentinel
認為主伺服器已經下線時,它會將這個主伺服器標記為主觀下線(Subjectively Down
,SDOWN
),然後詢問叢集中的其他 Sentinel
,是否也認為該伺服器已下線,當同意主伺服器已下線的 Sentinel
數量達到 quorum
引數所指定的數量時,Sentinel
就會將相應的主伺服器標記為客觀下線(Objectively down,ODOWN
),然後開始對其進行故障轉移。
主服務競選規則
新主節點競選優先順序設定
redis.conf
中的 replica-priority
選項來設定競選新主節點的優先順序,它的預設值是 100,它的最大值也是 100,這個值越小它的權重就越高。
新主節點競選規則
新主節點的競選會排除不符合條件的從節點,然後再剩餘的從節點按照優先順序來挑選。
存在以下條件的從節點會被排除:
排除所有已經下線以及長時間沒有回覆心跳檢測的疑似已下線從伺服器;
排除所有長時間沒有與主伺服器通訊,資料狀態過時的從伺服器;
排除所有優先順序(replica-priority
)為 0 的伺服器。
符合條件的從節點競選順序:
優先順序最高的從節點將會作為新主節點;
優先順序相等則判斷複製偏移量,偏移量最大的從節點獲勝;
如果以上兩個條件都相同,選擇 Redis
執行時隨機生成 ID 最小那個為新的主伺服器。
舊主節點恢復上線
如果之前的舊主節點恢復上線,會作為從節點執行在主從伺服器模式中。
哨兵工作原理
首先每個 Sentinel
會以每秒鐘 1 次的頻率,向已知的主伺服器、從伺服器和以及其他 Sentinel
範例,傳送一個 PING 命令。
如果最後一次有效回覆 PING
命令的時間超過 down-after-milliseconds
所設定的值(預設 30s),那麼這個範例會被 Sentinel
標記為主觀下線。
如果一個主伺服器被標記為主觀下線,那麼正在監視這個主伺服器的所有 Sentinel
節點,要以每秒 1 次的頻率確認主伺服器的確進入了主觀下線狀態。
如果有足夠數量(quorum
設定值)的 Sentinel
在指定的時間範圍內同意這一判斷,那麼這個主伺服器被標記為客觀下線。此時所有的 Sentinel
會按照規則協商自動選出新的主節點。
注意:一個有效的 PING
回覆可以是:+PONG、-LOADING
或者 -MASTERDOWN
。如果返回值非以上三種回覆,或者在指定時間內沒有回覆 PING
命令, 那麼 Sentinel
認為伺服器返回的回覆無效(non-valid
)。
Sentinel 命令操作
Sentinel 可以監視多臺主節點,而不是隻能監視一臺伺服器。想要監視多臺主節點只需要在組態檔中設定多個 sentinel monitor master-name ip port quorum
即可,我們通過 master-name
來區分不同的主節點。
查詢所有被監控的主伺服器資訊
sentinel masters
查詢某個主節點的資訊
sentinel master master-name
檢視某個主節點的 IP 和埠
sentinel get-master-addr-by-name master-name
查詢從節點的資訊
sentinel replicas mymaster
或 sentinel slaves master-name
查詢 Sentinel 叢集中的其他 Sentinel 資訊
sentinel sentinels master-name
檢查可用 Sentinel 的數量
sentinel ckquorum master-name
強制故障轉移
sentinel failover master-name
線上修改設定資訊
在 Redis 2.8.4
之前如果需要修改 Sentinel
的組態檔,需要重新啟動 Sentinel
。
Redis 2.8.4
之後,我們可以線上修改組態檔了。
增加監視主節點
sentinel monitor mymaster IP Port Quorum
命令。
移除主節點的監視
使用 sentinel remove master-name
命令。
修改 quorum 引數
使用 sentinel set master-name quorum n
命令。
quorum
引數用來表示確認主節點下線的 Sentinel
數量,如果 quorum
設定為 1 表示只要有一臺 Sentinel 確認主觀下線後,這個主節點就客觀(真正地)下線了。
以上所有對組態檔的修改,都會自動被重新整理到物理組態檔
sentinel.conf
中
程式碼實戰
import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisSentinelPool; import utils.Config; import java.util.HashSet; import java.util.Set; public class SentinelExample { // master name private static String _MASTER_NAME = "mymaster"; public static void main(String[] args) { // Sentinel 設定資訊 Set<String> set = new HashSet<>(); // 連線資訊 ip:port set.add("127.0.0.1:26379"); // 建立 Sentinel 連線池 JedisSentinelPool jedisSentinel = new JedisSentinelPool(_MASTER_NAME, set, Config.REDIS_AUTH); // 獲取 Redis 使用者端 Jedis jedis = jedisSentinel.getResource(); // 設定元素 String setRes = jedis.set("key", "Hello, redis."); System.out.println(setRes); // 獲取元素 System.out.println(jedis.get("key")); } }
更多程式設計相關知識,請存取:!!
以上就是聊聊Redis中的主從同步和哨兵模式的詳細內容,更多請關注TW511.COM其它相關文章!