Redis(五):Redis主從複製原理及其部署

Redis主從複製原理及其部署

  • Redis主從複製如何實現?爲什麼?存在問題有哪些?解決方案是什麼?

Redis的主從複製

(1)主從複製的目的

  • 機器故障:(可用性)如何保證數據同步。
  • 容器瓶頸:讀寫分離,擴容需求
  • 數據冗餘:主從複製實現了數據的熱備份,是持久化之外的一種數據冗餘方式。
  • 故障恢復:當主節點出現問題時,可以由從節點提供服務,實現快速的故障恢復;實際上是一種服務的冗餘。
  • 負載均衡:在主從複製的基礎上,配合讀寫分離,可以由主節點提供寫服務,由從節點提供讀服務(即寫Redis數據時應用連接主節點,讀Redis數據時應用連接從節點),分擔服務器負載;尤其是在寫少讀多的場景下,通過多個從節點分擔讀負載,可以大大提高Redis服務器的併發量。
  • 讀寫分離:可以用於實現讀寫分離,主庫寫、從庫讀,讀寫分離不僅可以提高服務器的負載能力,同時可根據需求的變化,改變從庫的數量;
  • 高可用基石:除了上述作用以外,主從複製還是哨兵和集羣能夠實施的基礎,因此說主從複製是Redis高可用的基礎。

總結下:數據的冗餘備份;機器故障時的快速回復;負載(讀請求可以請求到多個Slave,減小單個Redis的併發量)讀寫分離;實現數據的高可用。

(2)主從複製原理

  1. 從節點執行 slaveof 命令
  2. 從節點只是保存了 slaveof 命令中主節點的信息,並沒有立即發起複製
  3. 從節點內部的定時任務發現有主節點的信息,開始使用 socket 連接主節點
  4. 連接建立成功後,發送** ping 命令**,希望得到** pong 命令響應**,否則會進行重連
  5. 如果主節點設置了權限,那麼就需要進行權限驗證;如果驗證失敗,複製終止。
  6. 權限驗證通過後,進行數據同步,這是耗時最長的操作,主節點將把所有的數據全部發送給從節點。
  7. 當主節點把當前的數據同步給從節點後,便完成了複製的建立流程。接下來,主節點就會持續的把寫命令發送給從節點,保證主從數據一致性

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-MfXGH2lN-1588256828570)(E423F613AC8A45CF992C14CA73763745)]

可以分爲兩個過程,一個是連接過程,一個是數據複製過程

  • 連接過程:slaveof命令保存主節點,socket進行主節點的連接(輪詢ping命令,得到pong命令返回則表示連接成功);驗權(主節點有權限校驗的情況下,slaver節點需配置masterauth)
2-1. 連接過程

連接不成功的處理

從節點執行info replication查看 master_link_down_since_seconds指標,它會記錄與主節點連接失敗的系統時間。

ping 請求的主要作用:

  • 檢測主從之間網絡套接字是否可用。
  • 檢測主節點當前是否可接受處理命令。

權限驗證

如果主節點設置了requirepass 參數,則需要密碼驗證,從節點必須配置 masterauth參數保證與主節點相同的密碼才能通過驗證

2-2. 複製過程
數據同步

先了解下面三個名詞概念

  • 主節點保存各從節點複製偏移量(offset)
    • 從節點每秒鐘會上報自己的複製偏移量(心跳機制);主節點也會進行復制偏移量的保存。作用主要有兩個,一:主節點知道從節點複製位置,部分複製時,以複製偏移量爲開始位置進行復制;二:判斷主從節點數據是否一致的依據。
    • 通過 info replication 命令查看master_repl_offset
  • 主節點複製積壓緩存區
    • 複製積壓緩衝區是一個保存在主節點的一個固定長度的先進先出的隊列。默認大小 1MB。
    • 作用:用於部分複製和複製命令丟失的數據補救
  • 主節點運行ID
    • 運行 ID 的主要作用是用來識別 Redis 節點(40位)
    • 問題在於,主節點運行ID改變時,會導致全量複製的發生
    • 解決方法:debug reload命令重新加載 RDB 並保持運行 ID 不變。從而有效的避免不必要的全量複製。缺點是阻塞當前Redis節點主線程。
Redis 同步有 2 個命令:sync和psync

前者是 redis 2.8 之前的同步命令,後者是 redis 2.8 爲了優化 sync 新設計的命令。我們會重點關注 2.8 的 psync 命令。

命令格式爲 psync {runId} {offset}

runId : 從節點所複製主節點的運行 id

offset:當前從節點已複製的數據偏移量

知乎上盜的一張圖(知乎很好用)
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-jq6in3wz-1588256828573)(6A7B035C68654B5D953381AA27751DA1)]

大致說明下:從節點發送 psync 命令給主節點,runId 就是目標主節點的 ID,如果沒有默認爲 -1,offset 是從節點保存的複製偏移量,如果是第一次複製則爲 -1.

Redis同步-全量複製與部分複製

全量複製是 Redis 最早支持的複製方式,也是主從第一次建立複製時必須經歷的的階段。觸發全量複製的命令是 sync 和 psync。之前說過,這兩個命令的分水嶺版本是 2.8,redis 2.8 之前使用 sync 只能執行全量不同,2.8 之後同時支持全量同步和部分同步

全量複製流程如下:

知乎上盜的一張圖
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-CqSahG0C-1588256828577)(8F32F61DF85A482FA44B3E7FB62B454D)]

  1. 發送** psync 命令(spync ? -1)**
  2. 主節點根據命令返回 FULLRESYNC
  3. 從節點記錄主節點 ID 和 offset
  4. 主節點 bgsave 並保存 RDB 到本地
  5. 主節點發送 RBD 文件到從節點
  6. 從節點收到 RDB 文件並加載到內存中
  7. 主節點在從節點接受數據的期間,將新數據保存到**“複製客戶端緩衝區”**,當從節點加載 RDB 完畢,再發送過去。(如果從節點花費時間過長,將導致緩衝區溢出,最後全量同步失敗)
  8. 從節點清空數據後加載 RDB 文件,如果 RDB 文件很大,這一步操作仍然耗時,如果此時客戶端訪問,將導致數據不一致,可以使用配置slave-server-stale-data關閉.
  9. 從節點成功加載完 RBD 後,如果開啓了 AOF,會立刻做 bgrewriteaof。

注:Redis 的默認超時機制(60 秒),會導致全量複製失敗。可以通過調大 repl-timeout 參數來解決此問題。

部分複製流程如下:

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-u0euF5FZ-1588256828581)(59776A4219F142E1B2F0CEC7AB96636B)]

  1. 當從節點出現網絡中斷,超過了** repl-timeout 時間**,主節點就會中斷複製連接
  2. 主節點會將請求的數據寫入到“複製積壓緩衝區”,默認 1MB。
  3. 當從節點恢復,重新連接上主節點,從節點會將 offset 和主節點 id 發送到主節點
  4. 主節點校驗後,如果偏移量的數後的數據在緩衝區中,就發送 cuntinue 響應 —— 表示可以進行部分複製
  5. 主節點將緩衝區的數據發送到從節點,保證主從複製進行正常狀態。

注意事項:

Redis 在 2.8 版本退出了類似增量複製的 psync 命令,當 Redis 主從直接發生了網絡中斷,不會進行全量複製,而是將數據放到緩衝區(默認 1MB)裏,在通過主從之間各自維護複製 offset 來判斷緩存區的數據是否溢出,如果沒有溢出,只需要發送緩衝區數據即可,成本很小,反之,則要進行全量複製,因此,控制緩衝區大小非常的重要。修改repl-backlog-size參數實現

(3)如何部署Redis的主從

這裏我會介紹兩種安裝方式,一種是非Docker部署,一種是Docker部署,讓諸君看看Docker的魅力;真香!

非Docker部署的關鍵是配置文件的修改,Docker部署將配置文件的修改要麼使用鏡像文件替代,要麼是啓動容器時使用對應的參數和將本地文件掛載到Redis容器數據卷中,實現動態地配置;Docker在這裏就是起到了簡化部署過程的作用!很香!

1. 非Docker部署

根據服務器性能,以及項目中實際業務需求,選擇Master(主節點),slaver(從節點)。

F道友演示的,是在同一臺虛機上,所以iptable的設置在此省略;使用不同的端口來進行演示。

類型 角色 IP 端口
Redis master 192.168.30.134 6379
Redis slaver 192.168.30.134 6380
Redis slaver 192.168.30.134 6381
Redis slaver 192.168.30.134 6382

redis.config配置文件參數設置如下

# 包含文件(redis-base.conf,文件從redis安裝目錄中拷貝的)
include /data/soft/redis-sentinel/redis-base.conf
# 將redis-base.conf文件中,bind註釋,需要在外網訪問,將protected-model改爲no
protected-mode no
# 端口 從節點的端口需要修改
port 6379
# 綁定主機 (或者不配置-自己在單個虛機上練習要注意這一點)
bind 0.0.0.0
# 後臺運行
daemonize yes
# pid文件
pidfile redis_master.pid
# 日誌文件
logfile "/data/log/redis-sentinel-log/redis-17007-log/redis-17007.log"
# 主認證密碼
masterauth 123456
# 認證密碼
requirepass 123456
# 最大內存10M,一般爲機器內存的3/4
maxmemory 10mb
# 內存達到最大時策略,可選擇其他策略
maxmemory-policy volatile-lru
# 目錄(Data存放路徑,虛機練習時不要相同)
dir /data/soft/redis-sentinel/redis-master/
# 快照文件(可使用默認)
dbfilename dump-master.rdb
# 開啓AOF(熱備,減少宕機等情況下數據丟失)
appendonly yes
# 更新指定的日誌文件名,默認爲appendonly.aof
appendfilename appendonly.aof
# AOF執行間隔 
# no:表示等操作系統進行數據緩存同步到磁盤(快)     
# always:表示每次更新操作後手動調用fsync()將數據寫到磁盤(慢,安全)
# everysec:表示每秒同步一次(折衷,默認值)
appendfsync everysec
# 下面是核心的主從配置(配置在從節點上,重要的事情說三遍:配置在從節點上
# 配置在從節點上,配置在從節點上)
# 從節點要跟隨的主節點
slaveof 192.168.30.134 6379
# 主節點認證密碼,如果設置了密碼,就要設置
masterauth 123456
# 配置後從節點只能讀(讀寫分離時使用)
slave-read-only yes

還有一些slace的配置,因爲這裏是做演示,所以不一一列出,有興趣的看我另一篇相關博文。

執行命令如下:

// 主、從節點的配置文件修改成功後,啓動相應的Redis服務
// 這裏要確定兩點:一如果是在兩臺機器上,確定網絡端口是否開放iptable查看對應
// 開放端口信息;二先啓動Master服務,再啓動從節點服務(否則主從連接失敗)
// config/master-6379.conf 是以指定的配置文件(master-6379.conf)啓動Redis
./src/redis-server config/master-6379.conf 
2. Docker部署(Docker大法好)

虛機的安裝,linux操作系統的安裝,docker的安裝的過程這裏暫且不講,CSDN,知乎等有大量教程,自行學習。博主以後也會更新一篇,單機版玩轉分佈式的專欄,裏面會講到上述配置。各位道友,敬請期待!

Redis 鏡像文件的獲取;這裏提供兩種方式,一種直接從鏡像倉庫中pull,一種直接創建,(推薦自行創建,鏡像文件的創建是docker很重要的一點,建議一點點學習!)

# 第一種獲取鏡像方式 -創建鏡像
// 個人習慣,我習慣將鏡像文件放在local下創建自己的文件夾下
[root@localhost usr]# cd /usr/local/floatcloud/
// 創建鏡像文件
[root@localhost floatcloud]# touch Dockerfile
// 編輯鏡像文件
[root@localhost floatcloud]# vim Dockerfile 

// Redis鏡像文件的內容如下

# 鏡像的根本依賴,也可以說是基於centos最新鏡像
FROM centos:lastest
# 構建鏡像作者
MAINTAINER floatCloud
# 添加用戶組、用戶
RUN groupadd -r redis && useradd -r -g redis redis
# 更新yum源,linux的epel-release(前面講過安裝docker時,要先安裝epel);安裝Redis
RUN yum -y update && yum -y install epel-release && yum -y install redis
# 定義端口
EXPOSE 6379

// 創建鏡像,查看鏡像
// 這個. 很關鍵,表示的是上下文關係
[root@localhost floatcloud]# docker build -t redis .
[root@localhost floatcloud]# docker images -a

# 第二種獲取鏡像方式 -pull鏡像倉庫中的鏡像
// 從鏡像倉庫中搜索鏡像
[root@localhost floatcloud]# docker search redis
// docker pull 鏡像名:tags      注:tags用來標記鏡像不同版本-對應Redis不同版本
// 道友們,可以去https://hub.docker.com/ 中查看自己想下載的版本(不加tags使用的默認版本)
[root@localhost floatcloud]# docker pull redis
[root@localhost floatcloud]# docker images -a

運行docker,一種使用-v 將本地文件掛載到容器的容器數據卷中,實現數據的共享與同步;還有一種是在進入容器 (exec -it),修改配置文件。道友們可以都嘗試下!F道人這裏推薦使用掛載到容器數據卷的形式,原因你品,你細品。

# 啓動參數形式設置
[root@localhost ~]# docker rum -d --name redis-master --privileged=true --restart always -v /var/user/floatcloud/master/redis.conf:/usr/local/etc/redis/redis.conf -v /var/user/floatcloud/master/data:/data -p 6379:6379 redis
[root@localhost ~]# docker rum -d --name redis-slaver1 --privileged=true --restart always -v /var/user/floatcloud/slaver1/redis.conf:/usr/local/etc/redis/redis.conf -v /var/user/floatcloud/slaver1/data:/data -p 6380:6379 redis
[root@localhost ~]# docker rum -d --name redis-slaver2 --privileged=true --restart always -v /var/user/floatcloud/slaver2/redis.conf:/usr/local/etc/redis/redis.conf -v /var/user/floatcloud/slaver2/data:/data -p 6381:6379 redis
[root@localhost ~]# docker rum -d --name redis-slaver3 --privileged=true --restart always -v /var/user/floatcloud/slaver3/redis.conf:/usr/local/etc/redis/redis.conf -v /var/user/floatcloud/slaver3/data:/data -p 6382:6379 redis
// 修改配置文件
// 一:進入容器修改,二:修改本地文件,重啓容器
[root@localhost ~]# docker exec -it redis-master sh
[root@localhost ~]# vim /etc/redis/redis
// 配置文件的修改上面已經說過這裏就不贅述
// 修改本地文件,並重啓容器
[root@localhost ~]# vim /var/user/floatcloud/master/redis.conf
[root@localhost ~]# docker restart redis-master

這裏說下從節點的簡要配置

# 從節點要跟隨的主節點
slaveof 192.168.30.134 6379
# 主節點認證密碼,如果設置了密碼,就要設置
masterauth 123456
# 配置後從節點只能讀(讀寫分離時使用)
slave-read-only yes

(4)主從的弊端有哪些?怎麼解決?

第一:主節點宕機,則Redis主從不可用。

第二:主從節點的維護全部依賴運維,增加運維成本。

解決方法:開啓Redis的哨兵模式,道人會在後續博文中介紹Redis的哨兵模式!

道友們,你們的老婆來了!
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章