如下筆記以及實驗皆出自於 中華石杉大佬的視頻教學,我跟着作了實驗,而且把課上的筆記整理了一下。html
在一個項目中使用redis必然是由於咱們想要作成高併發,redis是整個大型的緩存架構中,支撐高併發的很是重要的一個環節, 可是光redis是不夠的。java
redis不能支撐高併發的瓶頸就是 單機 單機的redis不可能說QPS超過10萬+,除非你的機器性能特別好,維護作的好, 並且你的總體的操做不能太複雜。node
因此讀寫分離通常來講是用來支撐高併發,寫的請求比較少,大量的請求都是讀,那麼redis的主從架構就是比較好的選擇, 主從架構 -> 讀寫分離 -> 水平擴容支撐讀高併發,主節點用來寫,從節點用來讀。git
PS:在我使用的5.0.4版本中slave這個術語已經被replica代替了,嗯~ 這個單詞的意思確實有點很差聽哈。反正官方已經改掉了,我也就全換掉了。github
當啓動一個 replica node 的時候,它會發送一個 PSYNC
命令給 master node。redis
若是 replica node 使用 PSYNC
初次鏈接到 master node,那麼會觸發一次 full resynchronization 全量複製。此時 master 會啓動一個後臺線程, 開始生成一份 RDB 快照文件,同時還會將從客戶端 client 新收到的全部寫命令緩存在內存中。RDB 文件生成完畢後, master 會將這個 RDB 發送給 replica, replica 會先寫入本地磁盤,而後再從本地磁盤加載到內存中,接着 master 會將內存中緩存的寫命令發送到 replica,replica 也會同步這些數據。replica node 若是跟 master node 有網絡故障,斷開了鏈接,會自動重連,鏈接以後 master node 僅會複製給 replica 部分缺乏的數據。spring
簡單來講PSYNC完成的使命就是判斷從服務器是否須要全量複製仍是增量複製,畢竟每次由於一點點網路波動從新鏈接主節點,都要全量複製,很是的低效緩存
PSYNC格式:安全
PSYNC runid offsetbash
runid
每一個Redis服務器都會有一個代表本身身份的ID。在PSYNC中發送的這個ID是指以前鏈接的Master的ID,若是沒保存這個ID, PSYNC的命令會使用」PSYNC ? -1」 這種形式發送給Master,表示須要全量複製。
offset(複製偏移量)
在主從複製的Master和replica雙方都會各自維持一個offset。Master成功發送N個字節的命令後會將Master的offset加上N, replica在接收到N個字節命令後一樣會將replica的offset增長N。Master和replica若是狀態是一致的那麼它的的offset也應該是一致的。
若是在複製期間,內存緩衝區超過60秒一直消耗超過 64MB,或者一次性超過 256MB,那麼中止複製,複製失敗。後兩個參數是配合使用的,假如:消耗超過64MB 一直持續了59秒,可是60秒的時候不超過64MB了,那麼就保持鏈接繼續複製。
master node 將 rdb 快照文件發送給 replica node,若是 rdb 複製時間超過 60秒(redis配置文件參數:repl-timeout),那麼 replica node 就會認爲複製失敗, 能夠適當調大這個參數(對於千兆網卡的機器,通常每秒傳輸 100MB,6G 文件,極可能超過 60s)
master node 在生成 rdb 時,會將全部新的寫命令緩存在內存中,在 replica node 保存了 rdb 以後,再將新的寫命令複製給 replica node; 從節點首先清除本身的舊數據,而後載入接收的RDB文件
主節點將前述複製緩衝區中的全部寫命令發送給從節點,從節點執行這些寫命令,若是從節點開啓了AOF,則會觸發bgrewriteaof的執行,從而保證AOF文件更新至主節點的最新狀態
若是全量複製過程當中,master-replica 網絡鏈接斷掉,那麼 replica 從新鏈接 master 時,會觸發增量複製。
master 直接從本身的 backlog 中獲取部分丟失的數據,發送給 replica node,默認 backlog 就是 1MB。
master 就是根據 replica 發送的 psync 中的 offset 來從 backlog 中獲取數據的。
例如,若是主節點的offset是1000,而從節點的offset是500,那麼部分複製就須要將offset爲501-1000的數據傳遞給從節點
replica node 啓動時,會在本身本地保存 master node 的信息,包括 master node 的host和ip,可是複製流程沒開始。
replica node 內部有個定時任務,每秒檢查是否有新的 master node 要鏈接和複製,若是發現,就跟 master node 創建 socket 網絡鏈接; 而後 replica node 發送 ping 命令給 master node。若是 master 設置了 requirepass(就是redis的登陸密碼), 那麼 replica node 必須發送 masterauth 的口令過去進行認證;master node 第一次執行全量複製,將全部數據發給 replica node; 而在後續,master node 持續將寫命令,異步複製給 replica node。
第一步:從節點服務器內部維護了兩個字段,即masterhost和masterport字段,用於存儲主節點的ip和port信息。
第二步:創建socket鏈接,即從節點每秒1次調用複製定時函數replicationCron(),若是發現了有主節點能夠鏈接,便會根據主節點的ip和port,建立socket鏈接
第三步:身份驗證,若是從節點中設置了masterauth選項,則從節點須要向主節點進行身份驗證;沒有設置該選項,則不須要驗證; 從節點進行身份驗證是經過向主節點發送auth命令進行的,auth命令的參數即爲配置文件中的masterauth的值;若是主節點設置密碼的狀態, 與從節點masterauth的狀態一致(一致是指都存在,且密碼相同,或者都不存在),則身份驗證經過,複製過程繼續;若是不一致,則從節點斷開socket鏈接,並重連。
第四步:數據同步,就是全量複製或者增量複製,並且在複製階段繼續有寫命令會存在主節點內存中,後續會異步發送給replica node
replica node若是跟master node有網絡故障,斷開了鏈接,會自動重連。master若是發現有多個replica node都來從新鏈接, 僅僅會啓動一個rdb save操做,用一份數據服務全部replica node。
從redis 2.8開始,就支持主從複製的斷點續傳,若是主從複製過程當中,網絡鏈接斷掉了,那麼能夠接着上次複製的地方,繼續複製下去,而不是從頭開始複製一份
master node會在內存中常見一個backlog,master和replica都會保存一個replica offset還有一個master id,offset就是保存在backlog中的。 若是master和replica網絡鏈接斷掉了,replica會讓master從上次的replica offset開始繼續複製
可是若是沒有找到對應的offset,那麼就會執行一次resynchronization(全量複製)
master 在內存中直接建立 RDB,而後發送給 replica,不會在本身本地落地磁盤了。只須要在配置文件中開啓 repl-diskless-sync yes 便可。
repl-diskless-sync yes
# 等待 5s 後再開始複製,由於要等更多 replica 從新鏈接過來
repl-diskless-sync-delay 5
複製代碼
replica不會過時key,只會等待master過時key。若是master過時了一個key,或者經過LRU淘汰了一個key,那麼會模擬一條del命令發送給replica。
主從節點互相都會發送 heartbeat 信息。
master 默認每隔 10秒 發送一次 heartbeat,replica node 每隔 1秒 發送一個 heartbeat。
若是採用了主從架構,那麼建議必須開啓master node的持久化! 如何實現redis的持久化
並且不建議使用replica node做爲master node的數據熱備若是你關掉master的持久化,可能在master宕機重啓的時候數據是空的,而後可能一通過複製,replica node數據也丟了
另外,master 的各類備份方案,也須要作。萬一本地的全部文件丟失了,從備份中挑選一份 rdb 去恢復 master,這樣才能確保啓動的時候,是有數據的 即便採用了後續講解的高可用機制,replica node能夠自動接管master node,可是也可能sentinal尚未檢測到master failure,master node就自動重啓了, 仍是可能致使上面的全部replica node數據清空故障。
node | hostname | IP | port |
---|---|---|---|
master node | eshop-cache01 | 192.168.0.30 | 6379 |
replica node | eshop-cache02 | 192.168.0.31 | 6379 |
在除了安裝redis時配置的參數外,從節點還須要額外配置如下內容
bind 127.0.0.1
爲 bind 192.168.0.30
本身自己的ip地址或者配置成 bind 0.0.0.0 若是配置成自己ip地址,則須要在使用redis的客戶端時,使用redis-cli -h 192.168.0.30進入客戶端了
requirepass redis-pass
, 就是登陸redis 的登陸密碼在配置文件中修改 bind 127.0.0.1
爲 bind 192.168.0.31
本身自己的ip地址
配置 replicaof
爲 replicaof eshop-cache01 6379
eshop-cache01我是在 master node /etc/hosts
中配置了映射本機的ip
replicaof 填寫主節點的ip 和 端口號
開啓安全認證 masterauth redis-pass
填寫的就是 master node 的登陸密碼,須要在主節點配置文件中配置
強制讀寫分離 replica-read-only yes
這個默認是開啓的
能夠自由選擇是否開啓AOF持久化
前後啓動主節點和從節點的redis實例,進入主節點客戶端,set k1 v1
而後在從節點中看是否能讀取到數據,讀取到數據即表明成功。
info replication
命令能夠查看自己的角色是主節點 仍是 從節點