復制
- Redis 采用異步復制。從
Redis 2.8
開始蟆炊,從服務器會周期性
地報告從復制流中處理的數(shù)據(jù)量。 一個主服務器可以擁有多個從服務器。 - 從服務器可以接受其他從服務器的連接霹俺。除了連接多個從服務器到同一個主服務器,從服務器也可以連接到其他的從服務器毒费,形成圖狀結構丙唧。
-
Redis 的復制在主服務器上是非阻塞的。
這意味著觅玻,當一個或多個從服務器執(zhí)行初始化同步(initial synchronization)時想际,主服務器能繼續(xù)處理請求。 Redis 的復制在從服務器上也是非阻塞的溪厘。
- redis.conf 中進行了相應配置胡本,也能夠繼續(xù)使用舊版本的數(shù)據(jù)集處理請求。另外畸悬,你還可以配置當復制流宕(dowm)掉的時候侧甫,從服務器返回給客戶端一個錯誤。然而蹋宦,
初始化同步結束后披粟,舊的數(shù)據(jù)集需要被刪除,新的數(shù)據(jù)集需要被載入冷冗。在這個簡短的窗口期內(nèi)僻爽,從服務器會阻塞到來的連接。
- 復制可以用來支持可伸縮性贾惦,
用多個從服務器處理只讀查詢
(例如胸梆,繁重的 SORT 操作可以分配到從服務器上),也可以僅僅作為數(shù)據(jù)冗余须板。 - 可以使用復制來避免主服務器將全部數(shù)據(jù)集寫到磁盤的開銷:只需要配置你的主服務器的 redis.conf 來防止保存(所有的” 保存” 指令)碰镜,然后連接一個不斷復制的從服務器。但是习瑰,這種設置下要確保主服務器不會自動重啟(閱讀下一節(jié)獲取更多信息)绪颖。
主服務器關閉持久化時的安全性(Safety of replication)
當使用了 Redis 的復制時,強烈建議在主服務器上開啟持久化甜奄,或者柠横,當不可能開啟持久化時,例如由于關注延遲课兄,實例應該被配置為避免自動重啟牍氛。
為了更好的理解為什么關閉了持久化的主服務器被配置為自動重啟是很危險的,查看下面的失敗模型烟阐,數(shù)據(jù)從主服務器以及其所有從服務器上被清除:
- 我們設置節(jié)點 A 作為主服務器搬俊,關閉了持久化紊扬,節(jié)點 B 和節(jié)點 C 從節(jié)點 A 復制。
- A 崩潰了唉擂,但是它擁有某個自動重啟系統(tǒng)餐屎,重啟了這個進程。但是玩祟,由于持久化是被關閉的腹缩,這個節(jié)點以空的數(shù)據(jù)集重啟。
- 節(jié)點 B 和節(jié)點 C 從空的 A 復制空扎,于是它們完全銷毀了他們的數(shù)據(jù)拷貝庆聘。
當 Redis Sentinel 被用于高可用時,主服務器關閉了持久化勺卢,并開啟了進程重啟也是很危險的。例如象对,主務器非澈诔溃快速的重啟,以至于 Sentinel 沒有檢測到失敗勒魔,于是上面描述的失敗模型就發(fā)生了甫煞。
任何時刻數(shù)據(jù)安全都是很重要的,要禁止主服務器配置為關閉持久化并自動重啟冠绢。
Redis 復制如何工作(How works)
- 當你建立一個從服務器抚吠,連接時就會發(fā)送一個 SYNC 命令。不管是第一次連接上還是重連接上弟胀。
- 然后主服務器開始在后臺保存楷力,并且開始緩沖所有新收到的會修改數(shù)據(jù)集的命令。當后臺保存完成以后孵户,主服務器傳輸數(shù)據(jù)庫文件給從服務器萧朝,從服務器將其保存到磁盤上,然后加載到內(nèi)存中夏哭。然后主服務器開始發(fā)送緩沖的命令給從服務器检柬。這是通過命令流完成的,和 Redis 的協(xié)議是一樣的格式竖配。
你可以用 telnet 試試何址。連上一臺正在工作的 Redis 的端口,然后發(fā)送 SYNC 命令进胯。你會看到大量的傳輸用爪,還有主服務器收到的每條命令被重新發(fā)送給了 telnet 會話。
當主從鏈路由于某些原因斷開時胁镐,從服務器可以自動重連项钮。如果主服務器收到多個并發(fā)的從服務器的同步請求,只會執(zhí)行一個后臺保存來服務所有從服務器。
當主服務器和從服務器斷開后重連上烁巫,總是執(zhí)行一次完整重同步(full resynchronization)署隘。然而,從 Redis 2.8 以后亚隙,可以選擇執(zhí)行部分重同步(partial resynchronization)磁餐。
部分重同步(partial resynchronization)
從 Redis 2.8 開始,在復制鏈接斷開后阿弃,主服務器和從服務器通痴锱可以繼續(xù)復制過程,而不需要一次完整的重同步渣淳。
這是通過在主服務器上創(chuàng)建一個復制流的內(nèi)存緩沖區(qū)(in-memory backlog)實現(xiàn)的脾还。主服務器和所有從服務器都記錄一個復制偏移量(offset)和一個主服務器運行 ID(run id),當鏈接斷掉時入愧,從服務器會重連接鄙漏,并且請求主服務器繼續(xù)復制。假設主服務器的運行 ID 還是一樣的棺蛛,并且指定的偏移量在復制緩沖區(qū)中可用怔蚌,復制會從中斷的點繼續(xù)。如果這兩個條件之一不滿足旁赊,將會執(zhí)行完整重同步(2.8 版之前的正常行為)桦踊。
新的部分重同步特性使用的是內(nèi)部 PSYNC命令,老的實現(xiàn)采用的是SYNC 命令终畅。注意籍胯,Redis 2.8 的從服務器可以檢測主服務器是否不支持 PSYNC,然后使用 SYNC 代替离福。
無盤復制(Diskless replication)
通常芒炼,一次完整的重同步需要在磁盤上創(chuàng)建一個 RDB 文件,然后從磁盤重新加載同一個 RDB 來服務從服務器术徊。
由于低速的磁盤本刽,這對主服務器來說是很大壓力的操作。Redis 2.8.18 版本是第一個對無盤復制提供試驗性支持的版本赠涮。在這種設置下子寓,子進程直接通過線路(wire)發(fā)送 RDB 文件給從服務器,而不需要使用磁盤作為中間存儲笋除。
配置(Configuration)
配置復制簡直小菜一碟:只需要添加下面一行到從服務器配置文件:
slaveof 192.168.1.1 6379
當然斜友,你得把 192.168.1.1 6379 替換成你自己的主服務器 IP 地址(或主機名)和端口±或者鲜屏,你可以調(diào)用 SLAVEOF 命令和主服務器主機烹看,開始與從服務器的一次同步。
有很多參數(shù)可以用來調(diào)整執(zhí)行部分重同步主服務器的上的內(nèi)存復制緩沖區(qū)洛史」呤猓可以看看 Redis 發(fā)布版本中自帶的樣例文件 redis.conf 以獲取更多的信息。
只讀從服務器(Read-only slave)
從 Redis 2.6 開始也殖,從服務器支持默認開啟的只讀模式土思。
這個行為由 redis.conf 文件中的 slave-read-only 選項控制,可以在運行時使用 CONFIG SET 來開啟和關閉忆嗜。
只讀從服務器會拒絕所有寫命令己儒,所以寫入數(shù)據(jù)到從服務器只會引起錯誤。這并不意味著捆毫,這個特性打算暴露從服務器實例到互聯(lián)網(wǎng)闪湾,或者到網(wǎng)絡中不信任的客戶端,因為諸如 DEBUG 和 CONFIG 這樣的管理命令等仍可用绩卤。但是途样,可以通過在 redis.conf 中使用 rename-command 指令來禁止命令,從而改進只讀實例的安全性省艳。
你可能很好奇,為什么需要能夠反轉只讀設置嫁审,使得從服務器實例能夠成為寫操作的目標跋炕。盡管這些寫入的數(shù)據(jù)會在從服務器和主服務器重同步時,或者從服務器重啟時被丟棄律适,還是有一些存儲一些短暫的數(shù)據(jù)到可寫的從服務器的合理場景辐烂。例如,客戶端可以存儲一些主服務器的可達性信息來調(diào)整故障轉移(failover)策略捂贿。
認證主服務器(Authenticate to a master)
如果你的主服務器通過 requirepass 而有一個密碼纠修,很容易配置從服務器在所有同步操作中使用這個密碼。
要做到這個厂僧,在一個運行的實例上扣草,使用 redis-cli 并鍵入:
config set masterauth <password>
要永久設置這個,添加這個倒你的配置文件中:
masterauth <password>
N 個副本才能寫(Allow writes only with N attached replicas)
從 Redis 2.8 開始颜屠,可以設置 Redis 主服務器在當前至少擁有 N 個從服務器的連接的情況下辰妙,才能接受寫請求。
然而甫窟,由于 Redis 使用異步復制密浑,不能保證從服務器真正收到了一個給定的寫請求,于是總是有一個數(shù)據(jù)丟失的窗口期粗井。
下面是這個特性是如何運作的:
- Redis 從服務器每秒種 ping 主服務器尔破,上報處理完的復制流的數(shù)據(jù)量街图。
- Redis 主服務器記錄上一次從每一個從服務收到 ping 的時間。
- 用戶可以配置最小從服務器數(shù)量懒构,每臺從服務器擁有一個不大于最大秒數(shù)的滯后(lag)餐济。
如果有至少 N 個小于 M 秒滯后的從服務器,寫請求才會被接受痴脾。
你可能會認為這個像 CAP 理論中較寬松版本的”C”颤介,不能保證指定寫的一致性,但是至少數(shù)據(jù)丟失的時間窗口被限制在一個指定的秒數(shù)內(nèi)赞赖。
如果條件不滿足滚朵,主服務器會返回一個錯誤,并且不會接受寫請求前域。
這個特性有兩個配置參數(shù):
min-slaves-to-write <number of slaves>
min-slaves-max-lag <number of seconds>
請查看隨 Redis 源碼發(fā)布版本自帶的 redis.conf 文件獲取更多信息辕近。