15天玩轉redis —— 第十篇 對快照模式的深入分析

一線碼農發表於2015-12-01

      我們知道redis是帶有持久化這個能力了,那到底持久化成到哪裡,持久化成啥樣呢???這篇我們一起來尋求答案。

 

一:快照模式

  或許在用Redis之初的時候,就聽說過redis有兩種持久化模式,第一種是SNAPSHOTTING模式,還是一種是AOF模式,而且在實戰場景下用的最多的

莫過於SNAPSHOTTING模式,這個不需要反駁吧,而且你可能還知道,使用SNAPSHOTTING模式,需要在redis.conf中設定配置引數,比如下面這樣:

# Save the DB on disk:
#
#   save <seconds> <changes>
#
#   Will save the DB if both the given number of seconds and the given
#   number of write operations against the DB occurred.
#
#   In the example below the behaviour will be to save:
#   after 900 sec (15 min) if at least 1 key changed
#   after 300 sec (5 min) if at least 10 keys changed
#   after 60 sec if at least 10000 keys changed
#
#   Note: you can disable saving completely by commenting out all "save" lines.
#
#   It is also possible to remove all the previously configured save
#   points by adding a save directive with a single empty string argument
#   like in the following example:
#
#   save ""

save 900 1
save 300 10
save 60 10000

上面三組命令也是非常好理解的,就是說900指的是“秒數”,1指的是“change次數”,接下來如果在“900s“內有1次更改,那麼就執行save儲存,同樣

的道理,如果300s內有10次change,60s內有1w次change,那麼也會執行save操作,就這麼簡單,看了我剛才說了這麼幾句話,是不是有種直覺在

告訴你,有兩個問題是不是要澄清一下:

 

1.  上面這個操作應該是redis自身進行的同步操作,請問是否可以手工執行save呢? 

     

   當然可以進行手工操作,redis提供了兩個操作命令:save,bgsave,這兩個命令都會強制將資料重新整理到硬碟中,如下圖:

 

2. 看上面的圖,貌似bgsave是開啟單獨執行緒的,請問是嗎?

 

     確實如你所說,bgsave是開啟次執行緒進行資料重新整理的,不信的話我們來看看程式碼,它的程式碼是在rdb.c原始檔中,如下:

從上面的程式碼中,有沒有看到一個重點,那就是fork方法,它就是一些牛人口中說的什麼fork出一個執行緒,今天你也算終於看到了,其實redis並不是單純

的單執行緒服務,至少fork告訴我們,它在一些場景下也是會開啟工作執行緒的,然後可以看到程式碼會在工作執行緒中執行同步的bgsave操作,就這麼簡單。

 

 3. 能簡單說下saveparams引數在redis原始碼中的邏輯嗎?

 

     可以的,其實在redis中有一個週期性函式,叫做serverCron,它會週期性啟動,大概會做七件事情,如redis註釋所說:

/* This is our timer interrupt, called server.hz times per second.
 * Here is where we do a number of things that need to be done asynchronously.
 * For instance:
 *
 * - Active expired keys collection (it is also performed in a lazy way on
 *   lookup).
 * - Software watchdog.
 * - Update some statistic.
 * - Incremental rehashing of the DBs hash tables.
 * - Triggering BGSAVE / AOF rewrite, and handling of terminated children.
 * - Clients timeout of different kinds.
 * - Replication reconnection.
 * - Many more...
 *
 * Everything directly called here will be called server.hz times per second,
 * so in order to throttle execution of things we want to do less frequently
 * a macro is used: run_with_period(milliseconds) { .... }
 */

int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) {

 

 上面的紅色字型就是做了我們所關心的save操作,看過方法的註釋,接下來我們來找一下具體邏輯。

 

從上面這段程式碼邏輯,你應該可以發現以下幾點:

 

<1>. saveparams引數是在server物件下面,而server物件正好是redisServer型別,如下圖:

 

從上面圖中 *saveparams 的註釋上來看,你應該知道*saveparams是saveparam型別的陣列,那現在是不是有強烈的好奇心想看一下saveparam

型別是怎麼定義的的呢??? 如下圖:

可以看到,saveparam引數裡面有兩個引數,seconds就是儲存秒數,changes就是改變數,而這二個引數就對應著我們配置檔案中的900 0 這樣的

配置節,想起來的沒有哈~~~

 

<2>  然後我們通過if發現,如果終滿足,就會最終呼叫rdbSaveBackground來持久化我們的rdb檔案,簡單吧。。。

 

好了,大概就這樣了,希望對你有幫助。

相關文章