衆所周知,redis是內存數據庫,它把數據存儲在內存中,這樣在加快讀取速度的同時也對數據安全性產生了新的問題,即當redis所在服務器發生宕機後,redis數據庫裏的全部數據將會所有丟失。mysql
爲了解決這個問題,redis提供了持久化功能——RDB和AOF。通俗的講就是將內存中的數據寫入硬盤中。redis
1、持久化之全量寫入:RDBsql
[redis@6381]$ more /usr/local/redis/conf/redis.conf save 900 1 save 300 10 save 60 10000 dbfilename "dump.rdb" #持久化文件名稱 dir "/data/dbs/redis/6381" #持久化數據文件存放的路徑
上面是redis配置文件裏默認的RDB持久化設置,前三行都是對觸發RDB的一個條件,例如第一行的意思是每900秒鐘裏redis數據庫有一條數據被修改則觸發RDB,依次類推;只要有一條知足就會調用BGSAVE進行RDB持久化。第四行dbfilename指定了把內存裏的數據庫寫入本地文件的名稱,該文件是進行壓縮後的二進制文件,經過該文件能夠把數據庫還原到生成該文件時數據庫的狀態。第五行dir指定了RDB文件存放的目錄。數據庫
配置文件修改須要重啓redis服務,咱們還能夠在命令行裏進行配置,即時生效,服務器重啓後需從新配置緩存
[redis@iZ254r8s3m6Z redis]$ bin/redis-cli 127.0.0.1:6379> CONFIG GET save #查看redis持久化配置 1) "save" 2) "900 1 300 10 60 10000" 127.0.0.1:6379> CONFIG SET save "21600 1000" #修改redis持久化配置 OK
而RDB持久化也分兩種:SAVE和BGSAVE安全
SAVE是阻塞式的RDB持久化,當執行這個命令時redis的主進程把內存裏的數據庫狀態寫入到RDB文件(即上面的dump.rdb)中,直到該文件建立完畢的這段時間內redis將不能處理任何命令請求。服務器
BGSAVE屬於非阻塞式的持久化,它會建立一個子進程專門去把內存中的數據庫狀態寫入RDB文件裏,同時主進程還能夠處理來自客戶端的命令請求。但子進程基本是複製的父進程,這等於兩個相同大小的redis進程在系統上運行,會形成內存使用率的大幅增長。app
(本人在生產中就碰到過這問題,redis自己內存使用率就60%,總的內存使用率在百分之七八十左右,持久化的時候立馬飆到百分之一百三十多,告警郵件是天天幾十封/(ㄒoㄒ)/~~ 最後根據需求選擇了AOF持久化)spa
2、持久化之增量寫入:AOF操作系統
與RDB的保存整個redis數據庫狀態不一樣,AOF是經過保存對redis服務端的寫命令(如set、sadd、rpush)來記錄數據庫狀態的,即保存你對redis數據庫的寫操做,如下就是AOF文件的內容
1 [redis@iZ]$ more appendonly.aof 2 *2 3 $6 4 SELECT 5 $1 6 0 7 *3 8 $3 9 SET 10 $47 11 DEV_USER_LEGAL_F9683BE0E27F1A06C0CB869CEC7E3B22 12 $11 13 ¬ 14 *3 15 $3 16 SET 17 $47
先讓咱們看看如何配置AOF
1 [redis@iZ]$ more ~/redis/conf/redis.conf 2 dir "/data/dbs/redis/6381" #AOF文件存放目錄 3 appendonly yes #開啓AOF持久化,默認關閉 4 appendfilename "appendonly.aof" #AOF文件名稱(默認) 5 appendfsync no #AOF持久化策略 6 auto-aof-rewrite-percentage 100 #觸發AOF文件重寫的條件(默認) 7 auto-aof-rewrite-min-size 64mb #觸發AOF文件重寫的條件(默認)
要弄明白上面幾個配置就得從AOF的實現去理解,AOF的持久化是經過命令追加、文件寫入和文件同步三個步驟實現的。當reids開啓AOF後,服務端每執行一次寫操做(如set、sadd、rpush)就會把該條命令追加到一個單獨的AOF緩衝區的末尾,這就是命令追加;而後把AOF緩衝區的內容寫入AOF文件裏。看上去第二步就已經完成AOF持久化了那第三步是幹什麼的呢?這就須要從系統的文件寫入機制提及:通常咱們如今所使用的操做系統,爲了提升文件的寫入效率,都會有一個寫入策略,即當你往硬盤寫入數據時,操做系統不是實時的將數據寫入硬盤,而是先把數據暫時的保存在一個內存緩衝區裏,等到這個內存緩衝區的空間被填滿或者是超過了設定的時限後纔會真正的把緩衝區內的數據寫入硬盤中。也就是說當redis進行到第二步文件寫入的時候,從用戶的角度看是已經把AOF緩衝區裏的數據寫入到AOF文件了,但對系統而言只不過是把AOF緩衝區的內容放到了另外一個內存緩衝區裏而已,以後redis還須要進行文件同步把該內存緩衝區裏的數據真正寫入硬盤上纔算是完成了一次持久化。而什麼時候進行文件同步則是根據配置的appendfsync來進行:
appendfsync有三個選項:always、everysec和no:
一、選擇always的時候服務器會在每執行一個事件就把AOF緩衝區的內容強制性的寫入硬盤上的AOF文件裏,能夠當作你每執行一個redis寫入命令就往AOF文件裏記錄這條命令,這保證了數據持久化的完整性,但效率是最慢的,卻也是最安全的;
二、配置成everysec的話服務端每執行一次寫操做(如set、sadd、rpush)也會把該條命令追加到一個單獨的AOF緩衝區的末尾,並將AOF緩衝區寫入AOF文件,而後每隔一秒纔會進行一次文件同步把內存緩衝區裏的AOF緩存數據真正寫入AOF文件裏,這個模式兼顧了效率的同時也保證了數據的完整性,即便在服務器宕機也只會丟失一秒內對redis數據庫作的修改;
三、將appendfsync配置成no則意味redis數據庫裏的數據就算丟失你也能夠接受,它也會把每條寫命令追加到AOF緩衝區的末尾,而後寫入文件,但何時進行文件同步真正把數據寫入AOF文件裏則由系統自身決定,即當內存緩衝區的空間被填滿或者是超過了設定的時限後系統自動同步。這種模式下效率是最快的,但對數據來講也是最不安全的,若是redis裏的數據都是從後臺數據庫如mysql中取出來的,屬於隨時能夠找回或者不重要的數據,那麼能夠考慮設置成這種模式。
相比RDB每次持久化都會內存翻倍,AOF持久化除了在第一次啓用時會新開一個子進程建立AOF文件會大幅度消耗內存外,以後的每次持久化對內存使用都很小。但AOF也有一個不可忽視的問題:AOF文件過大。你對redis數據庫的每一次寫操做都會讓AOF文件裏增長一條數據,長此以往這個文件會造成一個龐然大物。還好的是redis提出了AOF重寫的機制,即咱們上面配置的auto-aof-rewrite-percentage和auto-aof-rewrite-min-size。AOF重寫機制這裏暫不細述,以後本人會另開博文對此解釋,有興趣的同窗能夠看看。咱們只要知道AOF重寫既是從新建立一個精簡化的AOF文件,裏面去掉了多餘的冗餘命令,並對原AOF文件進行覆蓋。這保證了AOF文件大小處於讓人能夠接受的地步。而上面的auto-aof-rewrite-percentage和auto-aof-rewrite-min-size配置觸發AOF重寫的條件。
Redis 會記錄上次重寫後AOF文件的文件大小,而當前AOF文件大小跟上次重寫後AOF文件大小的百分比超過auto-aof-rewrite-percentage設置的值,同時當前AOF文件大小也超過auto-aof-rewrite-min-size設置的最小值,則會觸發AOF文件重寫。以上面的配置爲例,當如今的AOF文件大於64mb同時也大於上次重寫AOF後的文件大小,則該文件就會被AOF重寫。
最後須要注意的是,若是redis開啓了AOF持久化功能,那麼當redis服務重啓時會優先使用AOF文件來還原數據庫。