這篇文章帶大家了解一下Redis中的主從同步,介紹一下Redis主從的兩種結構模型、主從關係的建立、主從複製策略等,希望對大家有所幫助!
先前的文章中詳細分析了redis的特性和核心原理,從本篇開始將對redis的部署結構和運作模式進行分析解讀。真正生產環境當中我們基本上不會使用單節點的redis來提供服務,至少是主從結構的哨兵或叢集模式,以保障redis服務的可靠性。本篇就來詳細解讀下redis的主從同步機制。 【相關建議:Redis影片教學】
下圖為主從關係建立流程:
注意:
#根據上執行流程這裡有一個需要注意點,當我們對一個已有主從關係的節點執行slaveof命令時,會結束掉現有的主從關係並清空節點下的所以數據,在生成環境當中這是比較威脅的操作。有沒有更安全的方式了?上面介紹slavelof指令的時候提到可以傳遞NO ONE參數,也就是執行SLAVEOF NO ONE指令,這個指令是只會結束主從複製關係不會清空資料的,相對安全很多。 三、資料同步建立好主從關係後就要進入主從資料同步的過程了,這裡主要分三種情況,剛建立主從關係後的資料全量同步;初始化同步完成後的命令傳播階段;主從關係異常中斷重連後的同步方式選擇,這裡會有全量和增量同步兩種場景。 3.1 全量同步master節點每執行一個寫入指令就會傳送相同的寫入指令,slave節點接收並執行收到的寫入指令。 (指令傳播操作,slave節點初始化完成後的操作)
全量同步流程如下圖:
在redis2.8之前,從節點無論是初始化或斷線重連後都是採用全量同步的方式,在2.8之後版本,引入PSYNC指令,在從節點斷線重連後會判斷是否採用增量同步。
PSYNC具備了資料全量重同步和增量同步模式。
全量重同步:跟舊版複製基本上是一致的,可以理解為「全量」複製。
部分重同步:salve斷開又重新連時,在指令傳播階段,只需要發送與master斷開這段時間執行的寫命給slave即可,可以理解為“增量”複製。
PSYNC執行過程中比較重要的概念有3個:runid、offset(複製偏移量)以及複製積壓緩衝區。
1.runid
每個Redis伺服器都會有一個表明自己身分的ID。在PSYNC中發送的這個ID是指之前連接的Master的ID,如果沒保存這個ID,PSYNC的命令會使用”PSYNC ? -1” 這種形式發送給Master,表示需要全量複製。
2.offset(複製偏移量)
在主從複製的Master和Slave雙方都會各自維持一個offset。 Master成功發送N個位元組的指令後會將Master裡的offset加上N,Slave在接收到N個位元組指令後同樣會將Slave裡的offset增加N。 Master和Slave如果狀態是一致的那麼它的的offset也應該是一致的。
3.複製積壓緩衝區
複製積壓緩衝區是由Master維護的一個固定長度環形積壓佇列(FIFO佇列),它的作用是快取已經傳播出去的命令。當Master進行指令傳播時,不僅將指令傳送給所有Slave,也會將指令寫入到複製積壓緩衝區裡面。 PSYNC執行過程和SYNC的差別在於:salve連接時,判斷是否需要全量同步,全量同步的邏輯過程和SYNC一樣。 PSYNC執行步驟如下:
客戶端向伺服器發送SLAVEOF指令,也就是salve向master發起連線請求時,slave會根據自己是否儲存Master runid來判斷是否是第一次連線。
如果是第一次同步則向Master發送PSYNC ? -1 指令來進行完整同步;如果是重連接,會向Master發送PSYNC runid offset指令(runid是master的身份ID,offset是從節點同步指令的全域遷移量)。
Master接收到PSYNC 指令後,先判斷runid是否和本機的id一致,如果一致則會再次判斷offset偏移量和本機的偏移量相差有沒有超過複製積壓緩衝區大小,如果沒有那麼就給Slave發送CONTINUE,此時Slave只需要等待Master傳回失去連線期間遺失的指令。如果runid和本機id不一致或offset差距超過了複製積壓緩衝區大小,那麼就會傳回FULLRESYNC runid offset,Slave將runid保存起來,並進行全量同步。
主節點在命令傳播時,主資料庫會將每個寫入命令傳遞給從資料庫的同時,都會將寫入命令存放到積壓隊列,並記錄當前積壓隊列中存放指令的全域偏移量offset。當salve重連接時,master會根據從節點傳的offset在環形積壓佇列中找到斷開這段時間執行的指令,並同步給salve節點,達到增量同步結果。
PSYNC執行流程如下圖:
從以上PSYNC的執行流程可以看出當slave節點斷線重連以後判斷是否採用增量同步的核心是slave的offset偏移量和master的偏移量相差有沒有超過複製積壓緩衝區大小,那麼這個大小是由下列參數來配置的。複製積壓緩衝區本質上是一個固定長度的循環隊列,預設情況下積壓隊列的大小為1MB,可以透過設定檔設定隊列大小:設定複製積壓緩衝區大小,積壓隊列越大,允許主從資料庫斷線的時間就越長
repl-backlog-size 1mb
Redis同時也提供了當沒有slave需要同步的時候,多久可以釋放環形佇列,預設一小時,沒有salve連線時,多久釋放一次複製積壓緩衝區
repl-backlog-ttl 3600
Redis采用了乐观复制的策略,也就是在一定程度内容忍主从数据库的内容不一致,但是保持主从数据库数据的最终一致性。具体来说,Redis在主从复制的过程中,本身就是异步的,在主从数据库执行完客户端请求后会立即将结果返回给客户端,并异步的将命令同步给从数据库,但是这里并不会等待从数据库完全同步之后,再返回客户端。这一特性虽然保证了主从复制期间性能不受影响,但是也会产生一个数据不一致的时间窗口,如果在这个时间窗口期间网络突然断开连接,就会导致两者数据不一致。如果不在配置文件中添加其他策略,那就默认会采用这种方式。为了防止主从不一致不可控,redis提供了以下两个参数来做约束:
min-slaves-to-write 3 min-slaves-max-lag 10
当slave数量小于min-slaves-to-write,且延迟小于等于min-slaves-max-lag时,master停止写入操作。
还有一个参数也会影响主从之间的延时:
repl-disable-tcp-nodelay:
设置成yes,则redis会合并小的TCP包从而节省带宽,但会增加同步延迟,造成master与slave数据不一致。设置成no,则redis master会立即发送同步数据,几乎没有延迟。
Redis的主从同步无论那种场景可以抽象为以下七个步骤:
1.建立socket连接
从服务器根据设置的套接字创建连向主服务器的套接字连接,主服务器接收从服务器的套接字连接之后,为该套接字创建响应的客户端状态,并将此时的从服务器看做是主服务器的客户端,也就是该从服务器同时具备服务器与客户端两个身份。
2.发送PING命令
PING命令主要有两种作用:虽然建立了套接字连接,但是还未使用过,通过发送PING命令检查套接字的读写状态是否正常;通过发送PING命令检查主服务器能否正常处理命令请求,能处理主服务器回复PONG。
3.身份验证
从服务器接收到主服务器返回的“PONG”回复,接下来就需要考虑身份验证的事。如果从服务器设置了masterauth选项,那么进行身份验证,如果从服务器没有设置masterauth选项,那么不进行身份验证。
4.发送端口信息
在身份验证步骤之后,从服务器将执行命令REPLCONF listening-port ,向主服务器发送从服务器的监听端口号。
5.数据同步
从服务器向主服务器发送SYNC命令、PSYNC命令,执行同步操作。
6.命令传播
主从服务器就会进入命令传播阶段,主服务器只要将自己执行的写命令发送给从服务器,而从服务器只要一直执行并接收主服务器发来的写命令。
本篇详细介绍了redis主从同步机制,不同场景下同步策略的选择,这也是redis高可用的基石。在此基础上,下一篇将对redis高可用的实现来进行分析讲解。
更多编程相关知识,请访问:编程视频!!
以上是深入了解Redis中的主從同步機制的詳細內容。更多資訊請關注PHP中文網其他相關文章!