簡介
本文簡要介紹Redis持久化與數(shù)據(jù)庫持久化的區(qū)別,主要參考Redis作者的blog(見下文參考文獻);在數(shù)據(jù)庫部分中,本文詳細調研了MySQL的實現(xiàn)方式進行補充。
數(shù)據(jù)庫寫操作
原文中介紹數(shù)據(jù)庫在進行寫操作時到底做了哪些事,主要有下面五個過程。
- 客戶端向服務端發(fā)送寫操作(數(shù)據(jù)在客戶端的內存中)
- 數(shù)據(jù)庫服務端接收到寫請求的數(shù)據(jù)(數(shù)據(jù)在服務端的內存中)
- 服務端調用write(2) 這個系統(tǒng)調用,將數(shù)據(jù)往磁盤上寫(數(shù)據(jù)在系統(tǒng)內存的緩沖區(qū)中)
- 操作系統(tǒng)將緩沖區(qū)中的數(shù)據(jù)轉移到磁盤控制器上(數(shù)據(jù)在磁盤緩存中)
- 磁盤控制器將數(shù)據(jù)寫到磁盤的物理介質中(數(shù)據(jù)真正落到磁盤上)
依據(jù)MySQL官網介紹,InnoDB的寫文件過程正是上述過程,又稱 Doublewrite Buffer;這樣做的好處是:
在崩潰或斷電后增加了恢復的安全性,并通過減少對fsync()操作的需求,提高了Unix大多數(shù)品種的性能。
Redis中RDB持久化
Redis支持將當前數(shù)據(jù)的快照存成一個數(shù)據(jù)文件的持久化機制。Redis借助了fork命令的copy on write機制。在生成快照時,將當前進程fork出一個子進程,然后在子進程中循環(huán)所有的數(shù)據(jù),將數(shù)據(jù)寫成為RDB文件。
我們可以通過Redis的save指令來配置RDB快照生成的時機,比如你可以配置當10分鐘以內有100次寫入就生成快照,也可以配置當1小時內有1000次寫入就生成快照,也可以多個規(guī)則一起實施。這些規(guī)則的定義就在Redis的配置文件中,你也可以通過Redis的CONFIG SET命令在Redis運行時設置規(guī)則,不需要重啟Redis。
RDB的不足,就是一旦數(shù)據(jù)庫出現(xiàn)問題,RDB文件中保存的數(shù)據(jù)并不是全新的,從上次RDB文件生成到Redis停機這段時間的數(shù)據(jù)全部丟掉了。
Redis中AOF持久化
AOF日志的全稱是Append Only File,它是一個追加寫入的日志文件。與一般數(shù)據(jù)庫的binlog不同的是,AOF文件是可識別的純文本,它的內容就是一個個的Redis標準命令。
AOF重寫
隨著Redis執(zhí)行命令的增加,AOF文件會越來越大,故Redis又提供了一個功能:AOF rewrite。其功能就是重新生成一份AOF文件,新的AOF文件中一條記錄的操作只會有一次,而不像一份老文件那樣,可能記錄了對同一個值的多次操作。其生成過程和RDB類似,也是fork一個進程,直接遍歷數(shù)據(jù),寫入新的AOF臨時文件。在寫入新文件的過程中,所有的寫操作日志還是會寫到原來老的AOF文件中,同時還會記錄在內存緩沖區(qū)中。當重完操作完成后,會將所有緩沖區(qū)中的日志一次性寫入到臨時文件中。然后調用原子性的rename命令用新的AOF文件取代老的AOF文件。
數(shù)據(jù)導入
Redis是一個內存數(shù)據(jù)庫,無論是RDB還是AOF,都只是其保證數(shù)據(jù)恢復的措施;故Redis在利用RDB和AOF進行恢復的時候,都會讀取RDB或AOF文件,重新加載到內存中。相對于MySQL等數(shù)據(jù)庫的啟動時間來說,會長很多,因為MySQL本來是不需要將數(shù)據(jù)加載到內存中的。
在利用RDB和利用AOF啟動上,其啟動時間有一些差別。RDB的啟動時間會更短,原因有兩個,一是RDB文件中每一條數(shù)據(jù)只有一條記錄,不會像AOF日志那樣可能有一條數(shù)據(jù)的多次操作記錄。所以每條數(shù)據(jù)只需要寫一次就行了。另一個原因是RDB文件的存儲格式和Redis數(shù)據(jù)在內存中的編碼格式是一致的,不需要再進行數(shù)據(jù)編碼工作。在CPU消耗上要遠小于AOF日志的加載。