Redis5.x兩種持久化方式以及主從複製配置

關注公衆號:CoderBuff,回覆「redis」獲取《Redis5.x入門教程》完整版PDF。html

配置

redis除了支持多種多樣的存儲類型,還有一點也很是重要,那就是儘管它是基於內存的存儲系統,但它也能進行數據的持久化操做。這一點,對於緩存不幸宕機想恢復緩存數據時至關有效。一樣,咱們實際使用redis時,爲了更高的性能和更高的可用性會將redis配置爲集羣主從模式。本章節重點介紹持久化和主從複製的相關配置。程序員

持久化

redis的持久化有兩種方式:快照持久化(RDB)AOF持久化redis

快照持久化(RDB)

快照持久化,是在某一時刻的全部數據寫入到硬盤中持久化。顯然,這存在一個「什麼時候」寫入硬盤的問題。若是相隔時間過長,那麼剛好在沒有持久化前宕機,這部分數據就會丟失。也就是說,不管如何配置持久化的時機,都有可能存在丟失數據的風險。因此,快照持久化適用於即便丟失一部分數據也不會形成問題的場景緩存

配置快照持久化,既能夠直接經過命令,也能夠經過配置文件的方式。服務器

配置文件

回到咱們redis的安裝位置,根據第一章準備工做,redis安裝在/usr/local/redis-5.0.7路徑,修改redis.conf配置文件。在配置文件中包含了持久化的相關配置、模板插件、lua腳本等等,咱們提取出關於快照持久化相關的配置信息。app

################################ SNAPSHOTTING  ################################

# save [seconds] [changes] 表示在[seconds]秒內有[changes]個鍵值的變化則進行持久化。可同時配置多個,知足一個條件則觸發。
save 900 1				#在900秒內有1次鍵值變化則進行持久化。
save 300 10				#在300秒內有10次鍵值變化則進行持久化。
save 60 10000			#在60秒內有10000次鍵值變化則進行持久化。

stop-writes-on-bgsave-error yes		#當持久化出現錯誤時,是否中止數據寫入,默認中止數據寫入。可配置爲no,當持久化出現錯誤時,仍然能繼續寫入緩存數據。

rdbcompression yes		#是否壓縮數據,默認壓縮。可配置爲no,不壓縮。

rdbchecksum yes				#對持久化rdb文件是否進行校驗,默認校驗。可配置爲no,不校驗。

dbfilename dump.rdb		#指定rdb保存到本地的文件名。

dir ./								#指定rdb保存的目錄,默認在本目錄下,即redis的安裝目錄。

在redis中,持久化默認使用快照持久化方式,若是想要開啓AOF持久化appendonly yes,下文會講AOF持久化的配置。分佈式

注意,儘管這是redis安裝目錄下默認的配置文件,但咱們在啓動時須要制定配置文件的路徑。若是在啓動時使用redis-server則會有如下提示:性能

10768:C 08 Feb 2020 19:52:40.149 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf

因此咱們終止redis服務,並在配置文件中增長一條save 10 1「在10秒內有1次鍵值變化則持久化」配置,指定redis安裝目錄下的配置文件。lua

okevindeMacBook-Air:redis-5.0.7 okevin$ redis-server redis.conf 
14206:C 11 Feb 2020 23:58:52.589 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
14206:C 11 Feb 2020 23:58:52.589 # Redis version=5.0.7, bits=64, commit=00000000, modified=0, pid=14206, just started
14206:C 11 Feb 2020 23:58:52.589 # Configuration loaded

能夠看到,安裝目錄下的配置文件加載成功。操作系統

接下來咱們來驗證redis是不是「在10秒內有1次鍵值變化則持久化」,咱們經過redis-cli進入redis命令行交互,而且寫入一條數據。在redis的啓動窗口出現瞭如下日誌內容:

14234:M 12 Feb 2020 00:02:13.016 * 1 changes in 10 seconds. Saving...
14234:M 12 Feb 2020 00:02:13.017 * Background saving started by pid 14235
14235:C 12 Feb 2020 00:02:13.020 * DB saved on disk
14234:M 12 Feb 2020 00:02:13.121 * Background saving terminated with success

這表示配置生效了。

直接修改配置文件的方式須要重啓redis服務,咱們能夠直接經過命令動態修改配置:

127.0.0.1:6379> config set save "5 1"
OK

此時寫入一條數據,並在redis的啓動窗口驗證:

14206:M 12 Feb 2020 00:04:26.133 * 1 changes in 5 seconds. Saving...
14206:M 12 Feb 2020 00:04:26.134 * Background saving started by pid 14237
14232:C 12 Feb 2020 00:04:26.139 * DB saved on disk
14206:M 12 Feb 2020 00:04:26.238 * Background saving terminated with success

可見,咱們已經動態地修改了快照持久化的配置。不過這種動態配置的方式當在redis重啓後將會失效。

命令

除了經過配置文件的方式快照持久化,咱們還能夠經過命令的方式「隨時」地進行快照持久化,有兩個命令可供使用:bgsavesavebgsave,redis會建立一個子進程,經過子進程將快照寫入硬盤,父進程則繼續處理命令請求。save則是redis在快照建立完成前不會響應其餘命令,也就是阻塞式的,並不經常使用。

在redis客戶端使用bgsave命令:

127.0.0.1:6379> bgsave
Background saving started

在redis服務端的日誌:

14234:M 12 Feb 2020 00:15:11.943 * Background saving started by pid 14245
14245:C 12 Feb 2020 00:15:11.948 * DB saved on disk
14234:M 12 Feb 2020 00:15:12.031 * Background saving terminated with success

在redis客戶端使用save命令:

127.0.0.1:6379> save
OK

在redis服務端的日誌:

14234:M 12 Feb 2020 00:16:12.922 * DB saved on disk

經過redis服務端的日誌咱們就能發現,配置文件中的save配置底層調用的是bgsave命令。那麼何時會用到save命令呢?

那就是在調用shutdown命令時,將會調用save命令阻塞其餘命令,當執行完成後關閉服務器。

在redis客戶端調用shutdown命令:

127.0.0.1:6379> shutdown

在redis服務端的日誌:

14234:M 12 Feb 2020 00:18:52.353 # User requested shutdown...
14234:M 12 Feb 2020 00:18:52.353 * Saving the final RDB snapshot before exiting.
14234:M 12 Feb 2020 00:18:52.356 * DB saved on disk
14234:M 12 Feb 2020 00:18:52.356 * Removing the pid file.
14234:M 12 Feb 2020 00:18:52.357 # Redis is now ready to exit, bye bye...

AOF持久化

AOF持久化的方式和MySQL中binlog主從同步相似,它記錄的是執行的命令,將被執行的寫命令寫入到AOF文件的末尾。它一樣有持久化時機的問題,一般咱們會配置「每秒執行一次同步」。下面咱們仍然經過配置來直觀感覺一下。

配置文件

############################## APPEND ONLY MODE ###############################

appendonly no			#是否開起AOF持久化,默認關閉,yes打開。在redis4.0之前不容許混合使用RDB和AOF,但此後容許使用混合模式,經過最後兩個參數配置。

appendfilename "appendonly.aof"			#AOF持久化數據的文件名。

appendfsync everysec		#執行AOF持久化的頻率,默認「每秒執行一次同步」。還有「always」選項,表示每一個redis命令都要同步寫入硬盤,可是這樣會嚴重減低redis的速度。還有「no」選項,此時持久化的時機將有操做系統決定。redis建議若是你不知道怎麼作,就使用「everysec」配置。

no-appendfsync-on-rewrite no		#默認不重寫AOF文件。

#下面這兩個配置是用於AOF「重寫」觸發條件。當AOF文件的體積大於64m,且AOF文件的體積比上一次重寫以後的體積至少打了一倍(100%)則執行從新命令。
auto-aof-rewrite-percentage 100		
auto-aof-rewrite-min-size 64mb	

aof-load-truncated yes			#指redis在恢復時,會忽略最後一條可能存在問題的指令,默認值yes。

aof-use-rdb-preamble yes		#是否打開RDB和AOF混合模式,默認yes打開。

咱們修改配置文件中appendonly yes即打開AOF持久化,並重啓redis服務。

和快照持久化略微不一樣的是咱們在redis-cli中寫入一條數據後,redis服務端並無記錄AOF的持久化日誌。但咱們在啓動時,會出現從AOF文件中加載數據。

15336:M 12 Feb 2020 14:21:42.541 # Server initialized
15336:M 12 Feb 2020 14:21:42.542 * DB loaded from append only file: 0.001 seconds
15336:M 12 Feb 2020 14:21:42.542 * Ready to accept connections

若是咱們此時關閉redis服務端再啓動,因爲咱們開啓了持久化因此仍然能獲取到剛剛寫入的值。

和快照持久化相同,咱們一樣能在命令行中經過config set appendonly "yes"動態修改配置文件。

在前面的配置文件中,咱們提到了「重寫」這個術語,它其實是針對AOF文件過大,須要覆蓋掉以前的AOF文件的配置。它和bgsave相似,都是經過一個子進程操做。

主從複製

對於一個使用了redis的大型應用程序,爲了保證redis的性能,咱們會配置redis集羣。同MySQL相似,redis的主服務器(master)也會向多個從服務器(slave)發送更新。主服務器負責寫、從服務器負責讀,以提升性能。

這一小節,我會找到另一臺mac實體機在同一局域網內實現redis主從複製,固然你也能夠在虛擬機中試驗。

修改master主服務器的配置文件(爲了更好演示主從複製,將盡量作更少的配置):

#bind 127.0.0.1			#默認只容許本機鏈接redis服務,因此須要註釋掉這行配置。
protected-mode no		#默認打開了保護模式,這裏咱們配置爲no關閉。
daemonize no				#實際應用中,咱們是一般是將redis之後臺運行,也就是會配置爲yes,默認是no表示不之後臺運行。咱們在這裏保持默認的配置,方便查看相關的運行日誌。

修改slave從服務器的配置文件(只比master多一行配置):

#bind 127.0.0.1			#默認只容許本機鏈接redis服務,因此須要註釋掉這行配置。
protected-mode no		#默認打開了保護模式,這裏咱們配置爲no關閉。
daemonize no				#實際應用中,咱們是一般是將redis之後臺運行,也就是會配置爲yes,默認是no表示不之後臺運行。咱們在這裏保持默認的配置,方便查看相關的運行日誌。

slaveof 192.168.31.125 6379

咱們先啓動master主服務器顯示如下信息:

okevindeMacBook-Air:redis-5.0.7 okevin$ redis-server redis.conf 
15702:C 12 Feb 2020 22:18:24.777 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
15702:C 12 Feb 2020 22:18:24.778 # Redis version=5.0.7, bits=64, commit=00000000, modified=0, pid=15702, just started
15702:C 12 Feb 2020 22:18:24.778 # Configuration loaded
15702:M 12 Feb 2020 22:18:24.781 * Increased maximum number of open files to 10032 (it was originally set to 2560).
                _._                                                  
           _.-``__ ''-._                                             
      _.-``    `.  `_.  ''-._           Redis 5.0.7 (00000000/0) 64 bit
  .-`` .-```.  ```\/    _.,_ ''-._                                   
 (    '      ,       .-`  | `,    )     Running in standalone mode
 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379
 |    `-._   `._    /     _.-'    |     PID: 15702
  `-._    `-._  `-./  _.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |           http://redis.io        
  `-._    `-._`-.__.-'_.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |                                  
  `-._    `-._`-.__.-'_.-'    _.-'                                   
      `-._    `-.__.-'    _.-'                                       
          `-._        _.-'                                           
              `-.__.-'                                               

15702:M 12 Feb 2020 22:18:24.801 # Server initialized
15702:M 12 Feb 2020 22:18:24.803 * DB loaded from append only file: 0.002 seconds
15702:M 12 Feb 2020 22:18:24.803 * Ready to accept connections

再啓動slave從服務器顯示如下信息:

t4f-mbp-17346:redis-5.0.7 yulinfeng$ redis-server redis.conf 
13801:C 12 Feb 2020 22:20:08.954 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
13801:C 12 Feb 2020 22:20:08.954 # Redis version=5.0.7, bits=64, commit=00000000, modified=0, pid=13801, just started
13801:C 12 Feb 2020 22:20:08.954 # Configuration loaded
13801:S 12 Feb 2020 22:20:08.955 * Increased maximum number of open files to 10032 (it was originally set to 256).
                _._                                                  
           _.-``__ ''-._                                             
      _.-``    `.  `_.  ''-._           Redis 5.0.7 (00000000/0) 64 bit
  .-`` .-```.  ```\/    _.,_ ''-._                                   
 (    '      ,       .-`  | `,    )     Running in standalone mode
 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379
 |    `-._   `._    /     _.-'    |     PID: 13801
  `-._    `-._  `-./  _.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |           http://redis.io        
  `-._    `-._`-.__.-'_.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |                                  
  `-._    `-._`-.__.-'_.-'    _.-'                                   
      `-._    `-.__.-'    _.-'                                       
          `-._        _.-'                                           
              `-.__.-'                                               

13801:S 12 Feb 2020 22:20:08.956 # Server initialized
13801:S 12 Feb 2020 22:20:08.956 * Ready to accept connections
13801:S 12 Feb 2020 22:20:08.957 * Connecting to MASTER 192.168.31.145:6379
13801:S 12 Feb 2020 22:20:08.965 * MASTER <-> REPLICA sync started
13801:S 12 Feb 2020 22:20:09.030 * Non blocking connect for SYNC fired the event.
13801:S 12 Feb 2020 22:20:09.034 * Master replied to PING, replication can continue...
13801:S 12 Feb 2020 22:20:09.039 * Partial resynchronization not possible (no cached master)
13801:S 12 Feb 2020 22:20:09.043 * Full resync from master: b7b0b93ea396930cc622250b959fd9eb8eb71c5f:0
13801:S 12 Feb 2020 22:20:09.138 * MASTER <-> REPLICA sync: receiving 185 bytes from master
13801:S 12 Feb 2020 22:20:09.139 * MASTER <-> REPLICA sync: Flushing old data
13801:S 12 Feb 2020 22:20:09.139 * MASTER <-> REPLICA sync: Loading DB in memory
13801:S 12 Feb 2020 22:20:09.139 * MASTER <-> REPLICA sync: Finished with success

能夠看到從服務器在啓動完成後多了一些日誌,第一行MASTER <-> REPLICA sync started向主服務器發送了同步的命令,一直到最後同步成功。

咱們回到master主服務的日誌:

15702:M 12 Feb 2020 22:20:09.010 * Replica 192.168.31.215:6379 asks for synchronization
15702:M 12 Feb 2020 22:20:09.010 * Full resync requested by replica 192.168.31.215:6379
15702:M 12 Feb 2020 22:20:09.010 * Starting BGSAVE for SYNC with target: disk
15702:M 12 Feb 2020 22:20:09.011 * Background saving started by pid 15703
15703:C 12 Feb 2020 22:20:09.014 * DB saved on disk
15702:M 12 Feb 2020 22:20:09.106 * Background saving terminated with success
15702:M 12 Feb 2020 22:20:09.106 * Synchronization with replica 192.168.31.215:6379 succeeded

能夠看到,第一行表示有一臺從服務器正在請求同步,而且觀察日誌能夠發現主服務器此時執行了bgsave命令進行了一次持久化操做。

此時,當咱們在主服務寫入一條數據時,在從服務器就能夠讀取到了。可是,若是咱們在從服務器寫入數據時會出現如下錯誤:

127.0.0.1:6379> set slave master
(error) READONLY You cant't write against a read only replica.

回顧主從複製中的一些細節,除了配置文件須要有注意的地方,在底層當從服務器鏈接到主服務器時會發送一條sync同步命令,當主服務器接收到從服務器的sync同步命令後,會在主服務器中執行bgsave持久化命令,執行完成後將向從服務器發送一份快照持久化的文件以完成同步。而且從服務器是隻讀不能寫入的。

關注公衆號:CoderBuff,回覆「redis」獲取《Redis5.x入門教程》完整版PDF。

這是一個能給程序員加buff的公衆號 (CoderBuff)
相關文章
相關標籤/搜索