redis持久化实现原理
RDB
rdb持久化原理:
會涉及到操作系統(tǒng)底層的fork調(diào)用,詳情查看:https://zhangxueliang.blog.csdn.net/article/details/104076571
會fork出一個子進程用于持久化。
當redis主進程發(fā)生數(shù)據(jù)修改的時候,會觸發(fā)內(nèi)核級別的寫時復制操作,寫數(shù)據(jù)到持久化文件是子進程來完成的,數(shù)據(jù)的增刪改是在父進程中進行的,所以redis的持久化是fork+copy on write來實現(xiàn)的。
比如8點fork出一個子進程用于持久化操作,此時子進程拷貝的是8點時的數(shù)據(jù),父子進程的數(shù)據(jù)修改,彼此都不可見。假如10點redis數(shù)據(jù)發(fā)生了修改,此時會由內(nèi)核的寫時復制機制觸發(fā)數(shù)據(jù)復制操作,將引用指向新的數(shù)據(jù),此時子進程的引用還是指向舊數(shù)據(jù)。寫時復制不是為了數(shù)據(jù)同步,而是數(shù)據(jù)隔離。
fork出來的子進程會一直等到數(shù)據(jù)持久化做完后才銷毀。每次持久化開始時都會fork出一個子進程。每次拍快照(持久化)都是當前時間點的全量數(shù)據(jù)覆蓋之前的快照數(shù)據(jù),如果快照采用增量更新的方式的話,需要在內(nèi)存中判斷哪些數(shù)據(jù)有更新哪些沒更新,反而消耗CPU資源。
拷貝引用的成本比拷貝數(shù)據(jù)的成本低很多,因為一個引用的大小是4個字節(jié),但引用指向的數(shù)據(jù)可能是一個數(shù)組幾百個字節(jié)。
redis RDB持久化配置方式:
如果想關閉持久化,只需在配置文件redis.conf中配置:
save ""redis.conf配置文件中配置持久化文件相關信息:
RDB的弊端:
①不支持拉鏈。由于只有一個dump.rdb持久化文件,所以會丟失前些天的數(shù)據(jù),需要手工將dump文件拷貝出來。比如:我需要某一天的dump文件,如果不手工干涉的話,也許已經(jīng)被覆蓋了。
②丟失數(shù)據(jù)相對多一些。時點與時點之間的窗口數(shù)據(jù)容易丟失,比如8點得到一個dump.rdb,8:15要落一個rdb,結果掛機了。
RDB的優(yōu)勢:
類似于Java中的序列化,恢復數(shù)據(jù)的速度較快。想象一下,傳輸一個json數(shù)據(jù)然后解析成對象load到內(nèi)存快還是直接傳輸一個二進制字節(jié)數(shù)組直接就懟到了內(nèi)存快?用大腿想都知道是后者啦!
正是由于RDB的弊端,才有了AOF:Append Only File 的持久化機制。
AOF
將redis的寫操作記錄到文件中。類似于MySQL中的redo log和binlog一樣。這樣的話,丟失數(shù)據(jù)就會少啦。
在redis中,RDB和AOF可以同時開啟,但是AOF優(yōu)先,只會使用AOF做重啟后的數(shù)據(jù)恢復。
aof執(zhí)行日志文件中的命令,速度相對rdb要慢。但丟失數(shù)據(jù)相對rdb少。
aof天然的弊端:
①日志體量無限變大;
②恢復慢。
優(yōu)點如果能保住,日志還是可以用的,需要設計一個方案讓日志,AOF足夠小。
4.0以前通過日志重寫來實現(xiàn):
①刪除抵銷的命令
②合并重復的命令
4.0以后也是通過日志重寫來實現(xiàn),只不過進行了優(yōu)化:
①將老的數(shù)據(jù)RDB到aof文件中,存儲的是二進制格式的日志數(shù)據(jù)。
②將增量的以redis指令的方式append到aof日志文件中。
AOF是一個混合體,利用了RDB的快和日志的全量。
redis 4.0 以后,AOF中包含RDB全量快照數(shù)據(jù),增加記錄新的寫操作。
開啟AOF
IO流中為什么要flush一下才能將數(shù)據(jù)寫到磁盤,因為磁盤IO操作都是由操作系統(tǒng)內(nèi)核來進行的,數(shù)據(jù)先是下入到內(nèi)存的buffer中,flush就是將數(shù)據(jù)從buffer中刷到硬盤。redis中也是如此:
always:每次發(fā)生數(shù)據(jù)變更,立即持久化到硬盤
ererysec:每秒持久化一次,也就是每秒調(diào)一次flush將buffer數(shù)據(jù)刷到硬盤
no:等待OS自己將數(shù)據(jù)刷到硬盤,buffer一滿OS就會刷到硬盤。
效率對比:always < everysec < no
no-appendfsync-on-rewrite默認是no:可能會發(fā)生丟數(shù)據(jù)的情況。但不會與自己的子進程爭搶IO操作權。
?
總結
以上是生活随笔為你收集整理的redis持久化实现原理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux fork()函数底层Copy
- 下一篇: redis 日志重写BGREWRITEA