redis學習筆記(詳細)——高階篇

至安發表於2021-11-11

redis配置檔案介紹

linux環境下配置大於程式設計

redis 的配置檔案位於 Redis 安裝目錄下,檔名為 redis.conf。一般情況下,會單獨拷貝出來一份進行操作。來保證初始檔案的安全

config get * # 獲取全部的配置

include部分

組合多個配置。和Spring配置檔案類似,可以通過includes包含,redis.conf 作為總檔案,可以包含其他配置檔案!

network網路部分

網路相關配置

bind 127.0.0.1 # 繫結的ip
protected-mode yes # 保護模式
port 6379 # 預設埠

General部分

序號 配置項 說明
1 daemonize no Redis 預設不是以守護程式的方式執行,可以通過該配置項修改,
使用 yes 啟用守護程式(Windows 不支援守護執行緒的配置為 no )
2 tcp-backlog 設定tcp的backlog, backlog其實是一一個連線佇列,
backlog佇列總和 = 未完成三次握手佇列+已經完成三次握手佇列。
注意Linux核心會將這個值減小到/ proc/sys/ net/ core/somaxconn的值,
所以需要確認增大somaxconn和tcp_ max_ syn backlog兩個值
5 timeout 300 當客戶端閒置多少秒後關閉連線,如果指定為 0 ,表示關閉該功能
6 Tcp-keepalive 0 檢測連線是否中斷,設定為0時表示禁用該服務
7 loglevel notice 日誌級別,Redis 總共支援四個級別:debug、verbose、notice、warning,
級別逐漸增高,列印的資訊隨著級別的變高而減少,預設為 notice
8 syslog-enabled no 是否列印日誌到syslog中,預設為no
9 syslog-ident redis 指定syslog中的日誌標誌
10 databases 16 設定資料庫的數量,預設資料庫為0,可以使用SELECT 命令連線指定資料庫id
11 logfile "" 日誌檔案的位置,當指定為空字串時,為標準輸出

SNAPSHOTTING部分

快照,持久化規則

AOF

# 900秒(15分鐘)內至少1個key值改變(則進行資料庫儲存--持久化)
save 900 1
# 300秒(5分鐘)內至少10個key值改變(則進行資料庫儲存--持久化)
save 300 10
# 60秒(1分鐘)內至少10000個key值改變(則進行資料庫儲存--持久化)
save 60 10000

RGB

stop-writes-on-bgsave-error yes # 持久化出現錯誤後,是否依然進行繼續進行工作

rdbcompression yes # 使用壓縮rdb檔案 yes:壓縮,但是需要一些cpu的消耗。no:不壓縮,需要更多的磁碟空間

rdbchecksum yes # 是否校驗rdb檔案,更有利於檔案的容錯性,但是在儲存rdb檔案的時候,會有大概10%的效能損耗

dbfilename dump.rdb # dbfilenamerdb檔名稱

dir ./ # dir 資料目錄,資料庫的寫入會在這個目錄。rdb、aof檔案也會寫在這個目錄

REPLICATION主從複製

後續主從複製部分詳細說明

SECURITY部分

# 啟動redis
# 連線客戶端

# 獲得和設定密碼
config get requirepass
config set requirepass "123456"
#密碼置空:
config set requirepass  ''

#測試ping,發現需要驗證
127.0.0.1:6379> ping
NOAUTH Authentication required.
# 驗證: auth 密碼
127.0.0.1:6379> auth 123456
OK
127.0.0.1:6379> ping
PONG

客戶端連線相關

maxclients 10000  最大客戶端數量
maxmemory <bytes> 最大記憶體限制
maxmemory-policy noeviction # 記憶體達到限制值的處理策略

maxmemory-policy 六種方式

  • volatile-lru:利用LRU演算法移除設定過過期時間的key。

  • allkeys-lru :用lru演算法刪除lkey

  • volatile-random:隨機刪除即將過期key

  • allkeys-random:隨機刪除

  • volatile-ttl :刪除即將過期的

  • noeviction :不移除任何key,只是返回一個寫錯誤。

redis 中的預設的過期策略是 volatile-lru

設定方式

config set maxmemory-policy volatile-lru 

append only mode 部分

AOF相關部分

appendonly no #預設是不開啟AOF模式的,而是使用RGB方式持久化,大多數情況下RGB完全夠用
appendfilename "appendonly.aof"	#持久化檔名
appendfsync everysec # appendfsync aof持久化策略的配置
        # no表示不執行fsync,由作業系統保證資料同步到磁碟,速度最快。
        # always表示每次寫入都執行fsync,以保證資料同步到磁碟。
        # everysec表示每秒執行一次fsync,可能會導致丟失這1s資料。

LIMITS部分

  • maxclients :設定同一時間最大客戶端連線數,預設無限制,Redis 可以同時開啟的客戶端連線數為 Redis 程式可以開啟的最大檔案描述符數,如果設定 maxclients 0,表示不作限制。當客戶端連線數到達限制時,Redis 會關閉新的連線並向客戶端返回 max number of clients reached 錯誤資訊
  • maxmemory-policy 資料清除策
    • volatile-lru: 設定了過期時間的資料採取LRU(近期最少使用)演算法.如果對key使用"expire"指令指定了過期時間,那麼此key將會被新增到"過期集合"中。將已經過期/LRU的資料優先移除.如果"過期集合"中全部移除仍不能滿足記憶體需求,將OOM。
    • allkeys-lru:對所有的資料,採用LRU演算法
    • volatile-random:對設定了過期時間的資料採取"隨即選取"演算法,並移除選中的K-V,直到"記憶體足夠"為止。如果"過期集合"中全部移除全部移除仍不能滿足,將OOM
    • allkeys-random:對所有的資料,採取"隨機選取"演算法,並移除選中的K-V,直到"記憶體足夠"為止
    • volatile-ttl:對設定了過期時間的資料採取TTL演算法(最小存活時間),移除即將過期的資料。
    • noeviction:不做任何干擾操作,直接返回OOM異常,也是預設選項,實際開發不要用該選項
  • # maxmemory-samples 3:上面LRU和最小TTL策略並非嚴謹的策略,而是大約估算的方式,因此可以選擇取樣值以便檢查,預設值3

redis持久化

傳送門:redis——持久化

redis訂閱釋出

簡介

Redis 釋出訂閱(pub/sub)是一種訊息通訊模式:傳送者(pub)傳送訊息,訂閱者(sub)接收訊息。

Redis 客戶端可以訂閱任意數量的頻道。

訂閱/釋出訊息圖:

下圖展示了頻道 channel1 , 以及訂閱這個頻道的三個客戶端 —— client2 、 client5 和 client1 之間的關係:

當有新訊息通過 PUBLISH 命令傳送給頻道 channel1 時, 這個訊息就會被髮送給訂閱它的三個客戶端:

命令

下表列出了 redis 釋出訂閱常用命令:

序號 命令及描述
1 PSUBSCRIBE pattern [pattern ...]
訂閱一個或多個符合給定模式的頻道。
2 PUBSUB subcommand [argument [argument ...]]
檢視訂閱與釋出系統狀態。
3 PUBLISH channel message
將資訊傳送到指定的頻道。
4 PUNSUBSCRIBE [pattern [pattern ...]]
退訂所有給定模式的頻道。
5 SUBSCRIBE channel [channel ...]]
訂閱給定的一個或多個頻道的資訊。
6 UNSUBSCRIBE [channel [channel ...]]
指退訂給定的頻道。

測試

我們先開啟兩個 redis-cli 客戶端

在第一個 redis-cli 客戶端作為訂閱客戶端,建立訂閱頻道名為 redisChat,輸入SUBSCRIBE redisChat

redis 127.0.0.1:6379> SUBSCRIBE redisChat
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "redisChat"
3) (integer) 1 

開啟第二個客戶端作為傳送端,在指定頻道上釋出兩次訊息,訂閱者就能接收 到訊息。

redis 127.0.0.1:6379> PUBLISH redisChat "Hello,Redis"
(integer) 1
redis 127.0.0.1:6379> PUBLISH redisChat "Hello,java"
(integer) 1

訂閱者的客戶端會顯示如下訊息

1. "message"
2. "redisChat"
3. "Hello,Redis"

1. "message"
2. "redisChat"
3. "Hello,java"

總結

Redis是使用C實現的,通過分析 Redis 原始碼裡的 pubsub.c 檔案,瞭解釋出和訂閱機制的底層實現,來加深對 Redis 的理解。

Redis 通過 PUBLISH 、SUBSCRIBE 和 PSUBSCRIBE 等命令實現釋出和訂閱功能。

通過 SUBSCRIBE 命令訂閱某頻道後,redis-server 裡維護了一個字典,字典的鍵就是一個個 channel ,而字典的值則是一個連結串列,連結串列中儲存了所有訂閱這個 channel 的客戶端。SUBSCRIBE 命令的關鍵,就是將客戶端新增到給定 channel 的訂閱連結串列中。

通過 PUBLISH 命令向訂閱者傳送訊息,redis-server 會使用給定的頻道作為鍵,在它所維護的 channel 字典中查詢記錄了訂閱這個頻道的所有客戶端的連結串列,遍歷這個連結串列,將訊息釋出給所有訂閱者。

Pub/Sub 從字面上理解就是釋出(Publish)與訂閱(Subscribe),在Redis中,你可以設定對某一個 key值進行訊息釋出及訊息訂閱,當一個key值上進行了訊息釋出後,所有訂閱它的客戶端都會收到相應的訊息。這一功能最明顯的用法就是用作實時訊息系統,比如普通的即時聊天,群聊等功能。

使用場景:Redis的Pub/Sub系統可以構建實時的訊息系統,比如很多用Pub/Sub構建的實時聊天系統的例子

叢集環境搭建

Redis叢集詳解

Redis支援三種叢集方案

  • 主從複製模式
  • Sentinel(哨兵)模式
  • Cluster模式

主從複製

傳送門:redis叢集之主從複製 - 至安 - 部落格園 (cnblogs.com)

哨兵模式

解決什麼問題

哨兵模式之前主從切換的方法是當主伺服器當機後,需要手動把一臺從伺服器切換為主伺服器,這就需要人工干預,費事費力,還會造成一段時間內服務不可用。這不是一種推薦的方式,更多時候,我們優先考慮哨兵模式。Redis從2.8開始正式提供了Sentinel(哨兵) 架構來解決這個問題。

謀朝篡位的自動版,能夠後臺監控主機是否故障,如果故障了根據投票數自動將從庫轉換為主庫。

哨兵模式是一種特殊的模式,首先Redis提供了哨兵的命令,哨兵是一個獨立的程式,作為程式,它會獨 立執行。其原理是哨兵通過傳送命令,等待Redis伺服器響應,從而監控執行的多個Redis例項。

redis學習筆記(詳細)——高階篇

這裡的哨兵有兩個作用

  • 通過傳送命令,讓Redis伺服器返回監控其執行狀態,包括主伺服器和從伺服器。
  • 當哨兵監測到master當機,會自動將slave切換成master,然後通過釋出訂閱模式通知其他的從伺服器,修改配置檔案,讓它們切換主機。

然而一個哨兵程式對Redis伺服器進行監控,可能會出現問題,為此,我們可以使用多個哨兵進行監控。 各個哨兵之間還會進行監控,這樣就形成了多哨兵模式。

image-20210409150717930

假設主伺服器當機,哨兵1先檢測到這個結果,系統並不會馬上進行failover過程,僅僅是哨兵1主觀的認 為主伺服器不可用,這個現象成為主觀下線。當後面的哨兵也檢測到主伺服器不可用,並且數量達到一 定值時,那麼哨兵之間就會進行一次投票,投票的結果由一個哨兵發起,進行failover[故障轉移]操作。 切換成功後,就會通過釋出訂閱模式,讓各個哨兵把自己監控的從伺服器實現切換主機,這個過程稱為 客觀下線

相關配置

模式配置檔案 sentinel.conf

# Example sentinel.conf
 
# 哨兵sentinel例項執行的埠 預設26379
port 26379
 
# 哨兵sentinel的工作目錄
dir /tmp
 
# 哨兵sentinel監控的redis主節點的 ip port 
# master-name  可以自己命名的主節點名字 只能由字母A-z、數字0-9 、這三個字元".-_"組成。
# quorum 當這些quorum個數sentinel哨兵認為master主節點失聯 那麼這時 客觀上認為主節點失聯了
# sentinel monitor <master-name> <ip> <redis-port> <quorum>
sentinel monitor mymaster 127.0.0.1 6379 1
 
# 當在Redis例項中開啟了requirepass foobared 授權密碼 這樣所有連線Redis例項的客戶端都要提供密碼
# 設定哨兵sentinel 連線主從的密碼 注意必須為主從設定一樣的驗證密碼
# sentinel auth-pass <master-name> <password>
sentinel auth-pass mymaster MySUPER--secret-0123passw0rd
 
 
# 指定多少毫秒之後 主節點沒有應答哨兵sentinel 此時 哨兵主觀上認為主節點下線 預設30秒
# sentinel down-after-milliseconds <master-name> <milliseconds>
sentinel down-after-milliseconds mymaster 30000
 
# 這個配置項指定了在發生failover主備切換時最多可以有多少個slave同時對新的master進行 同步,
這個數字越小,完成failover所需的時間就越長,
但是如果這個數字越大,就意味著越 多的slave因為replication而不可用。
可以通過將這個值設為 1 來保證每次只有一個slave 處於不能處理命令請求的狀態。
# sentinel parallel-syncs <master-name> <numslaves>
sentinel parallel-syncs mymaster 1
 
 
 
# 故障轉移的超時時間 failover-timeout 可以用在以下這些方面: 
#1. 同一個sentinel對同一個master兩次failover之間的間隔時間。
#2. 當一個slave從一個錯誤的master那裡同步資料開始計算時間。直到slave被糾正為向正確的master那裡同步資料時。
#3.當想要取消一個正在進行的failover所需要的時間。  
#4.當進行failover時,配置所有slaves指向新的master所需的最大時間。不過,即使過了這個超時,slaves依然會被正確配置為指向master,但是就不按parallel-syncs所配置的規則來了
# 預設三分鐘
# sentinel failover-timeout <master-name> <milliseconds>
sentinel failover-timeout mymaster 180000
 
# SCRIPTS EXECUTION
 
#配置當某一事件發生時所需要執行的指令碼,可以通過指令碼來通知管理員,例如當系統執行不正常時發郵件通知相關人員。
#對於指令碼的執行結果有以下規則:
#若指令碼執行後返回1,那麼該指令碼稍後將會被再次執行,重複次數目前預設為10
#若指令碼執行後返回2,或者比2更高的一個返回值,指令碼將不會重複執行。
#如果指令碼在執行過程中由於收到系統中斷訊號被終止了,則同返回值為1時的行為相同。
#一個指令碼的最大執行時間為60s,如果超過這個時間,指令碼將會被一個SIGKILL訊號終止,之後重新執行。
 
#通知型指令碼:當sentinel有任何警告級別的事件發生時(比如說redis例項的主觀失效和客觀失效等等),將會去呼叫這個指令碼,
#這時這個指令碼應該通過郵件,SMS等方式去通知系統管理員關於系統不正常執行的資訊。呼叫該指令碼時,將傳給指令碼兩個引數,
#一個是事件的型別,
#一個是事件的描述。
#如果sentinel.conf配置檔案中配置了這個指令碼路徑,那麼必須保證這個指令碼存在於這個路徑,並且是可執行的,否則sentinel無法正常啟動成功。
#通知指令碼
# sentinel notification-script <master-name> <script-path>
  sentinel notification-script mymaster /var/redis/notify.sh
 
# 客戶端重新配置主節點引數指令碼
# 當一個master由於failover而發生改變時,這個指令碼將會被呼叫,通知相關的客戶端關於master地址已經發生改變的資訊。
# 以下引數將會在呼叫指令碼時傳給指令碼:
# <master-name> <role> <state> <from-ip> <from-port> <to-ip> <to-port>
# 目前<state>總是“failover”,
# <role>是“leader”或者“observer”中的一個。 
# 引數 from-ip, from-port, to-ip, to-port是用來和舊的master和新的master(即舊的slave)通訊的
# 這個指令碼應該是通用的,能被多次呼叫,不是針對性的。
# sentinel client-reconfig-script <master-name> <script-path>
sentinel client-reconfig-script mymaster /var/redis/reconfig.sh

實戰測試

1 - 調整結構,6379帶著80、81

2 - 在redis.conf同級目錄下新建 sentinel.conf 檔案,檔名固定

3 - 配置哨兵,填寫內容

#sentinel monitor 被監控主機名字 127.0.0.1 6379 n
例如:sentinel monitor mymaster 127.0.0.1 6379 1,

上面最後一個數字n,表示得票數,主機掛掉後從機投票接替成為主機,得票數到n的從機接替成為主機

4 - 啟動哨兵

Redis-sentinel myconfig/sentinel.conf

上述目錄依照各自的實際情況配置,可能目錄不同

成功啟動哨兵模式

在這裡插入圖片描述

此時哨兵監視著我們的主機6379,當我們斷開主機後:

在這裡插入圖片描述

哨兵模式的優缺點

優點

  1. 哨兵叢集,基於主從複製模式,所有主從複製的優點,它都有
  2. 主從可以切換,故障可以轉移,系統的可用性更好
  3. 哨兵模式是主從模式的升級,手動到自動,更加健壯

缺點:

  1. Redis不好線上擴容,叢集容量一旦達到上限,線上擴容就十分麻煩
  2. 實現哨兵模式的配置其實是很麻煩的,裡面有很多配置項

cluster模式

Redis Cluster日常操作命令梳理 - 散盡浮華 - 部落格園 (cnblogs.com)

快取穿透和雪崩

快取穿透(查不到)

在預設情況下,使用者請求資料時,會先在快取(Redis)中查詢,若沒找到即快取未命中,再在資料庫中進行查詢,數量少可能問題不大,可是一旦大量的請求資料(例如秒殺場景)在快取中都沒有命中的話,就會全部轉移到資料庫上,造成資料庫極大的壓力,可能導致資料庫崩潰。網路安全中也有人惡意使用這種手段進行攻擊被稱為洪水攻擊。

解決方案

布隆過濾器

對所有可能查詢的引數以Hash的形式儲存,以便快速確定是否存在這個值,在控制層先進行攔截校驗,校驗不通過直接打回,減輕了儲存系統的壓力。

在這裡插入圖片描述

快取空物件

一次請求若在快取和資料庫中都沒找到,就在快取中方一個空物件用於處理後續這個請求。

在這裡插入圖片描述

這樣做有一個缺陷:儲存空物件也需要空間,大量的空物件會耗費一定的空間,儲存效率並不高。解決這個缺陷的方式就是設定較短過期時間。即使對空值設定了過期時間,還是會存在快取層和儲存層的資料會有一段時間視窗的不一致,這對於需要保持一致性的業務會有影響

快取擊穿(量太大,快取過期)

相較於快取穿透,快取擊穿的目的性更強,快取中原本存在的key在過期的一刻,同時有大量的請求,這些請求都會擊穿到資料庫,造成瞬時DB請求量大、壓力驟增。這就是快取被擊穿,只是針對其中某個key的快取不可用而導致擊穿,但是其他的key依然可以使用快取響應。

比如熱搜排行上,一個熱點新聞被同時大量訪問就可能導致快取擊穿。

解決方案

  1. 設定熱點資料永不過期

    這樣就不會出現熱點資料過期的情況,但是當Redis記憶體空間滿的時候也會清理部分資料,而且此種方案會佔用空間,一旦熱點資料多了起來,就會佔用部分空間。

  2. 加互斥鎖(分散式鎖)

    在訪問key之前,採用SETNX(set if not exists)來設定另一個短期key來鎖住當前key的訪問,訪問結束再刪除該短期key。保證同時刻只有一個執行緒訪問。這樣對鎖的要求就十分高。

快取雪崩

大量的key設定了相同的過期時間,導致快取在同一時刻全部失效,造成瞬時DB請求量大、壓力驟增,引起雪崩。

比如馬上就要到雙十一零點,很快就會迎來一波搶購,這波商品時間比較集中的放入了快取,假設快取一個小時。那麼到了凌晨一點鐘的時候,這批商品的快取就都過期了。而對這批商品的訪問查詢,都落到了資料庫上,對於資料庫而言,就會產生週期性的壓力波峰。於是所有的請求都會達到儲存層,儲存層的呼叫量會暴增,造成儲存層也會掛掉的情況。

在這裡插入圖片描述

其實集中過期,倒不是非常致命,比較致命的快取雪崩,是快取伺服器某個節點當機或斷網。因為自然 形成的快取雪崩,一定是在某個時間段集中建立快取,這個時候,資料庫也是可以頂住壓力的。無非就 是對資料庫產生週期性的壓力而已。而快取服務節點的當機,對資料庫伺服器造成的壓力是不可預知 的,很有可能瞬間就把資料庫壓垮。

解決方案

  • redis高可用

    這個思想的含義是,既然redis有可能掛掉,那我多增設幾臺redis,這樣一臺掛掉之後其他的還可以繼續工作,其實就是搭建的叢集

  • 限流降級

    這個解決方案的思想是,在快取失效後,通過加鎖或者佇列來控制讀資料庫寫快取的執行緒數量。比如對某個key只允許一個執行緒查詢資料和寫快取,其他執行緒等待。

  • 資料預熱

    資料加熱的含義就是在正式部署之前,我先把可能的資料先預先訪問一遍,這樣部分可能大量訪問的資料就會載入到快取中。在即將發生大併發訪問前手動觸發載入快取不同的key,設定不同的過期時間,讓快取失效的時間點儘量均勻。

相關文章