redis作為當下web程式設計必不可少的服務,它的特點的是顯而易見,相對memcached而言,做緩存,重啟資料不遺失,非常好用。那麼問題來了,它是怎麼做到的呢?
RDB
RDB就是持久化的一種手段,把記憶體中資料在某些條件下寫到磁碟中去。那麼在哪些條件下寫入呢?不可能無腦寫入,來一個寫一個,影響性能,也不能等老半天才寫一個,萬一中間宕機了,數據全丟失,還不如用memcached。在redis的配置裡有著這樣的一段配置:
save 900 1
save 300 10
save 60 10000
很關鍵的一段配置,這時RDB持久化的核心。意思是:
1.如果900秒時,有1個key變化(插入或更新),我就同步到磁碟一下
2.如果300秒時,有10個key變化(插入或更新),我就同步到磁碟一下
3.如果60秒時,有10000個key變化(插入或更新),我就同步到磁碟一下
#這些時間點和變化的數量是怎麼知道的,這時有另外兩個極為關鍵的東西,一個叫dirty計數器,一個叫lastsave(上次save的時間),dirty計數器專門記錄從上次save後變化key的數量,lastsave記錄執行save的時間,舉個例子剛開始時間是time1,dirty是0,這時有20個key發生了變化,dirty是20,然後現在的時間是time2,time2-time1 > ;= 300,滿足第二個條件,這時記憶體中的資料會save一下,同時dirty清為0,然後再等待條件觸發。
如果我60秒內有10萬個key,那麼問題來了,一下大量磁碟io來臨,這時redis主進程就會阻塞,期間的所有的命令都不執行,這哪能行,於是就來了一個叫bgsave的,它是redis主進程fork出來的一個子進程,專門執行rdb的持久化工作的。
儲存的檔案格式是二進位格式的,萬一資料庫宕機,復原不需要人為幹預,redis會自動讀取磁碟檔案。
AOF
與RDB不同,AOF儲存的是你執行的指令,當aof功能開啟的時候,執行的更新指令不會直接寫到aof文件中去,而是先寫到一個aof buf中,我們知道不能一直往buf中寫,buf也是內存啊,那麼何時才能同步到磁碟中去呢? redis中也有這樣一段配置
appendfsync always
appendfsync everysec
appendfsync no
##意思是:1.只要有更新的命令我就同步2.如果上次同步時間距離現在超過一秒就同步3.不同步,等待作業系統自己判斷(什麼時候有空我才同步)分析下,第一種io頻繁,io壓力大,但丟失數據的機率最小,第二種io壓力不是很大,最多也就丟失1秒左右的數據,第三中io壓力很小,遺失資料機率太大。綜合考慮,一般第二種。但還有個問題,我執行了100次INCR num,依道理num就是100,aof中也有100個同樣的指令,沒毛病,那麼請問執行100次INCR num和SET num 100有什麼差別,同樣的結果前者多了99倍的空間,很浪費啊,於是就出現了AOF重寫,它是怎麼做到的。很簡單:先從資料庫讀取現在的值,再用一筆記錄代替,這就是AOF重寫的原理。重寫很花時間,所以也是子進程來處理。重寫的過程中,如果有新的命令來臨怎麼辦,老辦法,寫buf緩衝,重寫完成後,把buf中的命令追加到新的aof中,然後用新的aof替代老的aof,就實現了重寫。 本文來自redis教學,歡迎學習。
以上是redis怎麼實現持久化的詳細內容。更多資訊請關注PHP中文網其他相關文章!