6.主從複製

做者

微信:tangy8080
電子郵箱:914661180@qq.com
更新時間:2019-08-26 20:53:04 星期一node

歡迎您訂閱和分享個人訂閱號,訂閱號內會不按期分享一些我本身學習過程當中的編寫的文章
如您在閱讀過程當中發現文章錯誤,可添加個人微信 tangy8080 進行反饋.感謝您的支持。
git

文章主題

瞭解Redis主從複製的過程
主從複製則側重解決數據的多機熱備,主從複製是實現負載均衡和故障恢復的基礎github

前置條件

[無]redis

正文

概述

在分佈式系統中爲了解決單點問題,一般會把數據複製多個副本部署到 其餘機器,知足故障恢復和負載均衡等需求。Redis也是如此,它爲咱們提供了複製功能,實現了相同數據的多個Redis副本。複製功能是高可用Redis的基礎,哨兵和集羣都是在複製的基礎上實現高可用的。
參與複製的Redis實例劃分爲主節點(master)和從節點(slave)。默認 狀況下,Redis都是主節點。每一個從節點只能有一個主節點,而主節點能夠同時具備多個從節點。複製的數據流是單向的,只能由主節點複製到從節點shell

主從複製的配置

二進制方式安裝下的配置
  • 在配置文件中加入slaveof{masterHost}{masterPort}隨Redis啓動生效。
  • 在redis-server啓動命令後加入--slaveof{masterHost}{masterPort}生效。
  • 直接使用命令:slaveof{masterHost}{masterPort}生效。
k8s Helm方式安裝下的配置

https://github.com/helm/charts/tree/master/stable/redis
數據庫

查看複製狀態信息
  • k8s-180 主節點
[root@k8s-180 ~]# kubectl exec -it redis-master-0  redis-cli
127.0.0.1:6379> auth SbN8nBfMWh
OK
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=172.30.104.11,port=6379,state=online,offset=350,lag=1
slave1:ip=172.30.160.8,port=6379,state=online,offset=350,lag=0
master_replid:60809f9cc34104686610bab1a41d727382f50ac0
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:350
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:350
127.0.0.1:6379>
  • k8s-181 從節點0
[root@k8s-181 ~]# kubectl exec -it redis-slave-0  redis-cli
127.0.0.1:6379> auth SbN8nBfMWh
OK
127.0.0.1:6379> info replication
# Replication
role:slave
master_host:redis-master-0.redis-headless.default.svc.cluster.local
master_port:6379
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
slave_repl_offset:504
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:60809f9cc34104686610bab1a41d727382f50ac0
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:504
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:29
repl_backlog_histlen:476
127.0.0.1:6379>
  • k8s-182,從節點1
[root@k8s-181 ~]# kubectl exec -it redis-slave-1  redis-cli
127.0.0.1:6379> auth SbN8nBfMWh
OK
127.0.0.1:6379> info replication
# Replication
role:slave
master_host:redis-master-0.redis-headless.default.svc.cluster.local
master_port:6379
master_link_status:up
master_last_io_seconds_ago:8
master_sync_in_progress:0
slave_repl_offset:588
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:60809f9cc34104686610bab1a41d727382f50ac0
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:588
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:588
127.0.0.1:6379>

能夠看出172.30.104.11和172.30.160.8這兩個節點做爲了從節點
服務器

從節點斷開和主節點的同步

經過slaveof 命令創建主從複製關係之後,能夠經過slaveof no one斷開。須要注意的是,從節點斷開復制後,不會刪除已有的數據,只是再也不接受主節點新的數據變化。 微信

我在k8s-181節點上斷開和主節點的同步,能夠觀察到斷開鏈接後從節點又變回爲主節點
網絡

再看k8s-180節點,從之前的兩個從節點鏈接變成了一個
負載均衡

再次鏈接上主節點

使用 slaveof host port再次鏈接上主節點

127.0.0.1:6379> slaveof 172.30.104.10 6379
OK

只讀庫

通常來講線上的redis環境,從庫是隻讀的.主要是因爲

  • 從庫的更改,主庫不能及時感知.可能會形成數據不一致

可使用config get slave-read-only 來查看從庫是否開啓了只讀模式,從下面的命令能夠看到.我這裏的從庫是隻讀的

127.0.0.1:6379> config get slave-read-only
1) "slave-read-only"
2) "yes"
127.0.0.1:6379>
延遲
127.0.0.1:6379> config get repl-disable-tcp-nodelay
1) "repl-disable-tcp-nodelay"
2) "no"
127.0.0.1:6379>

repl-disable-tcp-nodelay no:該配置做用於命令傳播階段,控制主節點是否禁止與從節點的TCP_NODELAY;默認no,即不由止TCP_NODELAY。當設置爲yes時,TCP會對包進行合併從而減小帶寬,可是發送的頻率會下降,從節點數據延遲增長,一致性變差;具體發送頻率與Linux內核的配置有關,默認配置爲40ms。當設置爲no時,TCP會立馬將主節點的數據發送給從節點,帶寬增長但延遲變小。

通常來講,只有當應用對Redis數據不一致的容忍度較高,且主從節點之間網絡情況很差時,纔會設置爲yes;多數狀況使用默認值no。

主從複製的過程

創建TCP鏈接


複製的前提是主從節點之間能感知到對方的存在,須要知道對方的IP和端口

  • 從節點感知主節點的IP和端口
    因爲咱們在配置或者使用命令鏈接上主庫時,須要指定主庫的IP和端口.這樣從庫便知道了主庫的IP和端口(我的理解,不必定對)
    從節點服務器內部維護了兩個字段,即masterhost和masterport字段,用於存儲主節點的ip和port信息。
  • 創建socket鏈接
    從節點調用複製定時函數replicationCron()來嘗試鏈接到主節點
  • 發送ping命令
    從節點成爲主節點的客戶端以後,發送ping命令進行首次請求,目的是:檢查socket鏈接是否可用,以及主節點當前是否可以處理請求。
    從節點發送ping命令後,可能出現3種狀況:
    (1)返回pong:說明socket鏈接正常,且主節點當前能夠處理請求,複製過程繼續。
    (2)超時:必定時間後從節點仍未收到主節點的回覆,說明socket鏈接不可用,則從節點斷開socket鏈接,並重連。
    (3)返回pong之外的結果:若是主節點返回其餘結果,如正在處理超時運行的腳本,說明主節點當前沒法處理命令,則從節點斷開socket鏈接,並重連。

  • 身份驗證
    若是從節點中設置了masterauth選項,則從節點須要向主節點進行身份驗證;沒有設置該選項,則不須要驗證

127.0.0.1:6379> config get masterauth
1) "masterauth"
2) ""
127.0.0.1:6379>

在我這裏沒有爲主節點設置masterauth

  • 發送從節點端口信息
    身份驗證以後,從節點會向主節點發送其監聽的端口號.主節點將該信息保存到該從節點對應的客戶端的slave_listening_port字段中;

數據同步階段

在Redis2.8及之後,從節點能夠發送psync命令請求同步數據,此時根據主從節點當前狀態的不一樣,同步方式多是全量複製或部分複製
psync命令運行須要如下組件支持:
A.主Redis的複製偏移量(replication offset)和從Redis的複製偏移量。
B.主Redis的複製積壓緩衝區(replication backlog)。
C.Redis的運行ID(run ID)。

run_id,offset,複製積壓緩衝區
  • run_id:用來標識redis實例
    Redis 服務器的隨機標識符(用於 Sentinel 和集羣),重啓後就會改變;當複製時發現和以前的 run_id 不一樣時,將會對數據全量同步。
  • 複製偏移量:經過對比主從節點的複製偏移量,能夠判斷主從節點數據是否一致。
    1.參與複製的主從節點都會維護自身複製偏移量。主節點(master)在處理完寫入命令後,會把命令的字節長度作累加記錄.
    2.從節點(slave)每秒鐘上報自身的複製偏移量給主節點,所以主節點也會保存從節點的複製偏移量.
    3.從節點在接收到主節點發送的命令後,也會累加記錄自身的偏移量
  • 複製積壓緩衝區
127.0.0.1:6379> config get repl-backlog-size
1) "repl-backlog-size"
2) "1048576"

複製積壓緩衝區是由主服務器維護的一個固定長度(fixed-size)先進先出(FIFO)隊列,默認大小爲1MB。
當主服務器進行命令傳播時,它不只會將寫命令發送給全部從服務器,還會將寫命令入隊到複製積壓緩衝區裏面

所以,主服務器的複製積壓緩衝區裏面會保存着一部分最近傳播的寫命令,而且複製積壓緩衝區會爲隊列中的每一個字節記錄相應的複製偏移量,就像下表所示的那樣。

當從服務器從新連上主服務器時,從服務器會經過PSYNC命令將本身的複製偏移量offset發送給主服務器,主服務器會根據這個複製偏移量來決定對從服務器執行何種同步操做:

a、若是offset偏移量以後的數據(也便是偏移量offset+1開始的數據)仍然存在於複製積壓緩衝區裏面,那麼主服務器將對從服務器執行部分重同步操做;
b、相反,若是offset偏移量以後的數據已經不存在於複製積壓緩衝區,那麼主服務器將對從服務器執行完整重同步操做。
舉例: 從服務器偏移量爲10086,若是能在積壓緩衝區裏找到10086+1的數據,執行部分同步.因爲隊列長度有限,可能已經超對隊列.

全量複製:

通常用於初次複製場景,Redis早期支持的複製功能只有全量複製,它會把主節點所有數據一次性發送給從節點,當數據量較大時,會對主從節點和網絡形成很大的開銷。

1.Redis內部會發出一個同步命令,剛開始是Psync命令,Psync ? -1表示要求master主機同步數據
2.主機會向從機發送run_id和offset,由於slave並無對應的 offset,因此是全量複製
3.從機slave會保存主機master的基本信息
4.主節點收到全量複製的命令後,執行bgsave(異步執行),在後臺生成RDB文件(快照),並使用一個緩衝區(稱爲複製緩衝區)記錄從如今開始執行的全部寫命令
5.主機發送RDB文件給從機
6.發送緩衝區數據
7.刷新舊的數據。從節點在載入主節點的數據以前要先將老數據清除
8.加載RDB文件將數據庫狀態更新至主節點執行bgsave時的數據庫狀態和緩衝區數據的加載。

部分複製:

用於網絡中斷等狀況後的複製,只將中斷期間主節點執行的寫命令發送給從節點,與全量複製相比更加高效。須要注意的是,若是網絡中斷時間過長,致使主節點沒有可以完整地保存中斷期間執行的寫命令,則沒法進行部分複製,仍使用全量複製。

1.若是網絡抖動(鏈接斷開 connection lost)
2.主機master 仍是會寫 repl_back_buffer(複製緩衝區)
3.從機slave 會繼續嘗試鏈接主機
4.從機slave 會把本身當前 run_id 和偏移量傳輸給主機 master,而且執行 pysnc 命令同步
5.若是master發現你的偏移量是在緩衝區的範圍內,就會返回 continue命令
同步了offset的部分數據,因此部分複製的基礎就是偏移量 offset。

引用連接

https://www.iteye.com/blog/uule-2429825

相關文章
相關標籤/搜索