寫在前面
今天繼續學習redis後面的知識。
Redis 哨兵機制
哨兵 Sentinel 機制
Sentinel(哨兵)是 Redis 的高可用性解決方案。由一個或多個 Sentinel 例項組成的 Sentinel 系統可以監視任意多個主伺服器,以及這些主伺服器屬下的所有從伺服器。當被監視的主伺服器進入下線狀態時,Sentinel 會自動將下線主伺服器屬下的某個從伺服器升級為新的主伺服器。簡單來說,哨兵就是帶有自動故障轉移功能的主從架構。
無法解決:
- 單節點併發壓力問題
- 單節點記憶體和磁碟物理上限
哨兵架構原理
Redis 叢集
叢集
Redis 從 3.0 開始支援 Cluster 模式。Redis 叢集支援節點的自動發現、支援從主節點的選舉和容錯、支援線上分片(sharding)等特性。
PING PONG 協議(心跳機制)
叢集搭建
建立叢集
-
準備環境安裝 Ruby 以及 Redis 叢集依賴
yum install -y ruby rubygems # https://rubygems.org/gems/redis/versions gem install redis-xxx.gem
-
在一臺機器建立 7 個目錄
# 建立目錄並複製配置檔案 cp /usr/local/soft/bigdata17/redis-install/redis-7.0.0/redis.conf ./7000/ cp /usr/local/soft/bigdata17/redis-install/redis-7.0.0/redis.conf ./7001/ cp /usr/local/soft/bigdata17/redis-install/redis-7.0.0/redis.conf ./7002/ cp /usr/local/soft/bigdata17/redis-install/redis-7.0.0/redis.conf ./7003/ cp /usr/local/soft/bigdata17/redis-install/redis-7.0.0/redis.conf ./7004/ cp /usr/local/soft/bigdata17/redis-install/redis-7.0.0/redis.conf ./7005/ cp /usr/local/soft/bigdata17/redis-install/redis-7.0.0/redis.conf ./7007/
-
修改不同目錄配置檔案
# 編輯配置檔案(例如 ./7000/redis.conf) port 7000 # 修改埠 # bind 127.0.0.1 -::1 # 開啟遠端連線 protected-mode no daemonize yes # 開啟後臺執行 dbfilename dump-7000.rdb # 每臺機器的檔案不能一樣 cluster-enabled yes # 開啟叢集模式 cluster-config-file nodes-7000.conf # 叢集節點配置檔案 cluster-node-timeout 5000 # 叢集節點超時時間 appendonly yes # 開啟 AOF 持久化 appendfilename "appendonly-7000.aof" # 修改 AOF 檔名 appenddirname "appendonlydir-7000"
-
指定不同目錄配置檔案啟動七個節點
redis-server 7000/redis.conf redis-server 7001/redis.conf redis-server 7002/redis.conf redis-server 7003/redis.conf redis-server 7004/redis.conf redis-server 7005/redis.conf redis-server 7006/redis.conf
-
複製叢集操作指令碼到 bin 目錄中
cp /usr/local/soft/bigdata17/redis-install/redis-7.0.0/src/redis-trib.rb /usr/local/soft/redis/bin/
對於 Redis 7.0.0 之後的版本,使用以下命令:
redis-cli --cluster create 192.168.40.110:7000 192.168.40.110:7001 192.168.40.110:7002 192.168.40.110:7003 192.168.40.110:7004 192.168.40.110:7005 --cluster-replicas 1
-
檢視叢集狀態
# 檢視叢集狀態 redis-cli --cluster check 192.168.40.110:7000
叢集節點狀態說明
-
主節點
- 主節點存在 hash slots,且主節點的 hash slots 沒有交叉
- 主節點不能刪除
- 一個主節點可以有多個從節點
- 主節點當機時多個副本之間自動選舉主節點
-
從節點
- 從節點沒有 hash slots
- 從節點可以刪除
- 從節點不負責資料的寫,只負責資料的同步
使用叢集
-
新增節點(預設為從)
# 新增主節點 redis-cli --cluster add-node 192.168.40.110:7006 192.168.40.110:7000 --cluster-slave
注意:1. 該節點必須以叢集模式啟動 2. 預設情況下該節點是以 master 節點形式新增
-
刪除副本節點
# 刪除節點 redis-trib.rb del-node 192.168.40.110:7002 0ca3f102ecf0c888fc7a7ce43a13e9be9f6d3dd1
注意: 1. 被刪除的節點必須是從節點或沒有被分配 hash slots 的節點
Redis 面試題與理解
穿透(要查詢的資料根本不存在)
穿透指使用者查詢資料時,如果資料既不存在於資料庫中,也不存在於快取中,那麼每次請求都會直接訪問資料庫,從而繞過快取,導致資料庫負載增加。
穿透解決方案
-
對空值進行快取
類似於上面的例子,雖然資料庫中沒有 id=-1234 的使用者資料,但可以在 Redis 中快取一個空值(key=-1234,value=null),以避免頻繁查詢資料庫。 -
實時監控
對 Redis 進行實時監控,發現命中率下降時進行排查,結合運維人員分析訪問物件和資料,設定黑名單限制服務。 -
使用布隆過濾器
使用 BitMap 作為布隆過濾器,將所有可訪問的資源透過簡單的對映關係放入布隆過濾器中,當請求到來時,先進行布隆過濾器判斷,如果有則放行,否則攔截。 -
介面校驗
對無效請求(例如 id=-1234)進行攔截,防止其到達 Redis 或資料庫。
雪崩(一批資料有,但過期時間到了)
雪崩指大量資料在同一時刻過期,導致大量請求落到資料庫,造成資料庫壓力增加,嚴重時可能導致資料庫當機。
雪崩解決方案
-
使用互斥鎖(Mutex Lock)或分散式鎖
只允許一個請求訪問後端資料來源,其他請求等待並共享結果。 -
將失效時間分散開
使用隨機數生成快取的過期時間,避免集中失效。 -
使用多級快取架構
例如使用 nginx 快取 + Redis 快取 + 其他快取,不同層使用不同快取,可靠性更強。 -
設定快取標記
記錄快取資料是否過期,過期時觸發後臺執行緒更新實際的 key。 -
設定熱點資料的永不過期或較長過期時間
減少熱點資料失效的機會。
擊穿(針對某一個資料突然過期,直接查資料庫)
擊穿指高併發情況下,當一個 key 突然失效,大量請求直接訪問資料庫,可能導致資料庫負載過高。
擊穿解決方案
-
為快取資料設定不同的過期時間
避免集中失效,監控資料,適時調整。 -
引入兩級快取架構
使用本地快取(如 Guava Cache)作為第一級快取,Redis 作為第二級快取,設定不同的過期時間。 -
針對熱點資料預載入
保證快取不會在同一時間全部失效。
總結
如果大量的請求在redis上得不到響應,那麼就會導致這些請求會直接去訪問DB,導致DB的壓力瞬間變大而卡死或者當機。
- 大量高併發請求打在 Redis 上
- Redis 上的資源未能響應時,直接訪問資料庫
- 資料庫壓力瞬間增大,可能導致資料庫當機,引發一系列“災害”