接觸redis並不久,作項目的時候,也大概的操做罷了,好比set,get..~等等的基礎操做,大概小嘍囉是夠用了java
最近大佬問我,你的redis數據有作持久化嗎?redis
個人想法..~ 設置了有效時間的key是未持久化的,永久的key就是持久化的數據庫
大佬一個勁的在嘲笑,尷尬... 偷偷笑,有我這麼想.確定還有人起步也這麼認爲的,哈哈哈數組
因而學習一下redis 持久化相關知識安全
Redis之因此速度這麼快,是由於Redis是基於內存的數據庫,進行讀寫操做時,redis都會在內存中完成,而後定時的刷新到磁盤中去,RDB和AOF就是兩種持久化內存中數據的方式bash
在硬盤中數據是持久化的,重啓機子也會存在服務器
在內存中數據不是持久化的,重啓機子就沒了網絡
根據一段本身寫的redis操做的代碼來學習,這邊使用的是Jedis(Java鏈接開發工具),來一段最簡單的setapp
/** * set 字節數組 * * @param key 字節key * @param value 字節value * @return OK */ public String set(byte[] key, byte[] value) { Jedis jedis = null; String result = null; try { jedis = getJedis(); result = jedis.set(key, value); } catch (Exception e) { log.error("set byte[] key:{} value:{} error", key, value, e); } finally { returnSource(jedis); } return result; }
redis 會把自身的數據以文件形式保存到硬盤中一份,在服務器重啓以後會自動把硬盤數據恢復到內存中
操做是一次性把redis中所有的數據保存一份到硬盤中,因此若是數據大的話,不太適合頻繁進行該操做async
默認文件名dump.rdb 能夠在redis.conf中設置
第1種. redis客戶端發送的save命令進行快照,會阻塞(代碼中須要調用jedis.save()的方法實現)
阻塞redis服務器的進程,直到RDB文件建立完,在該段時間內,redis不能處理其餘的命令
第2種. redis客戶端發送的bgsave命令,不阻塞(代碼中須要調用jedis.bgsave()的方法實現)
實際執行過程:
主進程和子進程是同時存在的, 不會阻塞redis服務器進程, 建立子進程會消耗額外的內存,因此bgsave比save要慢
第3種. redis根據redis.conf中的配置自動執行bgsave
save 900 1 #900秒以內修改了1次,則執行 save 300 10 #300秒以內修改了10次,則執行 save 60 10000 #60秒以內修改了10000次,則執行
服務器每次執行以後,爲實現自動持久化而設置的時間計數器和次數計數器就會清零,從新計算
在redis命令執行config get save查看redis的save配置
可用jedis.lastsave()命令查看生成RDB文件是否成功, 返回上次成功保存到磁盤的unix時間戳(save和bgsave都會修改時間) ,RDB文件每次都是覆蓋,須要控制備份的話,要定時定點另存備份
從上面學習過程當中,得出主動方式應該選擇使用bgsave的方式來持久化
public void bgsave() { Jedis jedis = null; try { jedis = getJedis(); jedis.bgsave(); } catch (Exception e) { log.error("bgsave error", e); } finally { returnSource(jedis); } }
給本身的工具類加個bgsave持久化方法,另外嘗試過程過遇到若是在一個Java方法中調兩次save或者bgsave是會報錯的,因此持久化單提出來,可能一個方法有好幾個redis操做
總結:
1.bgsave子線程建立RDB文件,不會對redis服務器性能形成大的影響
2.快照生成的RDB文件是一種壓縮的二進制文件,能夠方便的在網絡中傳輸和保存
3.在一次備份完RDB以後產生了新數據,但還未到達另外一次生成RDB文件的條件,這時redis服務器宕機,那麼新的數據會丟失掉
4.數據量大的時,觸發RDB持久化,包括建立子線程和生成RDB文件會佔很多系統資源和時間,會對redis產生影響
把操做執行的每一個指令都備份到aof文件中,還原數據的時候執行指令 , 每次在後面追加
aop重寫(不阻塞), redis.conf對應 appendonly yes 開啓aof
appendfilename "appendonly.aof" //備份文件名 appendfsync always //每次收到寫命令就當即寫入磁盤,最慢的方式,可是保證徹底的持久化 appendfsync everysec //每秒鐘強烈寫入磁盤一次,在性能和持久化方面很好的折中,默認 appendfsync no //不一樣步到硬盤,由操做系統來決定
aof生成過程三個步驟:redis在執行完一個寫命令後,把執行的命令追加到redis內部的aof_buf緩衝區末尾
調用調用fsync函數, 緩衝區的寫命令會被寫入到 AOF 文件, 完成同步
在目前操做系統裏,執行系統調用write函數,將一些內容寫入到某個文件時, 先將內容放入一個內存緩衝區(buffer)裏面,等到緩衝區被填滿,或者用戶執行fsync調用和fdatasync調用時纔將存儲在緩衝區裏面的內容真正的寫入到硬盤裏,那麼在這個過程當中出問題了,數據是否就丟了?!
總結:
使用 AOF 持久化會讓 Redis 變得很是耐久:你能夠設置不一樣的 fsync策略,好比無 fsync,每秒鐘一次 fsync ,或者每次執行寫入命令時 fsync 。 AOF 的默認策略爲每秒鐘 fsync一次,在這種配置下,Redis 仍然能夠保持良好的性能,而且就算髮生故障停機,也最多隻會丟失一秒鐘的數據
aof文件由於某些緣由而包含了未寫入完整的命令redis-check-aof 工具也能夠輕易地修復這種問題
Redis 能夠在 AOF 文件體積變得過大時,自動地在後臺對 AOF 進行重寫: 重寫後的新 AOF 文件包含了恢復當前數據集所需的最小命令集合。 整個重寫操做是絕對安全的,由於 Redis 在建立新 AOF 文件的過程當中,會繼續將命令追加到現有的 AOF 文件裏面,即便重寫過程當中發生停機,現有的 AOF 文件也不會丟失。 而一旦新 AOF 文件建立完畢,Redis 就會從舊 AOF 文件切換到新 AOF 文件,並開始對新 AOF 文件進行追加操做
AOF文件可讀性交強,也可手動操做寫命令
AOF文件比RDB文件較大
官方文檔也指出,在某些狀況下,AOF的確也存在一些bug,好比使用阻塞命令時,這些bug的場景RDB是不存在的
------------------------------------