1. 程式人生 > >redis啟動載入過程、資料持久化

redis啟動載入過程、資料持久化

https://www.cnblogs.com/cuijl/p/7992433.html

 

付出才有回報,敢於嘗試才能成功。

 

隨筆- 89  文章- 0  評論- 0 

redis啟動載入過程、資料持久化

背景

  公司一年的部分業務資料放在redis伺服器上,但資料量比較大,單純的string型別資料一年就將近32G,而且是經過壓縮後的。

  所以我在想能否通過獲取string資料的時間改為儲存list資料型別,或者將資料持久化到硬碟上,或者放在不同庫上,解決未來資料過大導致down機的問題。

相關知識點

  • 資料持久化
  • 資料載入

 

資料持久化

  • filesnapshotting(快照) 
  • Append-only(aof)

filesnapshotting

  預設redis是會以快照的形式將資料持久化到磁碟的(一個二進 制檔案,xx.rdb)

  在配置檔案中的格式是:save N M表示在N秒之內,redis至少發生M次修改則redis抓快照到磁碟。

  當然我們也可以手動執行save或者bgsave(非同步)做快照。

  工作原理簡單介紹:當redis需要做持久化時,redis會fork一個子程序;子程序將資料寫到磁碟上一個臨時RDB檔案中;當子程序完成寫臨時檔案後,將原來的RDB替換掉,這樣的好處就是可以copy-on-write

缺點:filesnapshotting方法在redis異常死掉時, 最近的資料會丟失(丟失資料的多少視你save策略的配置),所以這是它最大的缺點,當業務量很大時,丟失的資料是很多的

Appened-only

  可以做到全部資料不丟失,但redis的效能就要差些。AOF就可以做到全程持久化,只需要在配置檔案中開啟(預設是no),appendonly yes開啟AOF之後,可以選擇三種不同的策略,都會把它新增到aof檔案中,當redis重啟時,將會讀取AOF檔案進行“重放”以恢復到 redis關閉前的最後時刻。

AOF的三種策略

appendfsync :appendfsync always

每提交一個修改命令都呼叫fsync重新整理到AOF檔案,非常非常慢,但也非常安全;

appendfsync everysec每秒鐘都呼叫fsync重新整理到AOF檔案,很快,但可能會丟失一秒以內的資料;

appendfsync no依靠OS進行重新整理,redis不主動重新整理AOF,這樣最快,但安全性就差。預設並推薦每秒重新整理,這樣在速度和安全上都做到了兼顧。

LOG Rewriting隨著修改資料的執行AOF檔案會越來越大,其中很多內容記錄某一個key的變化情況。

因此redis有了一種比較有意思的特性:在後臺重建AOF檔案,而不會影響client端操作。在任何時候執行BGREWRITEAOF命令,都會把當前記憶體中最短序列的命令寫到磁碟,這些命令可以完全構建當前的資料情況,而不會存在多餘的變化情況(比如狀態變化,計數器變化等),縮小的AOF檔案的大小。

所以當使用AOF時,redis推薦同時使用BGREWRITEAOF

LOG Rewrite的工作原理:同樣用到了copy-on-write:首先redis會fork一個子程序;子程序將最新的AOF寫入一個臨時檔案;父程序 增量的把記憶體中的最新執行的修改寫入(這時仍寫入舊的AOF,rewrite如果失敗也是安全的);當子程序完成rewrite臨時檔案後,父程序會收到 一個訊號,並把之前記憶體中增量的修改寫入臨時檔案末尾;這時redis將舊AOF檔案重新命名,臨時檔案重新命名,開始向新的AOF中寫入。

Redis啟動載入過程

1. 初始化全域性伺服器配置

2. 載入配置檔案(如果指定了配置檔案,否則使用預設配置)

3. 初始化伺服器

4. 載入資料庫

5. 網路監聽

下面對上面這些步驟進行介紹

初始化全域性伺服器配置

初始化全域性伺服器配置通過initServerConfig()函式完成,主要是初始化server變數

初始化的內容包括下面幾個方面:

1. 網路監聽相關,如繫結地址,TCP埠等 
2. 虛擬記憶體相關,如swap檔案、page大小等 
3. 儲存機制,多長時間內有多少次更新才進行儲存 
4. 複製相關,如是否是slave,master地址、埠 
5. Hash相關設定 
6. 初始化命令表

如其中的儲存機制中,伺服器初始化策略為:

複製程式碼

// 1小時內1次更新
appendServerSaveParams(60*60,1);

// 5分鐘內100次更新
appendServerSaveParams(300,100);

// 1分鐘內10000次更新
appendServerSaveParams(60,10000);

複製程式碼

如果在啟動伺服器時,指定了配置檔案,則會在下面的“載入配置檔案”步驟中,根據配置檔案內容,更改其中的某些伺服器配置。

載入配置檔案

如果指定了配置檔案,Redis使用loadServerConfig()函式載入配置檔案,使用標準I/O庫開啟配置檔案,迴圈讀取每一行然後覆蓋上一步進行的預設配置。

需要注意的是,下載Redis後代碼包中有一個預設配置檔案,如果啟動Redis伺服器時,不指定配置檔案,Redis不會使用這個預設檔案的配置,而是使用上一步“初始化全域性伺服器配置”中的配置。在預設配置檔案中提供的配置項與上一步預設初始化的配置有些事不一樣的,所以如果沒有指定配置檔案,千萬不能認為Redis的行為會按照預設配置檔案進行,最典型的一個例子,在預設配置檔案中的資料儲存策略是:

複製程式碼

# 15分鐘內1次更新
save 900 1

# 5分鐘內100次更新
save 300 10

# 1分鐘內10000次更新
save 60 10000

複製程式碼

而預設初始化的全域性配置中資料儲存策略:appendServerSaveParams的配置項

初始化伺服器

初始化伺服器的工作在initServer()函式中,主要是完成前面未完成的工作,繼續對server變數初始化,如設定訊號處理、建立clients、slaves列表,建立Pub/Sub通道列表,同時還會建立共享物件:

shared.crlf = createObject(REDIS_STRING,sdsnew("\r\n"));
shared.ok = createObject(REDIS_STRING,sdsnew("+OK\r\n"));
shared.err = createObject(REDIS_STRING,sdsnew("-ERR\r\n"));
shared.emptybulk = createObject(REDIS_STRING,sdsnew("$0\r\n\r\n"));

最後,如果啟用了虛擬記憶體機制,還需要初始化虛擬記憶體相關,如Thread I/O等。

載入資料庫

在完成了上面的所有的初始化工作之後,Redis開始載入資料到記憶體中,如果啟用了appendonly了,則Redis從appendfile載入資料,否則就從dbfile載入資料

1. 從appendfile中載入資料:loadAppendOnlyFile()函式

在此之前,我們先來看一下appendfile裡面儲存了什麼,如我執行了下面兩條命令(記得在配置檔案中開啟appendonly):

redis> SET mykey001 myvalue001
OK
redis> GET mykey001
"myvalue001"

使用cat命令檢視appendonly.aof的內容:

複製程式碼

$ cat appendonly.aof
*2
$6
SELECT
$1
0
*3
$3
SET
$8
mykey001
$10
myvalue001

複製程式碼

在appendonly.aof檔案中儲存的正是從客戶端發過來的請求命令,還可以看到對於GET命令,並沒有儲存。

既然appendonly.aof中儲存了所有寫入資料的請求命令,那麼在載入資料的時候只要重新執行一遍這些命令即可。

事實上Redis也正是這麼做的,在開始載入之前暫時關閉appendonly,然後Redis建立一個假的Redis客戶端。

然後讀取appendonly.aof檔案中的命令,在假的Redis客戶端上下文中執行,同時伺服器也不對該客戶端做任何應答。

如果載入過程中實體記憶體不夠用,並且Redis開啟了VM,則還需要處理swap操作,最後載入完成後重新設定appendonly標誌。

2. 從dbfile中載入資料:rdbLoad()函式

如果Redis沒有開啟appendonly,就需要從資料庫檔案中載入資料到記憶體,基本步驟如下:

a. 處理SELECT命令,即選擇資料庫 
b. 讀取key 
c. 讀取value 
d. 檢測key是否過期 
e. 新增新的物件到雜湊表 
f. 設定過期時間(如果需要) 
g. 如果開啟了VM,處理swap操作

網路監聽

在完成了初始化配置和資料載入後,Redis啟動監聽。Redis的網路庫沒有使用libevent或者libev,而是作者自己實現的一個非常輕量級的庫(主要實現在ae.c檔案中)

 

然而回到我的問題上,如果資料庫中資料已經放入了32G的資料,在啟動redis時載入資料庫這部分必定會相當相當慢,而且涉及到宕機的問題(實體記憶體到達峰值)

這時可能單臺redis很難解決這個問題,而應該考慮叢集。

作者:大胖兒在努力 本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段宣告,且在文章頁面明顯位置給出原文連線,否則保留追究法律責任的權利。

分類: NoSQL

好文要頂 關注我 收藏該文  

大胖兒在努力
關注 - 18
粉絲 - 8

+加關注

0

0

« 上一篇:MongoDB學習筆記
» 下一篇:高位位元組、低位位元組

posted @ 2017-12-06 14:14 大胖兒在努力 閱讀(1588) 評論(0) 編輯 收藏

重新整理評論重新整理頁面返回頂部

註冊使用者登入後才能發表評論,請 登入 或 註冊訪問網站首頁。

【推薦】超50萬VC++原始碼: 大型組態工控、電力模擬CAD與GIS原始碼庫!

 

相關博文:
· Redis資料儲存解決方案
· C# Redis
· redis 資料型別詳解 以及 redis適用場景場合
· REDIS 資料型別詳解 以及 REDIS適用場景場合
· Redis應用場景

 

最新新聞
· 清華畢業計算機教授遭持槍劫車!靠“貪心演算法”追回秒殺美國警察
· 位元組跳動涉訴訟365起 或難支撐750億美元超高估值
· 2018<1790,這才是中華民族最大危機?
· 美國網癮戒除中心:沒有電擊、隔絕WiFi,治一次18萬元
· 蘋果iTune和三星電視達成流媒體合作
» 更多新聞...

暱稱:大胖兒在努力
園齡:6年11個月
粉絲:8
關注:18

+加關注

< 2019年1月 >
30 31 1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31 1 2
3 4 5 6 7 8 9

隨筆分類

隨筆檔案

閱讀排行榜

推薦排行榜

Copyright ©2019 大胖兒在努力