Redis主從數(shù)據(jù)同步

Redis作為一個分布式的存儲服務(wù),集群的工作模式幾乎是標配,Redis目前的主從模式也是大多人使用的模型,那Redis的主機和從機是如何保證數(shù)據(jù)同步一致的呢?

RDB 與 AOF 文件

Redis本身,數(shù)據(jù)的持久化有兩種形式,一種是AOF,另一種就是RDB文件的格式,作為主從同步的模型,Redis采用的就是RDB的文件格式。這里簡單介紹一下RDB 和 AOF。

AOF

這種存儲模式非常高效,他所存儲的是Redis本身執(zhí)行的所有寫命令,比如說set key value, 所有的寫相關(guān)的命令,都會被加載到AOF里面。

但是有兩點點要注意一下:

  1. 寫入文件的過程不是實時的,畢竟寫入文件是有性能消耗的,所以會有一個AOF緩沖區(qū)來存儲最近的操作,然后定時寫入文件。
  2. 對于一些命令,比如說反復(fù)對list的操作,結(jié)果集會越來越大,極端的例子是我們for循環(huán)一組數(shù)據(jù),逐一添加到list里面,對于AOF來說,就是幾千條命令,所以AOF會有一個重寫的過程,具體的內(nèi)容在這里不介紹了,可以參閱官網(wǎng)和相關(guān)書籍。

RDB

相較于AOF的快照行為,RDB是對于內(nèi)存中的數(shù)據(jù),直接進行一次壓縮和文件寫入的過程,這種形式還原數(shù)據(jù)對于Redis來說,比AOF要快很多,但是對于生成來講,可能性能就不盡如人意了,他是將數(shù)據(jù),按照對應(yīng)的類型(string,list,set,map,zset)按照特定的格式,存入文件里面,添加一些版本號和唯一標示,來識別RDB文件。

生成的命令有兩種,一個是SAVE,一個是BGSAVE, 區(qū)別就是前者是整個Redis不工作來生成數(shù)據(jù),后者是開啟另一個線程來處理,不影響Redis的正常工作。但同樣的是RDB文件生成的時候,性能低下,注定他不能實時存儲,通常情況下都是設(shè)置一些條件觸發(fā)生成操作。這里篇幅有限,以后有機會再慢慢介紹。

兩者對比

  1. 首先第一點,AOF存儲的是操作,而RDB存儲的是實際的數(shù)據(jù)庫內(nèi)容,所以注定的是存儲上,AOF肯定更加便捷,RDB更加耗費性能。但相反的是,對于大量數(shù)據(jù),RDB還原的速度就快很多了,而AOF由于包含了大量的命令,需要逐一執(zhí)行,整個過程對于Redis而言,肯定不如RDB來得好。

  2. 數(shù)據(jù)丟失的問題上,RDB由于不是實時的,所以注定的在宕機的時候,會有一段時間空隙,數(shù)據(jù)會產(chǎn)生丟失的情況,而AOF采用的是緩沖區(qū)的形式,后臺線程進行AOF重寫,所以緩沖區(qū)也有可能因為宕機而存在丟失的問題,但是對比于RDB,肯定丟失的情況更加少。

主從同步的基本原理

聊了文件存儲之后,回到主題上面,Redis的主從模式采用的是RDB文件同步的方式,因為Redis的服務(wù)端,數(shù)據(jù)量有可能非常的大,所以從性能考慮,沒有采用AOF快照來同步。

過程大概如下:

  1. 從機上線,主動鏈接主機,發(fā)送SYNC命令
  2. 主機接到命令后,執(zhí)行BGSAVE命令,生成RDB文件
  3. 主機向從機發(fā)送RDB文件,開始同步數(shù)據(jù)
  4. 同步之后,主機將最近的更新,采用命令的形式同步到從機上面。

舊版復(fù)制的缺陷

上述的過程對于一個從機,新加入到集群里面的時候,比較合適,但是如果因為斷線重連,則需要重新復(fù)制主機上所有的內(nèi)容,主機也因此要進行一次全量級的RDB,比較耗費性能。

在2.8版本之后,采用了一個新的增量復(fù)制的過程,流程如下:

  1. 前面的sync的過程還是一樣,沒有差異
  2. 當從機斷線重連之后,會發(fā)送PSYNC,要求增量同步,并包括一個offset
  3. 主機根據(jù)offset的位置,對之后的數(shù)據(jù)進行一次增量同步,到從機上面

這里面的offset是由主機和從機共同維護的,相當于一個樂觀鎖,描述了兩方的版本差異。

那決定能否增量同步的主要因素,包括如下三個:

  1. 是否具備偏移量,與主機進行對比
  2. 主服務(wù)器的復(fù)制積壓緩沖區(qū)(Replication backlog)
  3. 從服務(wù)器的ID

第一條不難理解,重點解釋一下第二和第三條

復(fù)制積壓緩沖區(qū)

Redis每分鐘都會處理很多的數(shù)據(jù),不可能一直把更新的操作存起來,等待從機上線在傳輸,AOF也不是都在內(nèi)存中一直保存,所以Redis有一個緩沖區(qū),采用隊列的模式來存儲這些寫操作。

所有的更新操作以隊列的形式放入里面,內(nèi)存大小默認是1MB,超過1MB之后,前面進入隊列的寫操作就會被移除。

所以當從機上線之后,如果offset與主機版本差距的內(nèi)容還在緩沖區(qū)內(nèi),則可以從緩沖區(qū)進行增量同步。否則依然還是全量同步(RDB),這里就好比你的機器宕機了一天,在上線,你不能要求我把這一天的數(shù)據(jù)都給你吧,你直接全量同步得了。

這里我就想到了一個問題,如果我們反復(fù)對Redis更新特別大的K-V的話,超過1M,會使得這個緩沖區(qū)失效,因為每次的更新都超過這個緩沖區(qū)大小了,所以同步操作對于從機來說,都是全量同步,如果太頻繁的話,則會產(chǎn)生很大的問題。

當然這個緩沖區(qū)的大小也是可以設(shè)置調(diào)整的餓,可以根據(jù)需求配置。

從服務(wù)器ID

這個不難理解,因為Redis有一個Slot的概念,每個機器負責一部分的Key,所以如果你之前不是我的從機,那你內(nèi)存內(nèi)的數(shù)據(jù)肯定都不是我的值,就不能只看offset了,還要看一下你之前是不是我的從機,這里主機會維護從機的唯一ID,來校驗。

整個復(fù)制流程

1. 設(shè)置端口號進行連接

SLAVEOF master_ip master_port 命令,或者通過配置文件配置均可。

2. 建立套接字連接

建立連接之后,從服務(wù)器會負責處理后續(xù)的RDB文件和寫命令,主服務(wù)器將從服務(wù)器作為一個客戶端進行響應(yīng)

3. 發(fā)送PING請求

連接之后,通過PING請求檢查相互的狀態(tài),類似心跳校測的內(nèi)容。

4. 身份驗證

這里需要主服務(wù)器和從服務(wù)器都設(shè)置校驗選項,然后校驗密碼。

  • 如果兩方都沒有設(shè)置,則這一步可以忽略
  • 如果從服務(wù)器設(shè)置了,主服務(wù)沒有設(shè)置,則會返回 no password is set
  • 如果都設(shè)置了,則會進行驗證
  • 如果主服務(wù)器設(shè)置了,但是從服務(wù)器沒有設(shè)置,則會返回NOAUTH

5. 發(fā)送端口

由于從服務(wù)類似于客戶端,等待接受信息,所以需要告知主服務(wù)器自己接受所用的端口號,方便未來接受RDB和寫命令。

6. 同步

這個時候就進入到我們上面描述的同步機制里面了,SYNC or PSYNC 等等的內(nèi)容。

7. 命令傳播

后續(xù)的寫命令,都會通過上面配置的端口號不停傳輸。

其他內(nèi)容

心跳檢測

進行了套接字連接,執(zhí)行過PING命令之后,雖然保證了連接,但是后續(xù)的寫同步操作,依然需要實時連接。所以從服務(wù)器會定期發(fā)送自己的offset到主服務(wù)器上,檢測是否需要同步寫操作。

檢測從服務(wù)狀態(tài)

主服務(wù)器在一個時間周期內(nèi)沒有收到從服務(wù)器上述的心跳檢測內(nèi)容,則察覺從服務(wù)器可能異常了,所以這個時候會需要查看從服務(wù)器的信息。

Redis會配置一些拒絕寫操作的內(nèi)容,在一些特定情況下會認為寫操作不安全,這里的不安全是通過配置決定的:

  1. min-slaves-to-write 3
  2. min-slaves-max-lag 10

以上的信息表示從節(jié)點不能少于3個,或者3個從服務(wù)延遲不能超過10秒。否則拒絕寫操作,只執(zhí)行讀操作。

命令丟失

由于定期的心跳檢測的存在,所以定期檢測版本,發(fā)現(xiàn)消息丟失這種內(nèi)容就自動實現(xiàn)了,可以通過offset準確的了解到從服務(wù)器哪些信息沒有接受到,及時的作出響應(yīng)。

感謝

以上內(nèi)容參考Redis官方網(wǎng)站,以及《Redis的設(shè)計與實現(xiàn)》一書,如有紕漏,歡迎指出。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 一、Redis高可用概述 在介紹Redis高可用之前,先說明一下在Redis的語境中高可用的含義。 我們知道,在w...
    空語閱讀 1,673評論 0 2
  • 企業(yè)級redis集群架構(gòu)的特點 海量數(shù)據(jù) 高并發(fā) 高可用 要達到高可用,持久化是不可減少的,持久化主要是做災(zāi)難恢復(fù)...
    lucode閱讀 2,277評論 0 7
  • 數(shù)據(jù)庫 多數(shù)據(jù)庫結(jié)構(gòu) 一個Redis實例可以支持多個數(shù)據(jù)庫,當客戶端與服務(wù)端連接并指定到某個數(shù)據(jù)庫時,兩者的結(jié)構(gòu)如...
    宇宙最強架構(gòu)師閱讀 728評論 0 3
  • 基于內(nèi)存的NoSQL數(shù)據(jù)庫。提供五種數(shù)據(jù)結(jié)構(gòu)的存儲。字符串、列表、集合、有序集合、散列表。Redis 支持很多特性...
    韓絕交閱讀 811評論 0 1
  • 一個國家、一個民族的強盛,總是以文化興盛為支撐的。沒有文明的繼承和發(fā)展,沒有文化的弘揚和繁榮,就沒有中國夢的實現(xiàn)。...
    y飛舞的燕子y閱讀 548評論 0 1

友情鏈接更多精彩內(nèi)容