1. 程式人生 > >java架構之路-(Redis專題)Redis的高效能和持久化

java架構之路-(Redis專題)Redis的高效能和持久化

  上次我們簡單的說了一下我們的redis的安裝和使用,這次我們來說說redis為什麼那麼快和持久化資料

  在我們現有的redis中(5.0.*之前的版本),Redis都是單執行緒的,那麼單執行緒的Redis為什麼還會有那麼高的效率呢?因為它所有的資料都在記憶體中,所有的運算都是記憶體級別的運算,而且單執行緒避免了多執行緒的切換中效能損耗的問題,正因為Redis是單執行緒,所以我們要小心使用Redis指令,對於那些耗時的指令(比如keys),我們一定要謹慎使用。

  在併發環境中,我們Redis的單執行緒並不是執行緒1請求了,而我們的執行緒2就無法繼續請求了,而他的內部是採用了IO多路複用,redis利用epoli來實現IO多路複用,將連線資訊和事件放在佇列中,依次放到事件分派器,事件分派器將事件分發給我們的事件處理器來執行指令操作。

 

  redis預設支援最大連線數是10000,我們通過設定我們的redis.conf來指定我們的最大連線數,# maxclients 10000 => maxclients 100,大致在539行,或者我們輸入/maxclients 可以快速查詢到我們需要改的配置,進入我們的客戶端,輸入$ CONFIG GET maxclients,即可檢視我們的客戶端最大連線數。

127.0.0.1:6379> CONFIG GET maxclients
1) "maxclients"
2) "100"

高階命令

  我們輸入keys *,既可以返回我們的全部鍵的資料,一般不推薦使用,如果資料量過大,會相當消耗效能的。

  scan,scan提供了三個引數,第一個是cursor整數值,第二個是key的正則模式。第三個是第一次遍歷的key的數量,並不是符合條件的結果的數量,第一次遍歷時,cursor值為0,然後我們將返回結果中第一個整數作為下一次遍歷的cursor。一直遍歷到cursor值為0時結束。

127.0.0.1:6379> scan 0 match key* count 5
1) "6"
2) 1) "key6"
   2) "key4"
   3) "key1"
127.0.0.1:6379> scan 6 match key* count 5
1) "0"
2) 1) "key5"
   2) "key2"
   3) "key3"

Info:檢視redis服務執行資訊,分為 9 大塊,每個塊都有非常多的引數,這 9 個塊分別是: 

Server 伺服器執行的環境引數 

Clients 客戶端相關資訊 

Memory 伺服器執行記憶體統計資料 

Persistence 持久化資訊 

Stats 通用統計資料 

Replication 主從複製相關資訊 

CPU CPU 使用情況 

Cluster 叢集資訊 

KeySpace 鍵值對統計數量資訊

日誌

redis.conf檔案配置logfile來配置我們的log日誌資訊。大概在137行。

logfile "logForRedis.log"

 Redis持久化

  持久化主要分為三種,RDB,AOF和混合模式(4.0.*以後的模式)。

RDB快照模式

  在預設情況下,Redis將記憶體資料庫快照儲存為*.rdb的二進位制檔案。我用的是5.0.5版本,預設是開啟我們的RDB快照模式的,大致在253行,我們看到dbfilename dump.rdb,就是我們要以dump.rdb的檔案來儲存,儲存位置在263行的dir ./ 也就是我們的當前路徑(這裡可以設定絕對路徑)。  

  我們在大概218行可以看到三個save,也就是我們RDB的儲存策略

save 900 1 //表示在900秒內,發生了一次變動,我們就生成一次快照,變動只是資料的變動,get並不算變動

save 300 10 //表示在300秒內,發生了十次變動,我們就生成一次快照

save 60 10000 //表示在60秒內,發生了一萬次變動,我們就生成一次快照

三者條件滿足其一就儲存一次,他們之間是一個或者的關係,如果三個條件都未滿足,這時宕機可能造成資料的丟失。

  我們還可以通過進入redis-cli客戶端以後,我們手動輸入save或者bgsave來生成我們的dump.rdb檔案。我們的redis服務端配置是採用bgsave的方式來儲存的。我們來看一下save和bgsave的比較。

命令 save bgsave
IO型別 同步 非同步
是否阻塞redis其它命令 否(在生成子程序執行呼叫fork函式時會有超級短暫的阻塞)
時間複雜度 O(n) O(n)
優點 不會消耗額外記憶體 不阻塞客戶端命令
缺點 阻塞客戶端命令 需要fork子程序,消耗記憶體

AOF命令模式

  我們為什麼成為AOF叫做命令模式呢?我們的AOF其實是儲存了我們每一個操作的動作,也就是我們每一個Redis指令,我們只需要設定appendonly yes即可,大概在699行。下面的appendfilename是我們需要儲存aof的檔名,rdb中提到的dir對應的也是aof檔案的儲存路徑。這樣的持久化,其實也不是每次都要向磁碟寫入資料的,他有三個選項供我們來修改。

  appendfsync always:每次有新命令追加到 AOF 檔案時就執行一次 fsync ,非常慢,也非常安全。

  appendfsync everysec:每秒 fsync 一次,足夠快(和使用 RDB 持久化差不多),並且在故障時只會丟失 1 秒鐘的資料。

  appendfsync no:從不 fsync ,將資料交給作業系統來處理。更快,也更不安全的選擇。

  大概在728-730行設定這三種策略,預設的每秒一次,也是推薦使用的,三種策略只能選擇其中一種生效。一組set testkey testvalue命令大概這樣的

*3 表示佔了幾個位置,*3表示佔了三個位置,也就是*** *** *** 樣式的命令
$3  表示下面命令佔位的長度
set  就是我們實際的命令
$7  表示下一個命令佔位的長度
testkey  就是我們實際的命令
$9  表示下一個命令佔位的長度
testvalue  就是我們實際的命令

  我們假象一下輸入了一百次incr article:xiaocai命令,我們現在要使用AOF來恢復我們的檔案,那麼指令incr article:xiaocai就要儲存100次,恢復100次,貌似效率不高啊。這裡就提到了我們的AOF檔案重寫。也就是把一些指令重新組合生成新的指令,但保證資料的準確性。我們來看一下,我們先經歷三次set命令,key值是一樣的,我很容易知道,這裡set了三次,但前兩次並沒有什麼卵用,最後一次將我們的值已經覆蓋掉了。

127.0.0.1:6379> set xiaocai 123
OK
127.0.0.1:6379> set xiaocai 456
OK
127.0.0.1:6379> set xiaocai 666
OK
127.0.0.1:6379> BGREWRITEAOF
Background append only file rewriting started
127.0.0.1:6379> 

這時應該生產三條AOF指令,我們來執行我們的AOF重寫命令$ BGREWRITEAOF,重寫之後,前面的set就不見了,相同鍵的set,只保留最後一次的set。可能造成亂碼(我們5.0.5預設開啟了混合模式,後面會說),但是確實壓縮了,恢復也是可以成功的。我們來看一下我該掉預設配置後的AOF重寫檔案。

我們可以看到我們前兩條指令被優化去掉了,這也就是我們的AOF重寫。

auto-aof-rewrite-min-size 64mb //表示當我們的aof檔案達到64M時,我們就重寫一次,建議使用預設配置就可以,太多了,重寫耗時長,太小了,經常重寫,消耗效能。

auto-aof-rewrite-percentage 100 這個表示。//當我們的配置增加了100%我們就重寫一次
  說到這,兩種持久化的方式就都說完了,我們來看一下誰才是王者,誰才是最優質的。

命令 RDB AOF
啟動優先順序
體積
恢復速度
資料安全性 容易丟失資料 根據策略決定

注意:當我們同時開啟RDB和AOF時,當我們重啟redis時,Redis會優先去載入AOF檔案來恢復我們的資料,相對來說AOF的資料更完整

混合模式

  重啟redis時,我們很少使用RDB來恢復記憶體資料,因為會丟失大量的資料。通常我們使用AOF指令來恢復,但AOF的效能相比RDB要慢很多,看到這我們還是覺得並沒有一種完美的解決方案,來持久化我們的資料,這時Redis4.0就引出了我們混合持久化。我們可以通過設定 # aof-use-rdb-preamble yes來開啟我們的混合持久化,這時我們生成的持久化檔案內部還是AOF的,但我們重寫的時候,會將這些AOF的指令重寫為二進位制檔案。這樣我們就綜合了RDB和AOF的優勢,在恢復資料的時候大部分是執行二進位制檔案的,小部分來執行我們的AOF指令操作,使我們的恢復資料的效率更高,在備份的時候是以AOF來備份的,也保證了資料的安全性。

總結

  這次我們主要說了我們的Redis的記憶體高效能,Redis在記憶體來計算的,再就是我們的高階設定keys *(少用或者別用)和我們的scan命令,再就是Redis的持久化,兩種RDB和AOF,RDB持久化可能資料丟失,但是二進位制檔案恢復的快,AOF持久化幾乎不會丟資料,但是是指令的模式,恢復資料效率低。由於都有缺點我們引入了混合模式,儲存用AOF來存,恢復用RDB+AOF來恢復。再就是一個重點是save和bgsave的區別。記住bgsave是後臺執行的,需要fork子程序,消耗記憶體,但是不阻塞Redis的其它執行緒。

  今天就說這麼多,下次博文我們說說我們的主從模式,哨兵模式和我們的Redis叢集。


 


 最進弄了一個公眾號,小菜技術,歡迎大家的加入

&n