Redis持久化之RDB


引子

今天遇到一個面試題,若是機器內存是4G,redis已經佔用了2G內存,這裏redis執行RDB持久化,可否持久化成功? 上一秒還在說本身熟悉redis,下一秒就被光速打臉了,發現本身竟然沒有深刻了解過redis的RDB持久化的機制。面試

1、Redis持久化的方式

redis持久化方式分爲兩種,分別是RDB和AOF。redis

  • RDB(Redis DataBase):將某一時刻內存的數據以二進制的形式保存到磁盤中,RDB的數據完整性比不上AOF,可是對redis的QPS不會有太大的影響。
  • AOF(Append Only File):將redis執行的命令按順序不斷追加到文件中,相似於MySQL的binlog日誌。 其中,RDB持久化又涉及到兩個操做命令,save和bgsave。
  • save:通常是手動操做,會阻塞redis主進行執行。
  • bgsave:經過配置文件來完成的RDB,執行的是bgsave命令,redis會fork一個子進程來執行持久化,只有在fork子進程的過程當中會短暫阻塞redis主進程,持久化的過程不會對主進行有影響。

2、fork和copyonwrite

Redis執行RDB持久化,主要依賴的是fork和copyonwrite技術。
fork函數是操做系統的API,用於從一個進程中建立一個子進程,這個子進程和父進程共享全部的內存信息、上下文、代碼區、引用的資源等。可是,這樣在子進程執行持久化的過程當中,主進程把內存中的數據修改了會怎麼辦呢?這裏就會使用到copyonwrite技術。ide

  1. 當主進程fork一個子進程出來後,內核會把主進程全部的內存頁都設置成read-only,此時,主進程和子進程都指向一樣的內存地址。 兩個進程共享內存
  2. 當主進程須要對內存進行修改時,發現須要修改的內存頁是read-only狀態,此時會觸發一頁異常中斷(page-fault)。內核會把須要修改的數據頁複製一份,把主進程的地址指向新的複製數據頁。 複製新內存數據後
  3. 最後主進程再在新的內存數據頁上進行修改操做。

3、總結

根據上面的技術,redis在執行RDB持久化的時候,持久化的內存數據就只會是fork子進程那一刻的內存數據,後續新的請求對持久化不會有影響。回到上面的面試題,redis是能夠執行持久化成功的。函數

4、其它問題

  1. RDB的過程當中,每次更新數據都須要複製一份原有的數據,對redis的性能是否會有影響? 由於redis的使用場景大部分是讀多寫少的場景,所以更新數據時須要先對原數據複製對redis帶來的性能影響是能夠接受的。
相關文章
相關標籤/搜索