【資料庫】Redis進階篇

xbmchina發表於2019-05-08

歡迎關注公眾號:【愛編碼】 如果有需要後臺回覆2019贈送1T的學習資料哦!!

繼續接著上一篇【資料庫】Redis基礎篇

事務

為了保證多條命令組合的原子性,Redis提供了簡單的事務功能以及整合Lua指令碼來解決這個問題。簡單介紹Redis中事務的使用方法以及它的侷限性。

127.0.0.1:6379> multi
OK
127.0.0.1:6379> sadd user:a:follow user:b
QUEUED
127.0.0.1:6379> zadd user:b:fans 1 user:a
QUEUED
127.0.0.1:6379> exec
1) (integer) 1
2) (error) WRONGTYPE Operation against a key holding the wrong kind of value
127.0.0.1:6379> sismember user:a:follow user:b
(integer) 1
複製程式碼

Redis提供了簡單的事務功能,將一組需要一起執行的命令放到multi和 exec兩個命令之間

multi命令代表事務開始exec命令代表事務結束。 它們之間的命令是原子順序執行的。 它不支援事務中的回滾特性

Lua指令碼

基本語法教程可參考下面這個網址: www.runoob.com/lua/lua-tut…

在Redis中執行Lua指令碼有兩種方法:eval和evalsha。

釋出訂閱

Redis提供了基於“釋出/訂閱”模式的訊息機制,此種模式下,訊息釋出 者和訂閱者不進行直接通訊,釋出者客戶端向指定的頻道(channel)釋出訊息,訂閱該頻道的每個客戶端都可以收到該訊息。

【資料庫】Redis進階篇

  1. 釋出訊息
publish channel:sports "Tim won the championship"
複製程式碼
  1. 訂閱訊息
subscribe channel:sports
複製程式碼

有關訂閱命令有兩點需要注意

  • 客戶端在執行訂閱命令之後進入了訂閱狀態,只能接收subscribe、 psubscribe、unsubscribe、punsubscribe的四個命令。
  • 新開啟的訂閱客戶端,無法收到該頻道之前的訊息,因為Redis不會對 釋出的訊息進行持久化。

Redis釋出訂閱與成熟MQ的比較

(1)MQ支援多種訊息協議,包括AMQP,MQTT,Stomp等,並且支援JMS規範,但Redis沒有提供對這些協議的支援; (2)MQ提供持久化功能,但Redis無法對訊息持久化儲存,一旦訊息被髮送,如果沒有訂閱者接收,那麼訊息就會丟失; (3)MQ提供了訊息傳輸保障,當客戶端連線超時或事務回滾等情況發生時,訊息會被重新傳送給客戶端,Redis沒有提供訊息傳輸保障。

總之,MQ所提供的功能遠比Redis釋出訂閱要複雜,畢竟Redis不是專門做釋出訂閱的,但是如果系統中已經有了Redis,並且需要基本的釋出訂閱功能,就沒有必要再安裝MQ了,因為可能MQ提供的功能大部分都用不到,而且你可以容忍redis釋出訂閱的缺點的話,可以考慮用它。

持久化

Redis支援RDB和AOF兩種持久化機制,持久化功能有效地避免因程式退出造成的資料丟失問題,當下次重啟時利用之前持久化的檔案即可實現資料恢復。

RDB持久化

RDB持久化是把當前程式資料生成快照儲存到硬碟的過程,觸發RDB持 久化過程分為手動觸發和自動觸發。

手動觸發和自動觸發操作方法參考這位大神的文章: www.cnblogs.com/ysocean/p/9…

RDB的優缺點 優點:

  1. RDB是一個緊湊壓縮的二進位制檔案,代表Redis在某個時間點上的資料快照。非常適用於備份,全量複製等場景。比如每6小時執行bgsave備份,並把RDB檔案拷貝到遠端機器或者檔案系統中(如hdfs),用於災難恢復。
  2. Redis載入RDB恢復資料遠遠快於AOF的方式。

缺點:

  1. RDB方式資料沒辦法做到實時持久化/秒級持久化。因為bgsave每次運 行都要執行fork操作建立子程式,屬於重量級操作,頻繁執行成本過高。
  2. RDB檔案使用特定二進位制格式儲存,Redis版本演進過程中有多個格式的RDB版本,存在老版本Redis服務無法相容新版RDB格式的問題。 針對RDB不適合實時持久化的問題,Redis提供了AOF持久化方式來解決。

AOF持久化

AOF(append only file)持久化:以獨立日誌的方式記錄每次寫命令,重啟時再重新執行AOF檔案中的命令達到恢復資料的目的。 AOF的主要作用是解決了資料持久化的實時性,目前已經是Redis持久化的主流方式。

開啟AOF,通過修改redis.conf配置檔案

appendonly yes    ##預設不開啟。
複製程式碼

AOF檔名通過appendfilename配置設定,預設檔名appendonly.aof。儲存路徑同RDB持久化方式一致,通過dir配置指定。

AOF的工作流程如下圖:

【資料庫】Redis進階篇

1)所有的寫入命令會追加到aof_buf(緩衝區)中。 2)AOF緩衝區根據對應的策略向硬碟做同步操作。 3)隨著AOF檔案越來越大,需要定期對AOF檔案進行重寫,達到壓縮的目的。 4)當Redis伺服器重啟時,可以載入AOF檔案進行資料恢復。

更詳細的工作原理可以參考書籍【Redis開發與運維(付磊)】 或者參考這篇文章: redisbook.readthedocs.io/en/latest/i…

溫馨提示 **場景:**AOF檔案可能存在結尾不完整的情況,比如機器突然掉電導致AOF尾部檔案命令寫入不全。

解決方法:

  1. 對於錯誤格式的AOF檔案,先進行備份,然後採用redis-check-aof --fix命令進行修復,修復後使用diff-u對比資料的差異,找出丟失的資料,有些可以人工修改補全。

  2. Redis為我們提供了aof-load-truncated配置來相容這種情況,預設開啟。載入AOF時,當遇到此問題時會忽略並繼續啟動,同時列印如下警告日誌:

# !!! Warning: short read while loading the AOF file !!!
# !!! Truncating the AOF at offset 397856725 !!!
# AOF loaded anyway because aof-load-truncated is enabled
複製程式碼

持久化的優化

Redis持久化功能一直是影響Redis效能的高發地。主要有以下方面

1. fork操作 起因:對於高流量的Redis例項OPS可達5萬以上,如果fork操作耗時在秒級別將拖慢Redis幾萬條命令執行,對線上應用延遲影響非常明顯。正常情況下fork耗時應該是每GB消耗20毫秒左右。可以在info stats統計中查latest_fork_usec指標獲取最近一次fork操作耗時,單位微秒。

優化: 1)優先使用物理機或者高效支援fork操作的虛擬化技術,避免使用Xen。 2)控制Redis例項最大可用記憶體,fork耗時跟記憶體量成正比,線上建議每個Redis例項記憶體控制在10GB以內。 3)合理配置Linux記憶體分配策略,避免實體記憶體不足導致fork失敗。 4)降低fork操作的頻率,如適度放寬AOF自動觸發時機,避免不必要的全量複製等。

2. CPU CPU開銷分析。子程式負責把程式內的資料分批寫入檔案,這個過程屬於CPU密集操作,通常子程式對單核CPU利用率接近90%。 CPU消耗優化。Redis是CPU密集型服務,不要做繫結單核CPU操作。由於子程式非常消耗CPU,會和父程式產生單核資源競爭。 不要和其他CPU密集型服務部署在一起,造成CPU過度競爭。如果部署多個Redis例項,儘量保證同一時刻只有一個子程式執行重寫工作。

3. 記憶體 記憶體消耗優化: 1)同CPU優化一樣,如果部署多個Redis例項,儘量保證同一時刻只有一個子程式在工作。 2)避免在大量寫入時做子程式重寫操作,這樣將導致父程式維護大量頁副本,造成記憶體消耗。

4. 硬碟 優化方法如下: a)不要和其他高硬碟負載的服務部署在一起。如:儲存服務、訊息佇列服務等。 b)AOF重寫時會消耗大量硬碟IO,可以開啟配置no-appendfsync-on-rewrite,預設關閉。表示在AOF重寫期間不做fsync操作。 c)當開啟AOF功能的Redis用於高流量寫入場景時,如果使用普通機械磁碟,寫入吞吐一般在100MB/s左右,這時Redis例項的瓶頸主要在AOF同步硬碟上。 d)對於單機配置多個Redis例項的情況,可以配置不同例項分盤儲存AOF檔案,分攤硬碟寫入壓力。

注:配置no-appendfsync-on-rewrite=yes時,在極端情況下可能丟失整個AOF重寫期間的資料,需要根據資料安全性決定是否配置。

5.AOF追加阻塞 當開啟AOF持久化時,常用的同步硬碟的策略是everysec,用於平衡效能和資料安全性。對於這種方式,Redis使用另一條執行緒每秒執行fsync同步硬碟。當系統硬碟資源繁忙時,會造成Redis主執行緒阻塞,

【資料庫】Redis進階篇

阻塞流程分析: 1)主執行緒負責寫入AOF緩衝區。 2)AOF執行緒負責每秒執行一次同步磁碟操作,並記錄最近一次同步時間。 3)主執行緒負責對比上次AOF同步時間:如果距上次同步成功時間在2秒內,主執行緒直接返回。如果距上次同步成功時間超過2秒,主執行緒將會阻塞,直到同步操作完成。

優化AOF追加阻塞問題主要是優化系統硬碟負載,優化方法參考第4點

總結

本文主要學習Redis的事務、釋出訂閱、以及持久化。 後續會繼續學習Redis叢集等方面的知識。

最後

如果對 Java、大資料感興趣請長按二維碼關注一波,我會努力帶給你們價值。覺得對你哪怕有一丁點幫助的請幫忙點個贊或者轉發哦。 關注公眾號**【愛編碼】,回覆2019**有相關資料哦。

【資料庫】Redis進階篇

相關文章