深入探討Redis持久化原理
Redis是記憶體資料庫,為了確保資料的持久化, redis提供了兩種持久化方式RDB和AOF,
Redis是記憶體資料庫,為了確保資料的持久化,redis提供了兩種持久化方式RDB和AOF,以下我們就分別來看下這兩種持久化方式的實作原理。
RDB(預設)
RDB是透過快照方式完成的,當滿足一定條件時,redis會自動將記憶體中的資料持久化到磁碟。
觸發快照的時機
- 符合自訂配置的快照規則。 (在redis.conf中配置,下面會詳細介紹)
- 執行save或bgsave指令
- #執行flushall指令
執行主從複製操作(第一次)
(免費學習影片教學推薦:mysql影片教學)
原理圖
- 在快照進行的過程中,也就是生成文件的過程中,不會對原有的rdb文件進行修改,直到快照生成完畢,直接將老的替換成新的,保證rdb文件任何時刻都是完整的。
- 我們可以透過定時備份rdb檔案來實現redis資料的備份,rdb是壓縮的二進位文件,佔用空間小,有利於傳輸
快照設定規則save {多少秒內} {資料變化了多少}
例如:save 100 1:在100秒內,至少有一個鍵被修改就進行快照;save 200 4:在200秒內,至少4個鍵被修改就進行快照。
RDB的優缺點
- 缺點:使用RDB進行持久化,在redis突然異常退出的時候,會遺失最後一次快照之後的資料。但是,可以根據組合設定自動快照的方式,降低資料損失,確保在接受範圍內。如果資料較為重要,可以使用AOF方式
- 優點:使用RDB方式可以最大化redis效能,在快照過程中,我們可以看到主行程只需要fork出一個子行程即可,剩下的工作全部由子進程完成,父進程無需進行任何的磁碟I/O操作。但是,如果資料集較大,在fork子程序的時候比較耗時,會導致redis在一段時間內停止處理請求。
AOF方式
預設情況下,redis是沒有開啟AOF(append only file)的。在開始AOF之後,redis每接收到一條更改redis資料的指令,就會將該指令寫入硬碟中的AOF檔。很明顯,該過程會降低redis的性能,但大部分情況下是能夠接受的,同時,使用性能較好的硬碟可以提高AOF性能
AOF配置方式
# 开启appendonly参数appendonly true# 设置AOF文件位置dir ./# 设置AOF文件名称,默认是appendonly.aofappendfilename appendonly.aof<br/>
登入後複製
原理圖
RESP協定
Redis客戶端使用RESP協定與Redis服務端進行通信,該協定是專門為redis設計的,但是也可以用於其他C-S項目。
間隔符號:在linux中是\r\n,在windows中是\n簡單字串以' '開頭錯誤Errors,以'-'開頭整數型別Integer,以':'開頭大字串以'$'開頭陣列類型Arrays,以'*'開頭
AOF原理說明
redis透過將所有的寫入指令記錄到AOF檔中,來持久化資料。而將指令記錄到AOF檔的過程,可以分成三個階段:
指令傳播
redis將執行完的指令,指令參數,指令參數格數等內容傳送到AOF程式。當redis客戶端執行命令的時候,透過連接,將協議文本發送到redis,redis接收到協議文本之後,根據內容,選擇適當的命令函數,將協議文本轉換成Redis字符串對象,在命令函數執行完成後,將命令參數發送到AOF程式。 ###
缓存追加
AOF程序接收到命令参数之后,会将其从字符串对象转换成协议内容,再将协议内容追加到AOF缓存中。AOF缓存是在redisServer结构的aof_buf中,新的内容会被追加到aof_buf末尾。aof_buf保持着所有未被写入到AOF文件的协议文本。
文件写入和保存
将AOF缓存内容写入到AOF文件,并保持到磁盘。 当服务器的常规函数被执行,或者事件处理器被执行的时候,flushAppendOnlyFile函数将会被执行。会有以下两个过程。
- WRITE:将AOF缓存中的内容写入到AOF文件
- SAVE:调用fsync或者fdatasync函数,将AOF文件保存到磁盘中
AOF一共有三种保存模式
- AOF_FSYNC_NO:不保存。在这种模式下,每次调用flushAppendOnlyFile函数,write会被执行,而save会被忽略。而save只有在以下三种条件下会触发,redis关闭,aof功能关闭,系统的写缓存被刷新(可能是缓存满了,或者定期执行保持操作)。这三种情况下执行save操作会引起redis主线程的阻塞。
- AOF_FSYNC_EVERYSEC(默认):每秒保存一次。save每秒被执行一次,但是save由后台子线程完成,不会导致redis主线程阻塞。
- AOF_FSYNC_ALWAYS:每执行一个命令保存一次。这种情况下,每执行一个命令write和save都会被执行,而且save操作由主线程完成,会导致redis的阻塞。安全性较高,性能较差,因此不推荐使用。
AOF的文件优化
Redis可以在AOF文件过大的时候,在后台(子进程)对AOF文件进行重写。重写之后的新文件,包含恢复当前数据集所需的最小命令集合。重写,并不会对AOF文件进行读取和写入,针对的是数据库中的当前键。
优化前set s1 1set s1 2set s1 3优化后set s1 3<br/>
登入後複製
AOF文件优化原理
AOF的重写是通过子进程实现的,因此,主线程是继续工作的,有可能对新的数据进行修改,有可能会导致数据库的数据和重写之后的数据不一致。redis通过增加一个AOF重写缓存来解决这个问题,当fork出子进程之后,新的命令不仅会追加到现有的AOF文件中,还会添加一份数据到这个缓存当中。
重写过程分析(需要保证从写的操作是绝对安全的)
Redis创建新的AOF文件之后,会继续将命令添加到原有的AOF文件中,即使数据库突然宕机了,原有的AOF文件和文件内容也不会有损失。而当新的AOF文件创建完毕之后,会直接把旧的替换掉,往新的AOF文件中添加命令。
当子进程在进行重写时,主进程会完成下列工作
- 处理请求,将新的命令继续添加到AOF文件中,同时将命令添加到AOF重写缓存中。保证数据的一致行,避免出现数据丢失。
- 当子进程重写完毕之后会向主进程发送一个完成信号,这时主进程会把重写缓存中的内容添加到新的AOF文件中,这样新的AOF文件,数据库,旧的AOF文件的内容就完全一致了。然后对新的AOF文件改名,覆盖原有的AOF文件。
这样程序就完成了新旧AOF文件的替换工作。而当处理完成之后,主进程就会继续接受请求。整个重写过程中只有最后的缓存写入和改名替换的操作会导致主进程阻塞,其他时候不会影响redis的正常工作,把AOF重写对redis的性能影响降到最低。
优化触发条件
#当前的AOF文件超过上次重写时AOF文件大小百分几的时候进行重写,如果没有重写过,则以启动时AOF文件的大小为准auto-aof-rewrite-percentage 100#限制允许重写的最小的AOF文件,也就是文件小于这个值的时候不需要进行重写优化auto-aof-rewrite-min-size 64mb<br/>
登入後複製
本文转载自:https://database.51cto.com/art/202002/610825.htm
更多redis知识请关注redis数据库教程栏目。
以上是探索Redis持久化原理的詳細內容。更多資訊請關注PHP中文網其他相關文章!