久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

redis持久化的示例分析

187次閱讀
沒有評論

共計 4341 個字符,預計需要花費 11 分鐘才能閱讀完成。

這篇文章給大家分享的是有關 redis 持久化的示例分析的內容。丸趣 TV 小編覺得挺實用的,因此分享給大家做個參考,一起跟隨丸趣 TV 小編過來看看吧。

為什么需要持久化?

由于 Redis 是一種內存型數據庫,即服務器在運行時,系統為其分配了一部分內存存儲數據,一旦服務器掛了,或者突然宕機了,那么數據庫里面的數據將會丟失,為了使服務器即使突然關機也能保存數據,必須通過持久化的方式將數據從內存保存到磁盤中。

對于進行持久化的程序來說,數據從程序寫到計算機的磁盤的流程如下:

1、客戶端發送一個寫指令給數據庫(此時數據在客戶端的內存)

2、數據庫接收到寫的指令以及數據(數據此時在服務端的內存)

3、數據庫發起一個系統調用,把數據寫到磁盤(此時數據在內核的內存)

4、操作系統把數據傳輸到磁盤控制器(數據此時在磁盤緩存中)

5、磁盤控制器執行真正寫入數據到物理媒介的操作(如磁盤)

如果只是考慮數據庫層面,數據在第三階段之后就安全了,在這個時候,系統調用已經發起了,即使數據庫進程奔潰了,系統調用會繼續進行,也能順利將數據寫入到磁盤中。在這一步之后,在第 4 步內核會將數據從內核緩存保存到磁盤緩存中,但為了系統的效率問題,默認情況下不會太頻繁地執行這個動作,大概會在 30s 執行一次,這就意味著如果這一步失敗了或者就在進行這一步的時候服務器突然關機了,那么就可能會有 30s 的數據丟失了,這種比較普通的災難性問題也是需要考慮的。

POSIX API 也提供了一個系統調用讓內核強制將緩存數據寫入到磁盤中,比較常見的就是 fsync 系統調用。

int fsync(int fd);

fsync 函數只對由文件描述符 fd 指定的一個文件起作用,并且等待寫磁盤操作結束后才返回。每次調用 fsync 時,會初始化一個寫操作,然后把緩沖區的數據寫入到磁盤中。fsync() 函數在完成寫操作的時候會阻塞進程,如果其他線程也在寫同一個文件,它也會阻塞其他線程,直到完成寫操作。

持久化

持久化是將程序數據在持久狀態和瞬時狀態間轉換的機制。對于程序來說,程序運行中數據是在內存的,如果沒有及時同步寫入到磁盤,那么一旦斷電或者程序突然奔潰,數據就會丟失了,只有把數據及時同步到磁盤,數據才能永久保存,不會因為宕機影像數據的有效性。而持久化就是將數據從程序同步到磁盤的一個動作過程。

Redis 的持久化

redis 有 RDB 和 AOF 兩種持久化方式。RDB 是快照文件的方式,redis 通過執行 SAVE/BGSAVE 命令,執行數據的備份,將 redis 當前的數據保存到 *.rdb 文件中,文件保存了所有的數據集合。AOF 是服務器通過讀取配置,在指定的時間里,追加 redis 寫操作的命令到 *.aof 文件中,是一種增量的持久化方式。

RDB

RDB 文件通過 SAVE 或 BGSAVE 命令實現。SAVE 命令會阻塞 Redis 服務進程,直到 RDB 文件創建完成為止。BGSAVE 命令通過 fork 子進程,有子進程來進行創建 RDB 文件,父進程和子進程共享數據段,父進程繼續提供讀寫服務,子進程實現備份功能。BGSAVE 階段只有在需要修改共享數據段的時候才進行拷貝,也就是 COW(Copy On Write)。SAVE 創建 RDB 文件可以通過設置多個保存條件,只要其中一個條件滿足,就可以在后臺執行 SAVE 操作。

SAVE 和 BGSAVE 命令的實現代碼如下:

void saveCommand(client *c) {
// BGSAVE 執行時不能執行 SAVE
if (server.rdb_child_pid != -1) {
addReplyError(c, Background save already in progress 
return;
rdbSaveInfo rsi, *rsiptr;
rsiptr = rdbPopulateSaveInfo(rsi);
//  調用 rdbSave 函數執行備份(阻塞當前客戶端)if (rdbSave(server.rdb_filename,rsiptr) == C_OK) {addReply(c,shared.ok);
} else {addReply(c,shared.err);
* BGSAVE  命令實現  [可選參數 schedule]
void bgsaveCommand(client *c) {
int schedule = 0;
/*  當 AOF 正在執行時,SCHEDULE 參數修改 BGSAVE 的效果
* BGSAVE 會在之后執行,而不是報錯
*  可以理解為:BGSAVE 被提上日程
if (c- argc   1) {
//  參數只能是 schedule 
if (c- argc == 2   !strcasecmp(c- argv[1]- ptr, schedule )) {schedule = 1;} else {addReply(c,shared.syntaxerr);
return;
// BGSAVE 正在執行,不操作
if (server.rdb_child_pid != -1) {addReplyError(c, Background save already in progress} else if (server.aof_child_pid != -1) {
// aof 正在執行,如果 schedule==1,BGSAVE 被提上日程
if (schedule) {
server.rdb_bgsave_scheduled = 1;
addReplyStatus(c, Background saving scheduled} else {
addReplyError(c,
 An AOF log rewriting in progress: can t BGSAVE right now.  
 Use BGSAVE SCHEDULE in order to schedule a BGSAVE whenever  
 possible. 
} else if (rdbSaveBackground(server.rdb_filename,NULL) == C_OK) {//  否則調用 rdbSaveBackground 執行備份操作
addReplyStatus(c, Background saving started} else {addReply(c,shared.err);
}

有了 RDB 文件之后,如果服務器關機了,或者需要新增一個服務器,重新啟動數據庫服務器之后,就可以通過載入 RDB 文件恢復之前備份的數據。但是 bgsave 會耗費較長時間,不夠實時,會導致在停機的時候丟失大量數據。

AOF(Append Only File)

RDB 文件保存的是數據庫的鍵值對數據,AOF 保存的是數據庫執行的寫命令。

AOF 的實現流程有三步:

append- write- fsync

append 追加命令到 AOF 緩沖區,write 將緩沖區的內容寫入到程序緩沖區,fsync 將程序緩沖區的內容寫入到文件。當 AOF 持久化功能處于開啟狀態時,服務器每執行完一個命令,就會將命令以協議格式追加寫入到 redisServer 結構體的 aof_buf 緩沖區,具體的協議這里不展開闡述。

AOF 的持久化發生時期有個配置選項:appendfsync。該選項有三個值:always:所有內容寫入并同步到 aof 文件 everysec:將 aof_buf 緩沖區的內容寫入到 AOF 文件,如果距離上次同步 AOF 文件的 no:將 aof_buf 緩沖區中的所有內容寫入到 AOF 文件,但并不對 AOF 文件進行同步,由操作系統決定何時進行同步,一般是默認情況下的 30s。

AOF 持久化模式每個寫命令都會追加到 AOF 文件,隨著服務器不斷運行,AOF 文件會越來越大,為了避免 AOF 產生的文件太大,服務器會對 AOF 文件進行重寫,將操作相同 key 的相同命令合并,從而減少文件的大小。

舉個例子,要保存一個員工的名字、性別等信息:

hset employee_12345 name hoohack

hset employee_12345 good_at php

hset employee_12345 gender male

只是錄入這個哈希鍵的狀態,AOF 文件就需要保存三條命令,如果還有其他,比如刪除,或者更新值的操作,那命令將會更多,文件會更大,有了重寫后,就可以適當地減少文件的大小。

AOF 重寫的實現原理是先服務器中的數據庫,然后遍歷數據庫,找出每個數據庫中的所有鍵對象,獲取鍵值對的鍵和值,根據鍵的類型對鍵值對進行重寫。比如上面的例子,可以合并為下面的一條命令:

hset employee_12345 name hoohack good_at php gender male。

AOF 的重寫會執行大量的寫入操作,Redis 是單線程的,所以如果有服務器直接調用重寫,服務器就不能處理其他命令了,因此 Redis 服務器新起了單獨一個進程來執行 AOF 重寫。

Redis 執行重寫的流程:

在子進程執行 AOF 重寫時,服務端接收到客戶端的命令之后,先執行客戶端發來的命令,然后將執行后的寫命令追加到 AOF 緩沖區中,同時將執行后的寫命令追加到 AOF 重寫緩沖區中。等到子進程完成了重寫工作后,會發一個完成的信號給服務器,服務器就將 AOF 重寫緩沖區中的所有內容追加到 AOF 文件中,然后原子性地覆蓋現有的 AOF 文件。

RDB 和 AOF 的優缺點

RDB 持久化方式可以只通過服務器讀取數據就能加載備份中的文件到程序中,而 AOF 方式必須創建一個偽客戶端才能執行。

RDB 的文件較小,保存了某個時間點之前的數據,適合做災備和主從同步。

RDB 備份耗時較長,如果數據量大,在遇到宕機的情況下,可能會丟失部分數據。另外,RDB 是通過配置使達到某種條件的時候才執行,如果在這段時間內宕機,那么這部分數據也會丟失。

AOF 方式,在相同數據集的情況下,文件大小會比 RDB 方式的大。

AOF 的持久化方式也是通過配置的不同,默認配置的是每秒同步,最快的模式是同步每一個命令,最壞的方式是等待系統執行 fsync 將緩沖同步到磁盤文件中,大部分操作系統是 30s。通常情況下會配置為每秒同步一次,所以最多會有 1s 的數據丟失。

怎樣的同步方式更好?

RDB 和 AOF 方式結合。起一個定時任務,每小時備份一份服務器當前狀態的數據,以日期和小時命名,另外起一個定時任務,定時刪除無效的備份文件(比如 48 小時之前)。AOF 配置為 1s 一次。這樣一來,最多會丟失 1s 的數據,同時如果 redis 發生雪崩,也能迅速恢復為前一天的狀態,不至于停止服務。

感謝各位的閱讀!關于“redis 持久化的示例分析”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!

正文完
 
丸趣
版權聲明:本站原創文章,由 丸趣 2023-08-04發表,共計4341字。
轉載說明:除特殊說明外本站除技術相關以外文章皆由網絡搜集發布,轉載請注明出處。
評論(沒有評論)
主站蜘蛛池模板: 开阳县| 平乐县| 大同市| 霍州市| 安宁市| 灌南县| 连云港市| 胶南市| 岐山县| 于田县| 宾阳县| 花垣县| 永川市| 彭州市| 扶绥县| 西华县| 牡丹江市| 滦南县| 石首市| 耿马| 沈丘县| 博湖县| 抚松县| 金乡县| 汶川县| 本溪| 沈阳市| 望江县| 微山县| 民县| 湖北省| 大荔县| 息烽县| 仁化县| 泰宁县| 静海县| 同江市| 西藏| 沈丘县| 绥芬河市| 怀来县|