Replication
Redis 支援簡單且易用的主從複製(master-slave replication)功能, 該功能可以讓從伺服器(slave server)成為主伺服器(master server)的精確複製品。
以下是關於 Redis 複製功能的幾個重要方面:
● Redis 使用非同步複製。 從 Redis 2.8 開始, 從伺服器會以每秒一次的頻率向主伺服器報告複製流(replication stream)的處理進度。
● 一個主伺服器可以有多個從伺服器。
● 不僅主伺服器可以有從伺服器, 從伺服器也可以有自己的從伺服器, 多個從伺服器之間可以構成一個圖狀結構。
● 複製功能不會阻塞主伺服器: 即使有一個或多個從伺服器進行中初次同步, 主伺服器也可以繼續處理命令請求。
● 複製功能也不會阻塞從伺服器: 只要在 redis.conf 檔案中進行了相應的設定, 即使從伺服器進行中初次同步, 伺服器也可以使用舊版本的資料集來處理命令查詢。
不過, 在從伺服器刪除舊版本資料集並載入新版本資料集的那段時間內, 串連請求會被阻塞。
你還可以配置從伺服器, 讓它在與主伺服器之間的串連斷開時, 向用戶端發送一個錯誤。
● 複製功能可以單純地用於資料冗餘(data redundancy), 也可以通過讓多個從伺服器處理唯讀命令請求來提升擴充性(scalability): 比如說, 繁重的 SORT 命令可以交給附屬節點去運行。
● 可以通過複製功能來讓主伺服器免於執行持久化操作: 只要關閉主伺服器的持久化功能, 然後由從伺服器去執行持久化操作即可。 複製功能的運作原理
無論是初次串連還是重新串連, 當建立一個從伺服器時, 從伺服器都將向主伺服器發送一個 SYNC 命令。
接到 SYNC 命令的主伺服器將開始執行 BGSAVE , 並在儲存操作執行期間, 將所有新執行的寫入命令都儲存到一個緩衝區裡面。
當 BGSAVE 執行完畢後, 主伺服器將執行儲存操作所得的 .rdb 檔案發送給從伺服器, 從伺服器接收這個 .rdb 檔案, 並將檔案中的資料載入到記憶體中。
之後主伺服器會以 Redis 命令協議的格式, 將寫命令緩衝區中積累的所有內容都發送給從伺服器。
你可以通過 telnet 命令來親自驗證這個同步過程: 首先連上一個正在處理命令請求的 Redis 伺服器, 然後向它發送 SYNC 命令, 過一陣子, 你將看到 telnet 會話(session)接收到伺服器發來的大段資料(.rdb 檔案), 之後還會看到, 所有在伺服器執行過的寫命令, 都會重新發送到 telnet 會話來。
即使有多個從伺服器同時向主伺服器發送 SYNC , 主伺服器也只需執行一次 BGSAVE 命令, 就可以處理所有這些從伺服器的同步請求。
從伺服器可以在主從伺服器之間的串連斷開時進行自動重連, 在 Redis 2.8 版本之前, 斷線之後重連的從伺服器總要執行一次完整重同步(full resynchronization)操作, 但是從 Redis 2.8 版本開始, 從伺服器可以根據主伺服器的情況來選擇執行完整重同步還是部分重同步(partial resynchronization)。 部分重同步
從 Redis 2.8 開始, 在網路連接短暫性失效之後, 主從伺服器可以嘗試繼續執行原有的複製進程(process), 而不一定要執行完整重同步操作。
這個特性需要主伺服器為被發送的複製流建立一個記憶體緩衝區(in-memory backlog), 並且主伺服器和所有從伺服器之間都記錄一個複製位移量(replication offset)和一個主伺服器 ID (master run id), 當出現網路連接斷開時, 從伺服器會重新串連, 並且向主伺服器請求繼續執行原來的複製進程:
● 如果從伺服器記錄的主伺服器 ID 和當前要串連的主伺服器的 ID 相同, 並且從伺服器記錄的位移量所指定的資料仍然儲存在主伺服器的複製流緩衝區裡面, 那麼主伺服器會向從伺服器發送斷線時缺失的那部分資料, 然後複製工作可以繼續執行。
● 否則的話, 從伺服器就要執行完整重同步操作。
Redis 2.8 的這個部分重同步特性會用到一個新增的 PSYNC 內部命令, 而 Redis 2.8 以前的舊版本只有 SYNC 命令, 不過, 只要從伺服器是 Redis 2.8 或以上的版本, 它就會根據主伺服器的版本來決定到底是使用 PSYNC 還是 SYNC :
● 如果主伺服器是 Redis 2.8 或以上版本,那麼從伺服器使用 PSYNC 命令來進行同步。
● 如果主伺服器是 Redis 2.8 之前的版本,那麼從伺服器使用 SYNC 命令來進行同步。 配置
配置一個從伺服器非常簡單, 只要在設定檔中增加以下的這一行就可以了:
slaveof 192.168.1.1 6379
當然, 你需要將代碼中的 192.168.1.1 和 6379 替換成你的主伺服器的 IP 和連接埠號碼。
另外一種方法是調用 SLAVEOF 命令, 輸入主伺服器的 IP 和連接埠, 然後同步就會開始:
127.0.0.1:6379> SLAVEOF 192.168.1.1 10086OK
唯讀從伺服器
從 Redis 2.6 開始, 從伺服器支援唯讀模式, 並且該模式為從伺服器的預設模式。
唯讀模式由 redis.conf 檔案中的 slave-read-only 選項控制, 也可以通過 CONFIG SET 命令來開啟或關閉這個模式。
唯讀從伺服器會拒絕執行任何寫命令, 所以不會出現因為操作失誤而將資料不小心寫入到了從伺服器的情況。
即使從伺服器是唯讀, DEBUG 和 CONFIG 等管理式命令仍然是可以使用的, 所以我們還是不應該將伺服器暴露給互連網或者任何不可信網路。 不過, 使用 redis.conf 中的命令改名選項, 我們可以通過禁止執行某些命令來提升唯讀從伺服器的安全性。
你可能會感到好奇, 既然從伺服器上的寫資料會被重同步資料覆蓋, 也可能在從伺服器重啟時丟失, 那麼為什麼要讓一個從伺服器變得可寫呢。
原因是, 一些不重要的臨時資料, 仍然是可以儲存在從伺服器上面的。 比如說, 用戶端可以在從伺服器上儲存主伺服器的可達性(reachability)資訊, 從而實現容錯移轉(failover)策略。 從伺服器相關配置
如果主伺服器通過 requirepass 選項設定了密碼, 那麼為了讓從伺服器的同步操作可以順利進行, 我們也必須為從伺服器進行相應的身分識別驗證設定。
對於一個正在啟動並執行伺服器, 可以使用用戶端輸入以下命令:
config set masterauth <password>
要永久地設定這個密碼, 那麼可以將它加入到設定檔中:
masterauth <password>
另外還有幾個選項, 它們和主伺服器執行部分重同步時所使用的複製流緩衝區有關, 詳細的資訊可以參考 Redis 源碼中附帶的 redis.conf 樣本檔案。 主伺服器在至少N個從伺服器的情況下才執行寫操作
從 Redis 2.8 開始, 為了保證資料的安全性, 可以通過配置, 讓主伺服器只在有至少 N 個當前已串連從伺服器的情況下, 才執行寫命令。
不過, 因為 Redis 使用非同步複製, 所以主伺服器發送的寫資料並不一定會被從伺服器接收到, 因此, 資料丟失的可能性仍然是存在的。
以下是這個特性的運作原理:
● 從伺服器以每秒一次的頻率 PING 主伺服器一次, 並報告複製流的處理情況。
● 主伺服器會記錄各個從伺服器最後一次向它發送 PING 的時間。
● 使用者可以通過配置, 指定網路延遲的最大值 min-slaves-max-lag , 以及執行寫操作所需的至少從伺服器數量 min-slaves-to-write 。
如果至少有 min-slaves-to-write 個從伺服器, 並且這些伺服器的延遲值都少於 min-slaves-max-lag 秒, 那麼主伺服器就會執行用戶端請求的寫操作。
你可以將這個特性看作 CAP 理論中的 C 的條件放寬版本: 儘管不能保證寫操作的持久性, 但起碼遺失資料的視窗會被嚴格限制在指定的秒數中。
另一方面, 如果條件達不到 min-slaves-to-write 和 min-slaves-max-lag 所指定的條件, 那麼寫操作就不會被執行, 主伺服器會向請求執行寫操作的用戶端返回一個錯誤。
以下是這個特性的兩個選項和它們所需的參數:
● min-slaves-to-write
● min-slaves-max-lag
詳細的資訊可以參考 Redis 源碼中附帶的 redis.conf 樣本檔案。