網站首頁 編程語言 正文
1.RDB持久化
?首先,RDB持久化方式會產生一個經過壓縮的二進制文件,Redis服務器在啟動之初,通過這個文件可以還原數據庫的狀態。那么我們接下來看下RDB文件是如何實現保存和載入的。
1.1 RDB文件的保存
?RDB文件的保存有兩個命令可以實現,分別是save
和bgsave
,執行后都會生成新的RDB文件,區別是save
會阻塞服務器的進程,直到RDB文件創建完成為止,期間服務器不能處理任何客戶端的命令請求。而bgsave
通過派生出一個子進程,由子進程來完成RDB文件的創建,期間服務器正常處理客戶端的命令請求。其實這兩個命令的底層實現方式都一樣,只不過一個是主進程來做,另一個是通過子進程來完成。
?在redis.conf文件中,有兩個參數是和rdb的文件保存相關:
// 這個是rdb文件的名稱 dbfilename dump.rdb // 這個是rdb文件的保存路徑,這是相對路徑,相對于redis-server的啟動路徑 dir ./
1.2 RDB文件的載入
?在redis服務器啟動之初,會去查找有沒有rdb的持久化文件存在,如果有就會自動載入,當然前提是沒有開啟aof持久化的功能。在rdb載入期間會,服務器處于阻塞裝填,直到載入工作完全結束。
1.3 RDB持久化時服務器的狀態
save
命令執行期間,所有客戶端命令都會被拒絕執行。
bgsave
命令執行期間,客戶端發送的save
和bgsave
命令會被拒絕執行,但是客戶端發送的bgrewriteaof
不會拒絕但會被阻塞,直到當前的bgsave
命令執行完畢。但是值得說明的是,如果服務器在執行bgrewriteaof
命令期間,客戶端發送的bgsave
命令會被服務器拒絕。當然這是站在性能角度考慮,否則fock出兩個子進程,大量的進行磁盤的讀寫,會影響整個服務器的性能。
1.4 RDB持久化策略
?用戶可以通過配置文件給RDB的持久化設置保存策略,看一下redis.conf文件中的配置:
save 900 1
save 300 10
save 60 10000
?以上的默認配置可以表示為:服務器在900秒之內,至少進行了1次的修改,在300秒之內至少進行了10次修改,在60秒之內至少進行了10000次修改。這三種策略只要滿足一個,即可觸發RDB的持久化。
?這里需要了解一下,Redis是怎么基于這些配置策略實現自動化間歇性保存RDB文件的,還是回到RedisServer這個這個結構體的源碼中看一下:
struct redisServer { // 數組,用于保存redis.conf配置的持久化策略 struct saveparam *saveparams; /* Save points array for RDB */ // 上面這個數組的長度 int saveparamslen; /* Number of saving points */ // 記錄上一次持久化到現在服務器修改了多少鍵值對 long long dirty; /* Changes to DB from the last save */ // 記錄上一次RDB持久化的UNIX時間戳 time_t lastsave; /* Unix time of last successful save */ }
?在redisServer中,有saveparams數組專門保存我們配置的持久化策略,這里使用到了saveparam這個結構體,看一下源碼:
struct saveparam { // 這里是配置文件save的第1個參數 time_t seconds; // 這里是配置文件save的第2個參數 int changes; };
?這樣,配置文件中的持久化策略就記錄到了redisServer.saveparam屬性中,還是會基于serverCron這個時間事件函數,100ms執行一次,每次會檢查 dirty 和 lastsave 記錄的修改鍵值對數量和時間差,是否匹配到了saveparam中配置的持久化策略,如果命中就進行新一輪的RDB持久化。
2.AOF持久化
?和RDB不同,AOF是通過記錄Redis服務器中執行的寫命令來記錄數據庫狀態的,類似于mysql的binlog,當然保存的內容是經過協議轉換的命令。在服務器啟動之初,通過載入和執行AOF文件中的命令來還原數據庫的狀態。
2.1 持久化的實現
?在服務器執行命令之后,并不是立刻寫入aof文件中,而是先寫入 aof_buf緩沖區里面,這也是redisServer的一個屬性結構:
struct redisServer { // aop緩沖區,記錄服務器寫入的命令 sds aof_buf; /* AOF buffer, written before entering the event loop */ }
?我們再看一下redis.conf關于aof持久化的一個配置:
// 這個表示每次執行都會寫入 # appendfsync always // 這個表示每秒寫入一次 appendfsync everysec // 這個由操作系統決定,無法控制 # appendfsync no
?AOF實現持久化的原理是這樣的,客戶端執行的命令會先記錄到 redisServer.aof_buf 中,然后基于配置文件的appendfsync策略決定什么時候同步到AOF文件中。這里的同步也會經過兩個步驟:
- aof_buf 內容寫入到操作系統文件緩存 pagecache;
- pagecache 落盤寫入到屋里磁盤設備中;
?我們知道Redis是基于Reactor網絡模型,不斷進行事件循環,每進行一輪的事件循環,都會執行步驟1,所以從aof_buf 到 pagecache總是會發生。但是步驟2就跟appendfsync有關系了:
- always表示只要步驟1發生,步驟2也會發生,所以是最安全,但是效率最慢的一個。
- everysec表示步驟1發生后,步驟2每秒執行一次落盤,是效率和數據安全折中的方案,停機故障時有丟失1秒鐘數據的風險。
- no表示步驟1發生后,何時落盤由操作系統決定,數據丟失風險大,效率也一般,因為數據量過大,單次落盤的時間也最長。
?默認配置是everysec,即每秒執行一次數據落盤保存。
2.2 文件的載入與數據還原
?因為AOF文件中包含了重建數據庫狀態的所有寫命令,所以服務器只要讀入并全部執行一遍就可以完成數據庫狀態的還原。服務器在啟動之初,會創建一個不帶網絡連接的偽客戶端來做這件事,在載入命令完成后,這個客戶端的使命就結束了。
2.3 AOF文件的重寫
?隨著寫入到AOF文件的命令越來越多,這個文件體積會越來大,會對宿主機或文件還原造成一定的影響,所以需要通過AOF文件的重寫來解決文件體積膨脹的問題。
?AOF文件重寫并不是對現有AOF文件進行處理,而是基于數據庫當前的狀態來實現的。服務器會從數據庫中讀取鍵對應的值,然后用一條命令去記錄鍵值對,代替之前可能存在的多條命令,寫入到一個新的AOF文件中,這就是AOF重寫功能實現的原理。需要注意的是,對于某些元素比較多的集合或者列表(默認配置是64個),這個一條命令可能拆分成多條實現,避免造成客戶端輸入緩沖區溢出的情況。
?和bgsave
一樣,AOF重寫的動作也是放到子進程去執行,這樣可以保證父進程可以繼續處理名請求。但是這里會有一個問題,就是AOF文件重寫期間,父進程處理命令請求之后,會和重寫AOF文件時的數據庫狀態不一致。Redis解決這個問題的方法是設置一個AOF重寫緩沖區,子進程一單創建并且開始重寫命令之后,父進程處理的所有寫命令請求都會記錄到AOF重寫緩沖區。當子進程重寫工作完成之后,會生成一個新的AOF文件,向父進程發送一個信號,父進程在接受此信號,開始執行以下工作:
- 將AOF重寫緩沖區的內容寫入到新的AOF文件中,保證新文件和服務器當前的狀態一致;
- 對新的AOF文件改名,并原子的替換現有的AOF文件,完成新舊文件的替換。
?以上兩步,父進程會造成服務器進程的阻塞,但其他時間,都不會阻塞,整個重寫動作對服務器性能的影響降到了最低,以上就是bgrewriteaof
命令的實現原理。
原文鏈接:https://blog.csdn.net/qq_35850405/article/details/127944005
相關推薦
- 2022-05-20 ElasticSearch 7.X系列之:細節問題
- 2022-04-24 python自定義封裝帶顏色的logging模塊_python
- 2022-04-02 C#中ManualResetEvent實現線程的暫停與恢復_C#教程
- 2023-01-07 Python中sys.argv用法圖文詳解_python
- 2022-04-12 C++中標準線程庫的基本使用介紹_C 語言
- 2024-01-15 spring-boot jpa 實現攔截器 StatementInspector
- 2022-11-18 Go與Redis實現分布式互斥鎖和紅鎖_Golang
- 2023-01-01 C++?Boost?Flyweight庫使用介紹_C 語言
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支