前言web
在上一篇文章中,介紹了Redis的內存模型,從這篇文章開始,將依次介紹Redis高可用相關的知識——持久化、複製(及讀寫分離)、哨兵、以及集羣。redis
本文將先說明上述幾種技術分別解決了Redis高可用的什麼問題;而後詳細介紹Redis的持久化技術,主要是RDB和AOF兩種持久化方案;在介紹RDB和AOF方案時,不只介紹其做用及操做方法,同時介紹持久化實現的一些原理細節及須要注意的問題。最後,介紹在實際使用中,持久化方案的選擇,以及常常遇到的問題等。數據庫
1、Redis高可用概述安全
在介紹Redis高可用以前,先說明一下在Redis的語境中高可用的含義。服務器
咱們知道,在web服務器中,高可用是指服務器能夠正常訪問的時間,衡量的標準是在多長時間內能夠提供正常服務(99.9%、99.99%、99.999% 等等)。可是在Redis語境中,高可用的含義彷佛要寬泛一些,除了保證提供正常服務(如主從分離、快速容災技術),還須要考慮數據容量的擴展、數據安全不會丟失等。負載均衡
在Redis中,實現高可用的技術主要包括持久化、複製、哨兵和集羣,下面分別說明它們的做用,以及解決了什麼樣的問題。函數
持久化:持久化是最簡單的高可用方法(有時甚至不被歸爲高可用的手段),主要做用是數據備份,即將數據存儲在硬盤,保證數據不會因進程退出而丟失。
複製:複製是高可用Redis的基礎,哨兵和集羣都是在複製基礎上實現高可用的。複製主要實現了數據的多機備份,以及對於讀操做的負載均衡和簡單的故障恢復。缺陷:故障恢復沒法自動化;寫操做沒法負載均衡;存儲能力受到單機的限制。
哨兵:在複製的基礎上,哨兵實現了自動化的故障恢復。缺陷:寫操做沒法負載均衡;存儲能力受到單機的限制。
集羣:經過集羣,Redis解決了寫操做沒法負載均衡,以及存儲能力受到單機限制的問題,實現了較爲完善的高可用方案。
2、Redis 持久化概述日誌
持久化的功能:Redis是內存數據庫,數據都是存儲在內存中,爲了不進程退出致使數據的永久丟失,須要按期將Redis中的數據以某種形式(數據或命令)從內存保存到硬盤;當下次Redis重啓時,利用持久化文件實現數據恢復。除此以外,爲了進行災難備份,能夠將持久化文件拷貝到一個遠程位置。server
Redis持久化分爲RDB持久化和AOF持久化:前者將當前數據保存到硬盤,後者則是將每次執行的寫命令保存到硬盤(相似於MySQL的binlog);因爲AOF持久化的實時性更好,即當進程意外退出時丟失的數據更少,所以AOF是目前主流的持久化方式,不過RDB持久化仍然有其用武之地。進程
下面依次介紹RDB持久化和AOF持久化;因爲Redis各個版本之間存在差別,如無特殊說明,以Redis3.0爲準。
3、RDB持久化
RDB持久化是將當前進程中的數據生成快照保存到硬盤(所以也稱做快照持久化),保存的文件後綴是rdb;當Redis從新啓動時,能夠讀取快照文件恢復數據。
RDB持久化的觸發分爲手動觸發和自動觸發兩種。
1) 手動觸發
save命令和bgsave命令均可以生成RDB文件。
save命令會阻塞Redis服務器進程,直到RDB文件建立完畢爲止,在Redis服務器阻塞期間,服務器不能處理任何命令請求。
而bgsave命令會建立一個子進程,由子進程來負責建立RDB文件,父進程(即Redis主進程)則繼續處理請求。
此時服務器執行日誌以下:
bgsave命令執行過程當中,只有fork子進程時會阻塞服務器,而對於save命令,整個過程都會阻塞服務器,所以save已基本被廢棄,線上環境要杜絕save的使用;後文中也將只介紹bgsave命令。此外,在自動觸發RDB持久化時,Redis也會選擇bgsave而不是save來進行持久化;下面介紹自動觸發RDB持久化的條件。
2) 自動觸發
save m n
自動觸發最多見的狀況是在配置文件中經過save m n,指定當m秒內發生n次變化時,會觸發bgsave。
例如,查看redis的默認配置文件(Linux下爲redis根目錄下的redis.conf),能夠看到以下配置信息:
其中save 900 1的含義是:當時間到900秒時,若是redis數據發生了至少1次變化,則執行bgsave;save 300 10和save 60 10000同理。當三個save條件知足任意一個時,都會引發bgsave的調用。
save m n的實現原理
Redis的save m n,是經過serverCron函數、dirty計數器、和lastsave時間戳來實現的。
serverCron是Redis服務器的週期性操做函數,默認每隔100ms執行一次;該函數對服務器的狀態進行維護,其中一項工做就是檢查 save m n 配置的條件是否知足,若是知足就執行bgsave。
dirty計數器是Redis服務器維持的一個狀態,記錄了上一次執行bgsave/save命令後,服務器狀態進行了多少次修改(包括增刪改);而當save/bgsave執行完成後,會將dirty從新置爲0。
例如,若是Redis執行了set mykey helloworld,則dirty值會+1;若是執行了sadd myset v1 v2 v3,則dirty值會+3;注意dirty記錄的是服務器進行了多少次修改,而不是客戶端執行了多少修改數據的命令。
lastsave時間戳也是Redis服務器維持的一個狀態,記錄的是上一次成功執行save/bgsave的時間。
save m n的原理以下:每隔100ms,執行serverCron函數;在serverCron函數中,遍歷save m n配置的保存條件,只要有一個條件知足,就進行bgsave。對於每個save m n條件,只有下面兩條同時知足時纔算知足:
(1)當前時間-lastsave > m
(2)dirty >= n