## 主從復制
Redis中可以將一臺服務器設置主機(master),別的服務器設置成從機(slaver),實現`主從模式`。在Redis的主從模式下主服務器只能`寫數據`,從服務器只能`讀數據`。Redis的主從模式會將主服務器中的所有數據會通過`寫時復制`技術**備份**到從服務器中,從而保證主從服務器之間的“數據一致性”。
```
備注:
主機:master - 寫數據
從機:slaver - 讀數據
```
將一臺服務器設置為從服務器的命令為:
```bash
localhost:6380>slaveof master_ip port
# 例如:slaveof localhost 6379
# 即可將6380端口這臺服務器設置為6379端口服務器的從服務器
```
使用`info replication`命令可以查看當前服務器的狀態

接著查看主服務器的狀態

Redis中搭建主從模式的命令非常簡單,下面就來看主從復制原理和服務器宕機時保存數據的解決方案。
下面是Redis中主從復制原理的實現,在不同版本的其實現有些區別。
### 2.8版本之下的主從復制實現
Redis中的復制功能可以分為兩個操作
1. `同步`:將從服務器的數據庫狀態更新為主服務器的數據庫狀態。
2. `命令傳播`:主服務器的數據被修改之后,將**修改命令**發送到從服務器中修改對應的數據,保持數據一致性。
當從服務器的客戶端向從服務器發送**slaveof**命令要求從服務器復制主服務器當中的數據時,從服務器會向主服務器發送`sync命令`來執行同步操作,會經過如下步驟:
1. 從服務器向主服務器發送sync命令。
2. 主服務器接收到sync命令之后執行`bgsave命令`,生成一個rdb文件。同時使用一個**緩沖區記錄從現在開始執行**的所有寫命令,這是為了在執行bgsave命令階段和發送rdb文件階段主服務器可能有數據被修改了,這一部分修改的數據會在后面通過命令傳播的方式復制到從服務器中。
3. 當主服務器執行完bgsave命令之后,會將rdb文件發送給從服務器,從服務器根據這個rdb文件與主服務的數據庫狀態進行同步。(寫時復制技術)
:-: 
在同步操作實現之后,每當主服務器的數據被修改了,就會通過命令傳播的方式向從服務器**發送同樣的命令**修改從服務器中數據,再一次的達到數據同步的效果。
> 2.8版本以下復制操作的缺陷
在2.8版本以下的復制操作中如果從服務器和主服務器斷開連接了(注意不是宕機),再重新連接之后,從服務器會重新執行一遍同步操作,即還是重新發送`sync命令`。這種斷線后重新復制的操作的效率是非常低下的。例如
```
在還沒有斷開連接之前,主從服務器都有鍵key1,key2,key3...key1000。
在從服務器斷開連接到重新恢復連接階段,主服務器又新加了鍵key1001,key1002,key1003,
而從服務器仍然之后前面的1000個鍵。如果這個時候因為這新加的三個鍵而重新完整的一份rdb數據,
是非常消耗性能和帶寬的。
```
2.8及之上版本就對斷開連接之后重新連接的復制進行了優化。
### 2.8版本及之上的主從復制實現(重點)
2.8及之上的版本使用**psync**命令來替代sync命令執行復制時的同步操作。psync命令分為完全重同步和部分重同步兩種模式。
1. 完全重同步的實現與sync命令的實現基本一致。
2. 斷開之后重新連接的數據同步通過`部分重同步模式`來實現。
部分重同步模式功能的實現有三個部分構成,**偏移量**,**復制積壓緩沖區**,**服務器的運行ID**。
1. 偏移量 replication offset,主從服務器雙方會維護一個復制偏移量,每次主服務器向從服務器傳播N個字節的數據的時候就會在自己的偏移量上加上N。同時從服務器在接收到這N個字節之后也會在自己的偏移量上加上N。
通過對比主從服務器的偏移量大小,就很容易能夠得出主從服務的數據是否一致。
從服務器向主服務器發送psync信號時會**攜帶自己的偏移量**過去。
2. 復制積壓緩沖區,是由主服務維護的一個固定長度的隊列,默認大小為1MB。當主服務進行命令傳播時,不僅會將命令發送給從服務器,還會將命令保存進復制積壓緩沖區中。因此隊列中會保存最近的命令,同時在隊列中會記錄對應命令的偏移量。
當主服務器接收到從服務器的psync命令中的偏移量之后,判斷從服務器的偏移量和自己當前的偏移量,如果不一致,就去復制積壓緩沖區找找對應的偏移量對應的命令發送給從服務器執行。**如果偏移量在復制積壓緩沖區沒有對應,則會進行一次完全重同步操作。**
`復制積壓緩沖區的大小可以去:repl-backlog-size中修改。`
3. 服務器運行ID(run ID),每個Redis服務器都有一個屬于自己的40位隨機的十六進制組成的ID編號。
當從服務器第一次與主服務進行同步時,會保存主服務器的id。接著在斷線重連之后會發送主服務器的ID,然后主服務器判斷該ID是否與自己的ID相等。如果相等則進行部分重同步的操作,如果不相等,則進行完全重同步操作。
> psync命令的格式
1. 從服務在第一次執行slaveof時,即開始第一次復制主服務器中的數據時會發送
```bash
psync ? -1
```
表示第一次復制,此時進行的是完整重同步。
2. 在之后的每一次發送的psync命令中都會發送
```bash
psync <runid> <offset>
```
runid:服務器id。
offset:數據偏移量。
完整的主從復制流程圖如下:
:-: 
### 主從復制的三種常用結構
1. 一主兩仆
如果一個從服務器掛掉了,重啟之后還是作為一個獨立的主服務器,而不會繼續作為原來主機的從服務器。需要使用`slaveof ip port`命令重新設置。
如果是主服務器掛掉了,從服務器仍然是從服務器,主服務器重啟之后仍然是主服務器。
2. 薪火相傳
`常用`
類似于樹的遞歸方式進行主從服務器的設置。當有一臺從服務器斷開了,可能會導致樹的斷開。
3. 反客為主
當主服務器掛掉了之后,其從服務器中有一臺成為主服務器。使用命令:
```
slaveof no one
```
這種方式需要手動的進行設置。
> 檢查網絡連接狀態
在命令傳播階段,從服務器每秒會向主服務發送一次
```bash
replconf ack <replication_offset>
```
這個命令可以起到:
1. 檢測主從服務器之間的網絡連接狀態
在從主務器中通過info replication可以查看如下信息:
:-: 
`lag`就是發送命令的時間差,一般在0-1之間,如果超過1,主從之間的連接可能就斷開了。
2. 輔助實現min-slaves選項
redis.conf中有如下兩個文件可以避免主服務在不安全的情況下進行寫操作:
```conf
min-slaves-to-write 3
min-slaves-max-lag 10
```
在從服務器數量少于3個,或者三個從服務器的延遲都大于10秒時,不進行寫操作。
3. 防止命令丟失
在命令傳播過程中可能會導致命令丟失,這個使用通過比較發送的replication_offset就可以發現,不一致的情況下主服務器就會從復制積壓緩沖區中再發送一次。
【參考】
1. 《Redis設計與實現》第15章
- 第一章 Java基礎
- ThreadLocal
- Java異常體系
- Java集合框架
- List接口及其實現類
- Queue接口及其實現類
- Set接口及其實現類
- Map接口及其實現類
- JDK1.8新特性
- Lambda表達式
- 常用函數式接口
- stream流
- 面試
- 第二章 Java虛擬機
- 第一節、運行時數據區
- 第二節、垃圾回收
- 第三節、類加載機制
- 第四節、類文件與字節碼指令
- 第五節、語法糖
- 第六節、運行期優化
- 面試常見問題
- 第三章 并發編程
- 第一節、Java中的線程
- 第二節、Java中的鎖
- 第三節、線程池
- 第四節、并發工具類
- AQS
- 第四章 網絡編程
- WebSocket協議
- Netty
- Netty入門
- Netty-自定義協議
- 面試題
- IO
- 網絡IO模型
- 第五章 操作系統
- IO
- 文件系統的相關概念
- Java幾種文件讀寫方式性能對比
- Socket
- 內存管理
- 進程、線程、協程
- IO模型的演化過程
- 第六章 計算機網絡
- 第七章 消息隊列
- RabbitMQ
- 第八章 開發框架
- Spring
- Spring事務
- Spring MVC
- Spring Boot
- Mybatis
- Mybatis-Plus
- Shiro
- 第九章 數據庫
- Mysql
- Mysql中的索引
- Mysql中的鎖
- 面試常見問題
- Mysql中的日志
- InnoDB存儲引擎
- 事務
- Redis
- redis的數據類型
- redis數據結構
- Redis主從復制
- 哨兵模式
- 面試題
- Spring Boot整合Lettuce+Redisson實現布隆過濾器
- 集群
- Redis網絡IO模型
- 第十章 設計模式
- 設計模式-七大原則
- 設計模式-單例模式
- 設計模式-備忘錄模式
- 設計模式-原型模式
- 設計模式-責任鏈模式
- 設計模式-過濾模式
- 設計模式-觀察者模式
- 設計模式-工廠方法模式
- 設計模式-抽象工廠模式
- 設計模式-代理模式
- 第十一章 后端開發常用工具、庫
- Docker
- Docker安裝Mysql
- 第十二章 中間件
- ZooKeeper