【小資說庫】第13期 應用程序開發人員、DBA和DBMS開發人員的分工是怎樣的?
686
2025-03-31
1、簡介
Redis的非常快,很大一部分原因是因為Redis的數據存儲在內存中,既然在內存中,那么當服務器宕機或者斷電的時候,數據就會全部丟失了,所以Redis提供了兩種機制來保證Redis數據不會因為故障而全部丟失,這種機制稱為Redis的持久化機制。
Redis的持久化機制有兩種:
RDB(Redis Data Base) 內存快照
AOF(Append Only File) 增量日志
RDB(Redis DataBase) 指的是在指定的時間間隔內將內存中的數據集快照寫入磁盤,RDB是內存快照(內存數據的二進制序列化形式)的方式持久化,每次都是從Redis中生成一個快照進行數據的全量備份。
優點:
存儲緊湊,節省內存空間
恢復速度非常快
適合全量備份、全量復制的場景,經常用于災難恢復(對數據的完整性和一致性要求相對較低的場合)
缺點:
容易丟失數據,容易丟失兩次快照之間Redis服務器中變化的數據。
RDB通過fork子進程對內存快照進行全量備份,是一個重量級操作,頻繁執行成本高。
fork子進程,雖然共享內存,但是如果備份時內存被修改,最大可能膨脹到2倍大小。
AOF(Append Only File)是把所有對內存進行修改的指令(寫操作)以獨立日志文件的方式進行記錄,重啟時通過執行AOF文件中的Redis命令來恢復數據。AOF能夠解決數據持久化實時性問題,是現在Redis持久化機制中主流的持久化方案(后續會談到4.0以后的混合持久化)。
優點:
數據的備份更加完整,丟失數據的概率更低,適合對數據完整性要求高的場景
日志文件可讀,AOF可操作性更強,可通過操作日志文件進行修復
缺點:
AOF日志記錄在長期運行中逐漸龐大,恢復起來非常耗時,需要定期對AOF日志進行瘦身處理(后續詳述)
恢復備份速度比較慢
同步寫操作頻繁會帶來性能壓力
官網地址
http://www.redis.io
2、RDB
2.1 簡介
RDB持久化方案進行備份時,Redis會單獨fork一個子進程來進行持久化,會將數據寫入一個臨時文件中,持久化完成后替換舊的RDB文件。在整個持久化過程中,主進程(為客戶端提供服務的進程)不參與IO操作,這樣能確保Redis服務的高性能,RDB持久化機制適合對數據完整性要求不高但追求高效恢復的使用場景。
下面展示RDB持久化流程:
2.2 Fork
上面說到了RDB持久化過程中,主進程會fork一個子進程來負責RDB的備份,這里簡單介紹一下fork
Linux操作系統中的程序,fork會產生一個和父進程完全相同的子進程。子進程與父進程所有的數據均一致,但是子進程是一個全新的進程,與原進程是父子進程關系
出于效率考慮,Linux操作系統中使用COW(Copy On Write)寫時復制機制,fork子進程一般情況下與父進程共同使用一段物理內存,只有在進程空間中的內存發生修改時,內存空間才會復制一份出來。
在Redis中,RDB持久化就是充分的利用了這項技術,Redis在持久化時調用glibc函數fork一個子進程,全權負責持久化工作,這樣父進程仍然能繼續給客戶端提供服務。fork的子進程初始時與父進程(Redis的主進程)共享同一塊內存;當持久化過程中,客戶端的請求對內存中的數據進行修改,此時就會通過COW機制對數據段頁面進行分離,也就是復制一塊內存出來給主進程去修改。
RDB觸發的規則分為兩大類,分別是手動觸發和自動觸發:
自動觸發:
配置觸發規則
shutdown觸發
flushall觸發
手動觸發:
save
bgsave
2.3 自動觸發
以下介紹Redis的RDB持久化機制中的自動觸發機制中的配置觸發規則來觸發RDB,涉及到RDB規則的配置、文件存儲路徑配置、文件名配置、文件壓縮配置、文件完整性校驗配置。
在Redis安裝目錄下的redis.conf配置文件中搜索 /snapshot即可快速定位,配置文件默認注釋了下面三行數據,通過配置規則來觸發RDB的持久化,需要開啟或者根據自己的需求按照規則來配置。
下面對配置規則進行解釋,實際使用過程中可以根據需求進行合理的配置
save 3600 1 -> 3600秒內有1個key被修改,觸發RDB
save 300 100 -> 300 秒內有100個key被修改,觸發RDB
save 60 10000 -> 60 秒內有10000個key被修改,觸發RDB
配置RDB文件的存儲路徑
我們可以在Redis的安裝目錄下看到dump.rdb文件,如果沒看到,連接到客戶端執行一次shutdown,這個是后面
shutdown自動觸發規則,后續會講述
配置RDB文件的名稱
配置RDB文件壓縮
Redis默認會使用LZF算法對Redis的RDB文件進行壓縮,這會消耗一定的CPU計算資源,但是會帶來空間上的節省
配置RDB文件完整性校驗
Redis 默認使用CRC64的算法,對RDB文件完整性進行校驗,以此來保證RDB文件的完整
shutdown觸發Redis的RDB持久化機制非常簡單,我們在客戶端執行shutdown即可。
首先這里一定要特別注意,flushall是刪庫跑路,它是清空dump.rdb文件,千萬千萬不要看了博主的文章,跑到公司備份的時候順手來個flushall,然后到時候來問候我……,這個flushall是為了清空Redis數據的同時清空dump.rdb文件,要不然重啟Redis的時候,數據又會恢復到上一次備份的時候的數據,與flushall的執行指令含義就沖突了。
為了證明這個文件不會保留數據,我特地特地的寫個腳本測試一下:
編寫一個批量插入的腳本文件
vi batchKeyInsert.sh
#!/bin/bash for((i=0;i<100000;i++)) do echo -en "Hello Redis." | redis-cli -h 192.168.211.108 -p 6379 -c -x set name$i >>redis.log done
文件賦權
chmod +x batchKeyInsert.sh
./batchKeyInsert.sh
此時查看dump.rdb
執行flushall,后再次查看,rbd文件被清空
2.2 手動觸發
手動觸發RDB持久化的方式可以使用save命令和bgsave命令,這兩個命令的區別如下。
save:執行save指令,阻塞Redis的其他操作,會導致Redis無法響應客戶端請求,不建議使用。
bgsave:執行bgsave指令,Redis后臺異步進行快照的保存操作,此時Redis仍然能響應客戶端的請求。
2.3 RDB持久化文件的備份
在實際的生產環境中,我們一般不會使用主節點Master來進行持久化備份,我們會通過在Redis的多個從服務器上進行RDB持久化備份,這樣是為了對Redis數據的多次備份,防止出現網絡分區或者部分節點宕機甚至是硬件損壞的情況發生。
作為運維或者架構師,李子捌覺得應該要定時定期的通過腳本對Redis持久化文件進行轉移備份,這樣雙重保險,更加可靠,萬一遇到突發情況,也是多一手解決方案。
3、AOF
3.1 簡介
Redis配置文件中開啟,AOF持久化方案進行備份時,客戶端所有請求的寫命令都會被追加到AOF緩沖區中,緩沖區中的數據會根據Redis配置文件中配置的同步策略來同步到磁盤上的AOF文件中,同時當AOF的文件達到重寫策略配置的閾值時,Redis會對AOF日志文件進行重寫,給AOF日志文件瘦身。Redis服務重啟的時候,通過加載AOF日志文件來恢復數據。
3.2 AOF配置
AOF默認不開啟,默認為appendonly no,開啟則需要修改為appendonly yes
AOF配置文件的名稱默認為appendonly.aof
配置文件的地址可以通過在redis客戶端執行config get dir獲取,其保存路徑與RDB一致
AOF日志是以文件的形式存在的,當程序對AOF日志文件進行寫操作時,實際上將內容寫到了內核為文件描述符分配的一個內存緩沖區中,隨后內核會異步的將緩沖區中的數據刷新到磁盤中。如果緩沖區中的數據沒來得及刷回磁盤時,服務器宕機了,這些數據就會丟失。
因此Redis通過調用Linux操作系統的glibc提供的fsync(int fid)來將指定文件的內容強制從內核緩沖區刷回磁盤,以此來保證緩沖區中的數據不會丟失。不過這是一個IO操作,相比Redis的性能來說它是非常慢的,所以不能頻繁的執行。
Redis配置文件中有三種刷新緩沖區的配置:
appendfsync always
每次Redis寫操作,都寫入AOF日志,這種配置理論上Linux操作系統扛不住,因為Redis的并發遠遠超過了Linux操作系統提供的最大刷新頻率,就算Redis寫操作比較少的情況,這種配置也是非常耗性能的,因為涉及到IO操作,所以這個配置基本上不會用
appendfsync everysec
每秒刷新一次緩沖區中的數據到AOF文件,這個Redis配置文件中默認的策略,兼容了性能和數據完整性的折中方案,這種配置,理論上丟失的數據在一秒鐘左右
appendfsync no
Redis進程不會主動的去刷新緩沖區中的數據到AOF文件中,而是直接交給操作系統去判斷,這種操作也是不推薦的,丟失數據的可能性非常大。
注意要刷新緩沖區的數據到磁盤需要將如下配置,配置為no,不是yes
no-appendfsync-on-rewrite no
AOF持久化機制正常恢復與RDB持久化機制的恢復是一樣的,都只需要將備份文件放置到Redis的工作目錄下,Redis啟動時就會自動的加載。AOF持久化機制提供了AOF文件異常時恢復的功能,這個功能在AOF文件損壞的場景中經常被使用到。
測試,清空Redis服務中的數據
寫入數據
AOF日志文件每秒會被刷新一次數據,此時數據已經寫入了appendonly.aof文件
打開文件我們可以非常清除的閱讀AOF的文件內容,看到Redis的指令序列
此時人為的進行數據破壞
再次啟動發現無法啟動(我配置的別名啟動)
執行redis-check-aof --fix ../appendonly.aof 對AOF日志文件進行修復
修復過程中會有部分數據丟失
連接客戶端查看數據
前面提到AOF的缺點時,說過AOF屬于日志追加的形式來存儲Redis的寫指令,這會導致大量冗余的指令存儲,從而使得AOF日志文件非常龐大,比如同一個key被寫了10000次,最后卻被刪除了,這種情況不僅占內存,也會導致恢復的時候非常緩慢,因此Redis提供重寫機制來解決這個問題。Redis的AOF持久化機制執行重寫后,保存的只是恢復數據的最小指令集,我們如果想手動觸發可以使用如下指令:
bgrewriteaof
Redis4.0后的重寫使用的是RDB快照和AOF指令拼接的方式,在AOF文件的頭部是RDB快照的二進制形式的數據,尾部是快照產生后發生的寫入操作的指令。
由于重寫AOF文件時,會對Redis的性能帶來一定的影響,因此也不能隨便的進行自動重寫,Redis提供兩個配置用于自動進行AOF重寫的指標,只有這兩個指標同時滿足的時候才會發生重寫:
auto-aof-rewrite-percentage 100:指的是當文件的內存達到原先內存的兩倍
auto-aof-rewrite-min-size 64mb:指的是文件重寫的最小內存大小
AOF重寫流程如下:
bgrewriteaof觸發重寫,判斷是否存在bgsave或者bgrewriteaof正在執行,存在則等待其執行結束再執行
主進程fork子進程,防止主進程阻塞無法提供服務,類似RDB
子進程遍歷Redis內存快照中數據寫入臨時AOF文件,同時會將新的寫指令寫入aof_buf和aof_rewrite_buf兩個重寫緩沖區,前者是為了寫會舊的AOF文件,后者是為了后續刷新到臨時AOF文件中,防止快照內存遍歷時新的寫入操作丟失
子進程結束臨時AOF文件寫入后,通知主進程
主進程會將上面3中的aof_rewirte_buf緩沖區中的數據寫入到子進程生成的臨時AOF文件中
主進程使用臨時AOF文件替換舊AOF文件,完成整個重寫過程
4、混合持久化
Redis4.0后大部分的使用場景都不會單獨使用RDB或者AOF來做持久化機制,而是兼顧二者的優勢混合使用。其原因是RDB雖然快,但是會丟失比較多的數據,不能保證數據完整性;AOF雖然能盡可能保證數據完整性,但是性能確實是一個詬病,比如重放恢復數據。
其日志文件結構如下:
混合持久化通過aof-use-rdb-preamble yes開啟,Redis 4.0以上版本默認開啟
測試,我們先插入一些key,然后執行BGREWRITEAOF觸發AOF持久化后,再插入一些key
此時將會看到如下的效果,驗證了混合持久化的方式
5、總結
最后來總結這兩者,到底用哪個更好呢?
推薦是兩者均開啟
如果對數據不敏感,可以選單獨用RDB
不建議單獨用AOF,因為可能會出現Bug
如果只是做純內存緩存,可以都不用
Redis官網是這么介紹的:
看不懂就看下Redis中文網的介紹:
Redis官網關于持久化的介紹
https://redis.io/topics/persistence
Redis中文網關于持久化的介紹
http://redis.cn/topics/persistence.html
Java Redis 分布式 分布式緩存服務 Redis
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。