一、什么是持久化數(shù)據(jù)結(jié)構(gòu)
持久化存儲,其實主要是針對內(nèi)存數(shù)據(jù)的,以典型的Redis來說,持久化存儲主要有三種方式:
1、RDB
RDB: 保存某個時間點的全量數(shù)據(jù)快照
觸發(fā)方式
1. save: 阻塞Redis的服務(wù)器進程,直到RDB文件被創(chuàng)建完畢
2. bgsave: fork出子進程來創(chuàng)建RDB文件,不阻塞服務(wù)器進程, lastsave 指令可以查看最近的備份時間
3. 根據(jù)redis.conf里的save m n配置定時觸發(fā)(用的是BGSAVE)
4. 主從復(fù)制時,主節(jié)點自動觸發(fā)
5. 執(zhí)行debug relaod命令
6. 執(zhí)行shutdown且沒有開啟AOF持久化
2、AOF
AOF: 增量存儲命令
觸發(fā)方式
1. BGREWRITEAOF: 增量追加命令
2. 根據(jù)redis.conf里的appendfsync配置定時觸發(fā)
3. AOF文件重寫
3、混合持久化
為解決AOF文件啟動加載慢,不利于快速恢復(fù)的缺點,RedisV4.0提供了新的持久化方式——混合持久化。
混合持久化的文件內(nèi)容: [RDB file][AOF tail]
持久化過程:
1. 將重寫(rewrite)這一刻之前的數(shù)據(jù)做RDB快照處理
2. 將RDB快照內(nèi)容和AOF增量命令先后寫入新的AOF臨時文件
3. 重寫完成后,對AOF臨時文件改名,并覆蓋舊的AOF文件
在redis重啟的時候,可以先加載RDB文件,然后再重放增量的AOF日志就可以完全替代之前的AOF全量文件重放,因此能大幅提高重啟效率提高。
延伸閱讀:
二、可持久化實際應(yīng)用
1.幾何計算
在幾何計算中有許多離線算法,例如懸線掃描法,其基本策略是一次掃描后給出所有詢問的回答,在時間復(fù)雜度分析相當(dāng)優(yōu)異。但在強迫在線的情況下,每次都要進行一次懸線掃描,詢問操作的時間復(fù)雜度就從對數(shù)時間降為線性。
為了解決時間復(fù)雜度上的問題,在這里可以引入可持久化的思維。我們將掃描線的時間軸作為一個變動依據(jù),持久化相關(guān)的結(jié)構(gòu),只要我們能將詢問在對數(shù)時間內(nèi)穿梭于這個時間軸,必能動態(tài)解決先前的問題。
2.字串處理
為了達(dá)到非常高效率的合并操作,防止大量重復(fù)性字串的生成伴隨的效能退化,使得各方面的操作都能遠(yuǎn)低于線性操作。如C++中的rope就是一個可持久化的數(shù)據(jù)結(jié)構(gòu)。不只是字串操作。若處理類型有大量重復(fù)操作,均可以考慮將數(shù)據(jù)結(jié)構(gòu)進行可持久化處理,以達(dá)到壓縮時間開支的效果。
3.版本回溯
實際上就是對應(yīng)大部分的應(yīng)用軟體中的redo/undo。如果資料庫/操作變動為了高效率操作而會配上復(fù)雜的結(jié)構(gòu)(并不像 hash, set 反轉(zhuǎn)操作只需要常數(shù)或?qū)?shù)時間),那么為了快速回推變動結(jié)果,持久化結(jié)構(gòu)就是要減少 redo/undo 的花費。
資料庫本身可以常數(shù)回推,紀(jì)錄變動的部分情況即可。而應(yīng)用層的計算,大部分實作都是砍掉快取,并且重新計算出一份新的結(jié)構(gòu),有時候回推的變動大小為 m,為了重新計算結(jié)構(gòu)而消耗了 n + m n+mn+m,如果 n nn 和 m mm 的差距非常大,那連續(xù)回推的體感就很糟糕。