日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

为什么子进程每次执行顺序不一样_看完这篇还不懂Redis的RDB持久化,你来打我...

發布時間:2023/12/2 数据库 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 为什么子进程每次执行顺序不一样_看完这篇还不懂Redis的RDB持久化,你来打我... 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

推薦觀看:

Redis緩存穿透的終極解決方案,手寫布隆過濾器_嗶哩嗶哩 (゜-゜)つロ 干杯~-bilibili?www.bilibili.comP8架構師串講:Redis,zookeeper,kafka,Nginx等技術_嗶哩嗶哩 (゜-゜)つロ 干杯~-bilibili?www.bilibili.com

一、為什么需要持久化

redis里有10gb數據,突然停電或者意外宕機了,再啟動的時候10gb都沒了?!所以需要持久化,宕機后再通過持久化文件將數據恢復。

二、優缺點

1、rdb文件

rdb文件都是二進制,很小。比如內存數據有10gb,rdb文件可能就1gb,只是舉例。

2、優點

  • 由于rdb文件都是二進制文件,所以很小,在災難恢復的時候會快些。
  • 他的效率(主進程處理命令的效率,而不是持久化的效率)相對于aof要高(bgsave而不是save),因為每來個請求他都不會處理任何事,只是bgsave的時候他會fork()子進程且可能copyonwrite,但copyonwrite只是一個尋址的過程,納秒級別的。而aof每次都是寫盤操作,毫米級別。沒法比。

3、缺點

數據可靠性比aof低,也就是會丟失的多。因為aof可以配置每秒都持久化或者每個命令處理完就持久化一次這種高頻率的操作,而rdb的話雖然也是靠配置進行bgsave,但是沒有aof配置那么靈活,也沒aof持久化快,因為rdb每次全量,aof每次只追加。

三、RDB持久化的兩種方法

配置文件也可以配置觸發rdb的規則。配置文件配置的規則采取的是bgsave的原理。

1、save

1.1、描述

同步、阻塞

1.2、缺點

致命的問題,持久化的時候redis服務阻塞(準確的說會阻塞當前執行save命令的線程,但是redis是單線程的,所以整個服務會阻塞),不能繼對外提供請求,GG!數據量小的話肯定影響不大,數據量大呢?每次復制需要1小時,那就相當于停機一小時。

2、bgsave

2.1、描述

異步、非阻塞

2.2、原理

fork() + copyonwrite

2.3、優點

他可以一邊進行持久化,一邊對外提供讀寫服務,互不影響,新寫的數據對我持久化不會造成數據影響,你持久化的過程中報錯或者耗時太久都對我當前對外提供請求的服務不會產生任何影響。持久化完會將新的rdb文件覆蓋之前的。

四、fork()

bgsave原理是fork() + copyonwrite,那么現在來聊一下fork()

1、fork()是什么

fork()是unix和linux這種操作系統的一個api,而不是Redis的api。

2、fork()有什么用

fork()用于創建一個子進程,注意是子進程,不是子線程。fork()出來的進程共享其父類的內存數據。僅僅是共享fork()出子進程的那一刻的內存數據,后期主進程修改數據對子進程不可見,同理,子進程修改的數據對主進程也不可見。

比如:A進程fork()了一個子進程B,那么A進程就稱之為主進程,這時候主進程子進程所指向的內存空間是同一個,所以他們的數據一致。但是A修改了內存上的一條數據,這時候B是看不到的,A新增一條數據,刪除一條數據,B都是看不到的。而且子進程B出問題了,對我主進程A完全沒影響,我依然可以對外提供服務,但是主進程掛了,子進程也必須跟隨一起掛。這一點有點像守護線程的概念。Redis正是巧妙的運用了fork()這個牛逼的api來完成RDB的持久化操作。

五、Redis中的fork()

Redis巧妙的運用了fork()。當bgsave執行時,Redis主進程會判斷當前是否有fork()出來的子進程,若有則忽略,若沒有則會fork()出一個子進程來執行rdb文件持久化的工作,子進程與Redis主進程共享同一份內存空間,所以子進程可以搞他的rdb文件持久化工作,主進程又能繼續他的對外提供服務,二者互不影響。

我們說了他們之后的修改內存數據對彼此不可見,但是明明指向的都是同一塊內存空間,這是咋搞得?肯定不可能是fork()出來子進程后順帶復制了一份數據出來,如果是這樣的話比如我有4g內存,那么其實最大有限空間是2g,我要給rdb留出一半空間來,扯淡一樣!那他咋做的?采取了copyonwrite技術。

六、copyonwrite

很簡單,現在不就是主進程和子進程共享了一塊內存空間,怎么做到的彼此更改互不影響嗎?

1、原理

主進程fork()子進程之后,內核把主進程中所有的內存頁的權限都設為read-only,然后子進程的地址空間指向主進程。這也就是共享了主進程的內存,當其中某個進程寫內存時(這里肯定是主進程寫,因為子進程只負責rdb文件持久化工作,不參與客戶端的請求),CPU硬件檢測到內存頁是read-only的,于是觸發頁異常中斷(page-fault),陷入內核的一個中斷例程。

中斷例程中,內核就會把觸發的異常的頁復制一份(這里僅僅復制異常頁,也就是所修改的那個數據頁,而不是內存中的全部數據),于是主子進程各自持有獨立的一份。數據修改之前的樣子

數據修改之后的樣子

2、回到原問題

其實就是更改數據的之前進行copy一份更改數據的數據頁出來,比如主進程收到了set k 1請求(之前k的值是2),然后這同時又有子進程在rdb持久化,那么主進程就會把k這個key的數據頁拷貝一份,并且主進程中k這個指針指向新拷貝出來的數據頁地址上,然后進行更改值為1的操作,這個主進程k元素地址引用的新拷貝出來的地址,而子進程引用的內存數據k還是修改之前的。

3、一段話總結

copyonwritefork()出來的子進程共享主進程的物理空間,當主子進程有內存寫入操作時,read-only內存頁發生中斷,將觸發的異常的內存頁復制一份(其余的頁還是共享主進程的)。

4、額外補充

在 Redis 服務中,子進程只會讀取共享內存中的數據,它并不會執行任何寫操作,只有主進程會在寫入時才會觸發這一機制,而對于大多數的 Redis 服務或者數據庫,寫請求往往都是遠小于讀請求的,所以使用fork()加上寫時拷貝這一機制能夠帶來非常好的性能,也讓BGSAVE這一操作的實現變得很簡單。

七、疑問

0、調用fork()也會阻塞啊

我只能說沒毛病,但是這個阻塞真的可以忽略不計。尤其是相對于阻塞主線程的save。

1、會同時存在多個子進程嗎?

不會,主進程每次收到bgsave命令需要fork()子進程之前都會判斷是否存在子進程了,若存在也會忽略掉這次bgsave請求。若不存在我會fork()出子進程進行工作。

為什么這么搞?

我猜測原因如下:

  • 如果支持并行存在多個子進程,那么不僅會拉低服務器性能,還會造成數據問題,比如八點的bgsave在工作,九點又來個bgsave命令。這時候九點的先執行完了,八點的后執行完了,那九點的不白執行了嗎?這是我所謂的數據問題。再比如,都沒執行完,十點又開一個bgsave,越積越多,服務器性能被拉低。
  • 那為什么不阻塞?判斷有子進程在工作,就等待,等他執行完我在上場,那一樣,越積越多,文件過大,只會造成堆積。
  • 2、如果沒有copyonwrite這種技術是什么效果?

  • 假設是全量復制,那么內存空間直接減半,浪費資源不說,數據量10g,全量復制這10g的時間也夠長的。這誰頂得住?
  • 如果不全量復制,會是怎樣?相當于我一邊復制,你一邊寫數據,看著貌似問題不大,其實不然。比如現在Redis里有k1的值是1,k2的值是2,比如bgsave了,這時候rdb寫入了k1的值,在寫k2的值之前時,有個客戶端請求
  • set k1 11 set k2 22

    那么持久化進去的是k2 22,但是k1的值還是1,而不是最新的11,所以會造成數據問題,所以采取了copyonwrite技術來保證觸發bgsave請求的時候無論你怎么更改,都對我rdb文件的數據持久化不會造成任何影響。

    八、總結

    此篇都是重點,廢話很少。沒啥可總結的。

    總結

    以上是生活随笔為你收集整理的为什么子进程每次执行顺序不一样_看完这篇还不懂Redis的RDB持久化,你来打我...的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。