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