a)保存
1.將客戶端請求的命令轉換爲網絡協議格式
2.將協議內容字符串追加到變量server.aof_buf中
3.當AOF系統達到設定的條件時,會調用aof_fsync(文件描述符號)將數據寫入磁盤
其中第三步提到的設定條件,就是AOF性能的關鍵點。目前Redis支持三種保存條件機制:
1.AOF_FSYNC_NO:不保存
此模式下,每執行一條客戶端的命令,都會將協議字符串追加到server.aof_buf中,但不會執行寫入磁盤。
寫入只發生在:
1.Redis被正常關閉;
2.Aof功能關閉;
3.系統寫緩存已滿,或後臺定時保存操做被執行
上面三種狀況都會阻塞主進程,致使客戶端請求失敗。
2.AOF_FSYNC_EVERYSECS:每一秒保存一次
由後臺子進程調用寫入保存,不會阻塞主進程。若是發生宕機,那麼最大丟失數據會在2s之內的數據。
這也是默認的設置選項。
3.AOF_FSYNC_ALWAYS:每執行一個命令都保存一次
這種模式下,能夠保證每一條客戶端指令都被保存,保證數據不會丟失。但缺點就是性能大大降低,由於每一次操做都是獨佔性的,須要阻塞主進程。
b)讀取
AOF保存的是數據協議格式的數據,因此只要將AOF中的數據轉換爲命令,模擬客戶端從新執行一遍,就能夠還原全部數據庫狀態。
讀取的過程是:
1.建立模擬的客戶端
2.讀取AOF保存的文本,還原數據爲原命令和原參數。而後使用模擬的客戶端發出這個命令請求。
3.繼續執行第二步,直到讀取完AOF文件
AOF須要將全部的命令都保存到磁盤,那麼這個文件會隨着時間變得愈來愈大。讀取也會變得很慢。Redis提供了AOF的重寫機制,幫助減小文件的大小。
實現的思路是:
LPUSH list 1 2 3 4 5
LPOP list
LPOP list
LPUSH list 1
最初保存到AOF文件的將會是四條指令。但通過AOF重寫後,會變成一條指令:redis
同時,考慮到爲了在AOF重寫時,不影響AOF的寫入增長了AOF重寫緩存的概念。也就是說Redis在開啓AOF時,除了將命令格式數據寫入到AOF文件,同時也會寫入到AOF重寫緩存。這樣AOF的寫入、重寫就作到了隔離,保證了重寫時不會阻塞寫入。
c)AOF重寫流程
1.AOF重寫完成會向主進程發送一個完成的信號
2.會將AOF重寫緩存中的數據所有寫入到文件中
3.用新的AOF文件,覆蓋原有的AOF文件。
d)AOF缺點
1.AOF文件一般會大於相同數據集的RDB文件
2.AOF模式下性能與RDB模式下性能高低,主要取決於AOF選用的fsync模式
下面給出客戶端請求RedisServer時,server端持久化的部分操做圖解。
4、Redis數據庫的實現
Redis是一個鍵值對數據庫,稱爲鍵空間。實現這種KV形式的存儲,Redis使用了兩種數據結構類型:一、字典,Redis字典使用的是哈希表實現,本來不許備詳細介紹Redis哈希表的實現。但發現Redis在實現哈希表時,提供了一個很好的rehash方案,這個方案思路很好,甚至能夠衍生到其餘各個應用中使用,方案的名稱叫「漸進式Rehash」。
實現哈希表的方法大同小異,但爲什麼各個開源軟件老是去開發本身獨有的哈希數據結構呢?從研究PHP內核的哈希實現與Redis哈希實現,發現應用場景決定了必須定製才能更好的發揮性能。
a)PHP主要應用於WEB場景,在WEB場景針對單次請求數據之間是隔離的,而且哈希的數量是有限的,那麼進行一次rehash也是很快的。因此PHP內核使用阻塞形式rehash,即rehash進行中將不能對當前哈希表進行任何操做。
b)在來看Redis,常駐進程,接收客戶端請求處理各項事務,而且操做的數據是相關且數據量較大的,若是使用PHP內核的那種方式就會出現:對哈希表進行rehash時,此時將阻塞全部客戶端請求,併發性能會大大降低。