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,直到"記憶體足夠"為止。如果"過期集合"中全部移除全部移除仍不能滿足,將OOMallkeys-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支援三種叢集方案
- 主從複製模式
- Sentinel(哨兵)模式
- Cluster模式
主從複製
傳送門:redis叢集之主從複製 - 至安 - 部落格園 (cnblogs.com)
哨兵模式
解決什麼問題
哨兵模式之前主從切換的方法是當主伺服器當機後,需要手動把一臺從伺服器切換為主伺服器,這就需要人工干預,費事費力,還會造成一段時間內服務不可用。這不是一種推薦的方式,更多時候,我們優先考慮哨兵模式。Redis從2.8開始正式提供了Sentinel(哨兵) 架構來解決這個問題。
謀朝篡位的自動版,能夠後臺監控主機是否故障,如果故障了根據投票數自動將從庫轉換為主庫。
哨兵模式是一種特殊的模式,首先Redis提供了哨兵的命令,哨兵是一個獨立的程式,作為程式,它會獨 立執行。其原理是哨兵通過傳送命令,等待Redis伺服器響應,從而監控執行的多個Redis例項。
這裡的哨兵有兩個作用
- 通過傳送命令,讓Redis伺服器返回監控其執行狀態,包括主伺服器和從伺服器。
- 當哨兵監測到master當機,會自動將slave切換成master,然後通過釋出訂閱模式通知其他的從伺服器,修改配置檔案,讓它們切換主機。
然而一個哨兵程式對Redis伺服器進行監控,可能會出現問題,為此,我們可以使用多個哨兵進行監控。 各個哨兵之間還會進行監控,這樣就形成了多哨兵模式。
假設主伺服器當機,哨兵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,當我們斷開主機後:
哨兵模式的優缺點
優點
- 哨兵叢集,基於主從複製模式,所有主從複製的優點,它都有
- 主從可以切換,故障可以轉移,系統的可用性更好
- 哨兵模式是主從模式的升級,手動到自動,更加健壯
缺點:
- Redis不好線上擴容,叢集容量一旦達到上限,線上擴容就十分麻煩
- 實現哨兵模式的配置其實是很麻煩的,裡面有很多配置項
cluster模式
Redis Cluster日常操作命令梳理 - 散盡浮華 - 部落格園 (cnblogs.com)
快取穿透和雪崩
快取穿透(查不到)
在預設情況下,使用者請求資料時,會先在快取(Redis)中查詢,若沒找到即快取未命中,再在資料庫中進行查詢,數量少可能問題不大,可是一旦大量的請求資料(例如秒殺場景)在快取中都沒有命中的話,就會全部轉移到資料庫上,造成資料庫極大的壓力,可能導致資料庫崩潰。網路安全中也有人惡意使用這種手段進行攻擊被稱為洪水攻擊。
解決方案
布隆過濾器
對所有可能查詢的引數以Hash的形式儲存,以便快速確定是否存在這個值,在控制層先進行攔截校驗,校驗不通過直接打回,減輕了儲存系統的壓力。
快取空物件
一次請求若在快取和資料庫中都沒找到,就在快取中方一個空物件用於處理後續這個請求。
這樣做有一個缺陷:儲存空物件也需要空間,大量的空物件會耗費一定的空間,儲存效率並不高。解決這個缺陷的方式就是設定較短過期時間。即使對空值設定了過期時間,還是會存在快取層和儲存層的資料會有一段時間視窗的不一致,這對於需要保持一致性的業務會有影響
快取擊穿(量太大,快取過期)
相較於快取穿透,快取擊穿的目的性更強,快取中原本存在的key在過期的一刻,同時有大量的請求,這些請求都會擊穿到資料庫,造成瞬時DB請求量大、壓力驟增。這就是快取被擊穿,只是針對其中某個key的快取不可用而導致擊穿,但是其他的key依然可以使用快取響應。
比如熱搜排行上,一個熱點新聞被同時大量訪問就可能導致快取擊穿。
解決方案
-
設定熱點資料永不過期
這樣就不會出現熱點資料過期的情況,但是當Redis記憶體空間滿的時候也會清理部分資料,而且此種方案會佔用空間,一旦熱點資料多了起來,就會佔用部分空間。
-
加互斥鎖(分散式鎖)
在訪問key之前,採用SETNX(set if not exists)來設定另一個短期key來鎖住當前key的訪問,訪問結束再刪除該短期key。保證同時刻只有一個執行緒訪問。這樣對鎖的要求就十分高。
快取雪崩
大量的key設定了相同的過期時間,導致快取在同一時刻全部失效,造成瞬時DB請求量大、壓力驟增,引起雪崩。
比如馬上就要到雙十一零點,很快就會迎來一波搶購,這波商品時間比較集中的放入了快取,假設快取一個小時。那麼到了凌晨一點鐘的時候,這批商品的快取就都過期了。而對這批商品的訪問查詢,都落到了資料庫上,對於資料庫而言,就會產生週期性的壓力波峰。於是所有的請求都會達到儲存層,儲存層的呼叫量會暴增,造成儲存層也會掛掉的情況。
其實集中過期,倒不是非常致命,比較致命的快取雪崩,是快取伺服器某個節點當機或斷網。因為自然 形成的快取雪崩,一定是在某個時間段集中建立快取,這個時候,資料庫也是可以頂住壓力的。無非就 是對資料庫產生週期性的壓力而已。而快取服務節點的當機,對資料庫伺服器造成的壓力是不可預知 的,很有可能瞬間就把資料庫壓垮。
解決方案
-
redis高可用
這個思想的含義是,既然redis有可能掛掉,那我多增設幾臺redis,這樣一臺掛掉之後其他的還可以繼續工作,其實就是搭建的叢集
-
限流降級
這個解決方案的思想是,在快取失效後,通過加鎖或者佇列來控制讀資料庫寫快取的執行緒數量。比如對某個key只允許一個執行緒查詢資料和寫快取,其他執行緒等待。
-
資料預熱
資料加熱的含義就是在正式部署之前,我先把可能的資料先預先訪問一遍,這樣部分可能大量訪問的資料就會載入到快取中。在即將發生大併發訪問前手動觸發載入快取不同的key,設定不同的過期時間,讓快取失效的時間點儘量均勻。