可以合理的查看,以及理解修改配置文件,能幫助咱們更好的使用 Redis,下面按照 Redis 配置文件的順序依次往下講redis
主從複製會在下面專門講解,這裏暫時略過算法
接下來的 SECURITY 部分,註釋中有說起到關於密碼的設置,這裏多提一下在客戶端中設置密碼的方式shell
127.0.0.1:6379> ping PONG 127.0.0.1:6379> config get requirepass # 獲取redis的密碼 1) "requirepass" 2) "" 127.0.0.1:6379> config set requirepass "123456" # 設置redis的密碼 OK 127.0.0.1:6379> config get requirepass # 發現全部的命令都沒有權限 (error) NOAUTH Authentication required. 127.0.0.1:6379> ping (error) NOAUTH Authentication required. 127.0.0.1:6379> auth 123456 # 使用密碼進行登陸 OK 127.0.0.1:6379> config get requirepass 1) "requirepass" 2) "123456"
CLIENTS 客戶端鏈接部分,註釋太多,這裏很差截圖,就簡單說一說數據庫
maxclients —— 最大客戶端數量vim
maxmemory —— 最大內存限制centos
maxmemory-policy noeviction —— 內存達到限制值的處理策略緩存
redis 中的默認的過時策略是 volatile-lru ,設置方式以下:服務器
config set maxmemory-policy volatile-lru
maxmemory-policy 六種方式
volatile-lru:只對設置了過時時間的key進行LRU(默認值)網絡
allkeys-lru : 刪除lru算法的key架構
volatile-random:隨機刪除即將過時key
allkeys-random:隨機刪除volatile-ttl :刪除即將過時的
noeviction: 永不過時,返回錯誤
前面已經講過,Redis是一個內存數據庫,也就是說,咱們的數據所有存儲在內存中,而咱們常見的MySQL和Oracle等SQL數據庫會將數據存儲到硬盤中,凡事都是有利有弊,雖然內存數據庫讀寫速度要比在硬盤中讀寫的數據庫快的多,可是卻出現了一個很麻煩的問題,也就是說,當 Redis 服務器重啓或者宕機後,內存中的數據會所有丟失,爲了解決這個問題,Redis提供了一種持久化的技術,也就是將內存中的數據存儲到硬盤中去,往後方便咱們使用這些文件恢復數據庫中的數據
在配置文件的解釋中,提到了兩種持久化方式 RDB、AOF ,下面咱們具體來說解一下:
在指定時間間隔後,將內存中的數據集快照寫入數據庫 ,在恢復時候,直接讀取快照文件,進行數據的恢復
簡單理解:必定的時間內,檢測key的變化狀況,而後持久化數據
默認狀況下, Redis 將數據庫快照保存在名字爲 dump.rdb 的二進制文件中。
文件名能夠在配置文件中進行自定義,例如:dbfilename dump.rdb
在進行 RDB
的時候,redis
的主線程是不會作 io
操做的,主線程會 fork
一個子線程來完成該操做(這也是保證了其極大性能的特色)
這種工做方式使得 Redis 能夠從寫時複製(copy-on-write)機制中獲益(由於是使用子進程進行寫操做,而父進程依然能夠接收來自客戶端的請求。)
咱們知道了一個進程如何採用請求調頁,僅調入包括第一條指令的頁面,從而可以很 快開始執行。然而,經過系統調用 fork() 的進程建立最初能夠經過使用相似於頁面共享的技術,繞過請求調頁的須要。這種技術提供了快速的進程建立,並最小化必須分配給新建立進程的新頁面的數量。
回想一下,系統調用 fork() 建立了父進程的一個複製,以做爲子進程。傳統上,fork() 爲子進程建立一個父進程地址空間的副本,複製屬於父進程的頁面。然而,考慮到許多子進程在建立以後當即調用系統調用 exec(),父進程地址空間的複製可能沒有必要。
所以,能夠採用一種稱爲寫時複製的技術,它經過容許父進程和子進程最初共享相同的頁面來工做。這些共享頁面標記爲寫時複製,這意味着若是任何一個進程寫入共享頁面,那麼就建立共享頁面的副本。
知足 save 條件會自動觸發 rdb 原則
執行save / bgsave / flushall命令,也會觸發 rdb 原則
退出 Redis,也會自動產生 rdb 文件(默認生成位置就是 redis 的啓動目錄)
只要將 rdb 文件,放在 Redis 的啓動目錄,Redis 會自動在這個目錄下檢查 dump.rdb 文件,而後恢復其中的數據
查詢配置文件中位置的命令
127.0.0.1:6379> config get dir 1) "dir" 2) "/usr/local/bin"
優勢:
缺點:
以日誌的形式來記錄每一個寫的操做,將Redis執行過的全部指令記錄下來(讀操做不記錄),只許追加文件但不能夠改寫文件,redis啓動之初會讀取該文件從新構建數據,換言之,redis重啓的話就根據日誌文件的內容將寫指令從前到後執行一次以完成數據的恢復工做。
若是你不深究其背後的操做,能夠簡單理解爲:每個操做執行後,進行持久化操做
想要使用 AOF 方式,須要主動打開,由於默認使用的是 RDB
在配置文件中,咱們找到這兩行,能夠設置 aof 的啓動,以及其持久化文件的名字
appendonly no
:no 表明關閉 aof,改成 yes 表明開啓
appendfilename "appendonly.aof"
—— 持久化文件的名字
這裏能夠修改其持久化的一個方式
appendfsync always
—— 每次修改都會 sync(消耗性能 )
appendfsync everysec
—— 每秒執行一次 sync,可能會丟失這1s的數據
appendfsync no
—— 不執行 sync,操做系統本身同步數據,速度最快
其默認是無限追加模式的,若是 aof 文件大於 64m,就 fork一個新的進程來將咱們的文件進行重寫
no-appendfsync-on-rewrite no aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb
若是這個 aof 文件有錯位,這時候redis是啓動不起來的
Redis 給咱們提供了一個工具 redis-check-aof --fix
# 命令示例 redis-check-aof --fix appendonly.aof
優勢
缺點
若是你只但願你的數據在服務器運行的時候存在,你也能夠不使用任何持久化,即只當作緩存使用
同時開啓兩種持久化方式
在這種狀況下,當redis重啓的時候會優先載入AOF文件來恢復原始的數據,由於在一般狀況下AOF
文件保存的數據集要比RDB文件保存的數據集要完整。
RDB 的數據不實時,同時使用二者時服務器重啓也只會找AOF文件,那要不要只使用AOF呢?做者
建議不要,由於RDB更適合用於備份數據庫(AOF在不斷變化很差備份),快速重啓,並且不會有
AOF可能潛在的Bug,留着做爲一個萬一的手段。
性能建議
由於RDB文件只用做後備用途,建議只在Slave上持久化RDB文件,並且只要15分鐘備份一次就夠
了,只保留 save 900 1 這條規則。
若是Enable AOF ,好處是在最惡劣狀況下也只會丟失不超過兩秒數據,啓動腳本較簡單隻load自
己的AOF文件就能夠了,代價以下:
一是帶來了持續的IO,
二是AOF rewrite 的最後將 rewrite 過程當中產生的新數據寫到新文件形成的阻塞幾乎是不可避免的。
所以只要硬盤許可,應該儘可能減小AOF rewrite的頻率,AOF重寫的基礎大小默認值64M過小了,能夠設到5G以上,默認超過原大小100%大小重寫能夠改到適當的數值。
若是不Enable AOF ,僅靠 Master-Slave Repllcation 實現高可用性也能夠,能省掉一大筆IO,也
減小了rewrite時帶來的系統波動。
這部分,用的不是特別多,做爲一個補充。 下面是我在 菜鳥教程(runoob)貼過來的定義,重製了一下圖
定義:Redis 發佈訂閱 (pub/sub) 是一種消息通訊模式:發送者 (pub) 發送消息,訂閱者 (sub) 接收消息。
Redis 客戶端能夠訂閱任意數量的頻道。
下圖展現了頻道 channel1 , 以及訂閱這個頻道的三個客戶端 —— client2 、 client5 和 client1 之間的關係:
當有新消息經過 PUBLISH 命令發送給頻道 channel1 時, 這個消息就會被髮送給訂閱它的三個客戶端:
PSUBSCRIBE pattern [pattern..]
—— 訂閱一個或多個符合給定模式的頻道。PUNSUBSCRIBE pattern [pattern..]
—— 退訂一個或多個符合給定模式的頻道。PUBSUB subcommand [argument[argument]]
—— 查看訂閱與發佈系統狀態。PUBLISH channel message
—— 向指定頻道發佈消息SUBSCRIBE channel [channel..]
—— 訂閱給定的一個或多個頻道。SUBSCRIBE channel [channel..]
—— 退訂一個或多個頻道演示
------------訂閱端---------------------- 127.0.0.1:6379> SUBSCRIBE ideal-20 # 訂閱ideal-20頻道 Reading messages... (press Ctrl-C to quit) # 等待接收消息 1) "subscribe" # 訂閱成功的消息 2) "ideal-20" 3) (integer) 1 1) "message" # 接收到來自 ideal-20 頻道的消息 "hello ideal" 2) "ideal-20" 3) "hello ideal" 1) "message" # 接收到來自 ideal-20 頻道的消息 "hello i am ideal-20" 2) "ideal-20" 3) "Hi,i am BWH_Steven" --------------消息發佈端------------------- 127.0.0.1:6379> PUBLISH ideal-20 "hello ideal" # 發佈消息到ideal-20頻道 (integer) 1 127.0.0.1:6379> PUBLISH ideal-20 "Hi,i am BWH_Steven" # 發佈消息 (integer) 1 -----------------查看活躍的頻道------------ 127.0.0.1:6379> PUBSUB channels 1) "ideal-20"
說明:每一個 Redis 服務器進程都維持着一個表示服務器狀態的 redis.h/redisServer 結構,而結構的 pubsub_channels 屬性是一個字典, 這個字典就用於保存訂閱頻道的信息
例子示意圖:在下圖展現的這個 pubsub_channels 示例中, client2 、 client5 和 client1 就訂閱了 channel1(頻道1) ,其餘 channel (頻道)同理
有了這個結構上的概念,訂閱以及發佈的動做就很好理解了:
訂閱:當客戶端調用 SUBSCRIBE 命令執行訂閱頻道操做時,程序就會把一個個客戶端(client)和要訂閱的頻道(channel)在 pubsub_channels 中關聯起來
發佈: 程序首先根據 channel 定位到字典的鍵(例如找到 channel1), 而後將信息發送給字典值鏈表中的全部客戶端(例如 client二、client五、client1)。
首先,在一個項目中,使用一臺 Redis 服務器確定是有問題的:
一臺服務器處理全部請求,壓力過大,且容易出現故障,會致使整個相關服務出現問題
一臺服務器的內存是有限的,不可能將全部內存用做 Redis 存儲(推薦不該該超過 20g)
大部分場景下,大部分都是讀的操做,寫的操做會相對少一點,因此對讀取的要求會大一些
而主從複製就能夠將讀寫分離,下面來一塊兒瞭解一下
主從複製,是指將一臺Redis服務器的數據,複製到其餘的Redis服務器
前者稱爲主節點(Master/Leader),後者稱爲從節點(Slave/Follower)
數據的複製是單向的!只能由主節點複製到從節點(主節點以寫爲主、從節點以讀爲主)
簡單理解一下就是:一臺服務器做爲主機器,其餘服務器做爲從機器,他們經過命令或配置進行了鏈接,這樣從機就能獲取到主機的數據了,從機能夠幫主機分擔不少讀的請求等等
正常的狀況,應該是多臺不一樣的服務器,爲了演示方便,這裏使用幾個不一樣的端口來模擬不一樣的 Redis 服務器
首先,要使用不一樣的端口,天然須要多個不一樣的配置文件了,咱們先將原先的配置文件,複製三份(分別表明等會的一臺主機和兩臺從機)
# 一段都是爲了告訴你們個人配置文件的目錄,即redis 啓動目錄下面的 myconfig 目錄下 [root@centos7 ~]# cd /usr/local/bin [root@centos7 bin]# ls appendonly.aof dump.rdb myconfig redis-benchmark redis-check-aof redis-check-rdb redis-cli redis-sentinel redis-server temp-2415.rdb [root@centos7 bin]# cd myconfig/ [root@centos7 myconfig]# ls redis.conf # 複製三份,分別按照等會的端口號起名 [root@centos7 myconfig]# cp redis.conf redis6379.conf [root@centos7 myconfig]# cp redis.conf redis6380.conf [root@centos7 myconfig]# cp redis.conf redis6381.conf # 這樣三份就賦值好了 [root@centos7 myconfig]# ls redis6379.conf redis6380.conf redis6381.conf redis.conf
複製後,就須要分別經過 vim 修改每一個配置文件的 port 、daemonize、pid 、 logfile、dbfilename
例如:
port 6380 daemonize yes pidfile /var/run/redis_6380.pid logfile "6380.log" dbfilename dump6380.rdb
在 XShell 中再打開兩個窗口,而後分別運行不一樣端口號的 Redis
在第一個窗口運行 Redis 服務,使用 6379 這個配置文件
[root@centos7 bin]# redis-server myconfig/redis6379.conf
其餘兩個也是同理,分別啓動 6380、6381
查看一下,三個端口的 Redis 都啓動了
一主二從,就是表明一臺主機,還有兩臺是從機,而 Redis 默認都是主機,也就是說,咱們上面模擬搭建出來的幾臺 Redis 服務器,如今還都是主機,並且相互之間並不存在什麼關係
在客戶端中經過 info replication
命令能夠查看當前的一個信息
127.0.0.1:6379> info replication # Replication role:master # 當前是一個 master 主機 connected_slaves:0 master_replid:bfee90411a4ee99e80ace78ee587fdb7b564b4b4 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:0 second_repl_offset:-1 repl_backlog_active:0 repl_backlog_size:1048576 repl_backlog_first_byte_offset:0 repl_backlog_histlen:0
說明:如下演示中主機端口號爲 6379,兩臺從機分別爲 6380、6381
配置一主二從,只須要配置從機,使用 SLAVEOF 127.0.0.1 6379
便可
分別在 6380 和 6381 的窗口中執行
而後查詢從機自身的信息,例如查詢 6380 這臺
127.0.0.1:6380> info replication # Replication role:slave # 當前身份變成了一臺從機 master_host:127.0.0.1 master_port:6379 master_link_status:up master_last_io_seconds_ago:1 master_sync_in_progress:0 slave_repl_offset:364 slave_priority:100 slave_read_only:1 connected_slaves:0 master_replid:bd7b9c5f3bb1287211b23a3f62e41f24e009b77e master_replid2:0000000000000000000000000000000000000000 master_repl_offset:364 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:85 repl_backlog_histlen:280
一樣在主機中查詢,也能看到有兩臺從機已經鏈接
127.0.0.1:6379> info replication # Replication role:master connected_slaves:2 slave0:ip=127.0.0.1,port=6381,state=online,offset=84,lag=0 # 第一臺 slave1:ip=127.0.0.1,port=6380,state=online,offset=84,lag=0 # 第二臺 master_replid:bd7b9c5f3bb1287211b23a3f62e41f24e009b77e master_replid2:0000000000000000000000000000000000000000 master_repl_offset:84 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:84
上面使用命令的方式,須要每一次重啓等都須要執行命令,而將其寫到配置文件中的時候,就能夠每次根據配置自動加載了,首先修改從機配置文件中的 replicaof 後面跟隨主機的 ip 和 端口
若是主機的 Redis 設置了密碼,別忘了在從機中的 masterauth 中加上主機的密碼
從機只能讀,不能寫,主機可讀可寫可是多用於寫。
主機斷電/宕機後,默認角色不變,從機還是從機,集羣只是失去了寫操做,等待主機恢復,會從新回到原來的狀態
slaveof no one
使其成爲主機從機斷電/宕機後,若以前使用的是命令的方式稱爲從機,則啓動後沒法獲取主機,從新配置或者是使用配置文件的方式成爲從機,重啓後,能夠從新獲取到主機全部數據
Slave(從機) 啓動成功鏈接到 Master(註解) 後會發送一個 sync(同步命令)
Master 接到命令,啓動後臺的存盤進程,同時收集全部接收到的用於修改數據集命令,在後臺進程執行,完畢以後,master將傳送整個數據文件到slave,並完成一次徹底同步。
全量複製:而slave服務在接收到數據庫文件數據後,將其存盤並加載到內存中。
增量複製:Master 繼續將新的全部收集到的修改命令依次傳給slave,完成同步
可是隻要是從新鏈接master,一次徹底同步(全量複製)將被自動執行,從機中就能看到全部數據
在前面的主從複製的概念中,咱們知道,一旦主服務器宕機,就須要使用手動的方式,將一臺從服務器切換爲主服務器,這種方式很麻煩,還有一種方式就是哨兵模式,也是一種比較推薦的方式
定義:哨兵模式是一種特殊的模式,首先Redis提供了哨兵的命令,哨兵是一個獨立的進程,做爲進程,它會獨立運行。其原理是哨兵經過發送命令,等待Redis服務器響應,從而監控運行的多個Redis實例。
其做用以下:
單哨兵與多哨兵模式:
單哨兵模式:以獨立的進程監控3臺 Redis 服務器是否正常運行
多哨兵模式:除了監控Redis 服務器,哨兵之間也會互相監控
Redis 啓動目錄下的 redis-sentinel 就是咱們要啓動的哨兵,可是咱們須要爲其指定配置文件,這樣哨兵太知道要監控誰
我在個人 Redis 啓動目錄 /usr/local/bin/ 下的 myconfig 目錄中,建立了一個名爲 sentinel.conf 的配置文件
[root@centos7 bin]# vim myconfig/sentinel.conf
裏面寫入了其核心配置內容,即指定監控咱們本地 6379 端口的主機,後面的數字1,表明主機宕機後,會使用投票算法機制選擇一臺從機做爲新的主機
# sentinel monitor 被監控的名稱 host port 1 sentinel monitor myredis 127.0.0.1 6379 1
接着咱們回到 Redis 啓動目錄,以剛纔那個配置文件啓動哨兵
[root@centos7 bin]# redis-sentinel myconfig/sentinel.conf
啓動成功以下圖:
一旦將主機斷開鏈接,等待一下,哨兵監測到,就會發起投票(這裏只有一個哨兵,因此是 100%的),而後切換一臺從機成爲新的主機,而主機一旦從新上線後,也只能做爲新主機的一臺從機了
能夠根據哨兵這邊自動彈出來的日誌看到,首先 6379 這臺主機斷開後,1 個哨兵認爲其斷開,而後下面的 switch 即選擇了新的 6380 做爲新的主機,6379 從新上線後,只能做爲 6380 的從機了
查看一下 6380 的信息,其果真已經成爲了主機
127.0.0.1:6380> info replication # Replication role:master # 主機 connected_slaves:2 slave0:ip=127.0.0.1,port=6381,state=online,offset=147896,lag=0 slave1:ip=127.0.0.1,port=6379,state=online,offset=147764,lag=0 master_replid:d32e400babb8bfdabfd8ea1d3fc559f714ef0d5a master_replid2:bd7b9c5f3bb1287211b23a3f62e41f24e009b77e master_repl_offset:147896 second_repl_offset:7221 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:85 repl_backlog_histlen:147812
實際上最核心的也就是咱們剛纔演示中的那一句即下面的:sentinel monitor mymaster 127.0.0.1 6379 1
還有端口修改會用到,其餘的能夠根據狀況設置
其配置文件仍是比較複雜的
# 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
此部分爲一個補充知識點,本文重點仍是 Redis 的一個基本入門,而下面的這些知識點,更多的是在具體場景中產生的一些問題,並且其每個內容展開講都是很是複雜的,因此這裏只作一個基本概念的介紹,不作詳細說明
用戶查詢數據,首先在 Redis 緩存中去查,若是沒有,也就是緩存沒有命中,就會去持久層數據庫,例如 MySQL 中去查。
緩存穿透:大量緩存未命中的狀況下,大量請求持久層數據庫,持久層數據庫承載很大的壓力,出現問題。
常看法決方案有兩種:
① 布隆過濾器:
對全部可能查詢的參數以Hash的形式存儲,以便快速肯定是否存在這個值,在控制層先進行攔截校驗,校驗不經過直接打回,減輕了存儲系統的壓力。
② 緩存空對象:
次請求若在緩存和數據庫中都沒找到,就在緩存中方一個空對象用於處理後續這個請求
不過此方法存在兩種問題:
定義:緩存擊穿,是指一個key很是熱點,在不停的扛着大併發,大併發集中對這一個點進行訪問,當這個key在失效的瞬間,持續的大併發就穿破緩存,直接請求數據庫,就像在一個屏障上鑿開了一個洞
解決方案:
設置熱點數據永不過時
這樣就不會出現熱點數據過時的狀況,可是當 Redis 內存空間滿的時候也會清理部分數據,並且此種方案會佔用空間,一旦熱點數據多了起來,就會佔用部分空間。
加互斥鎖(分佈式鎖)
在訪問 key 以前,採用SETNX(set if not exists)來設置另外一個短時間key來鎖住當前key的訪問,訪問結束再刪除該短時間 key 。保證同時刻只有一個線程訪問。這樣對鎖的要求就十分高。
大量的key設置了相同的過時時間,致使在緩存在同一時刻所有失效,形成瞬時DB請求量大、壓力驟增,引發雪崩。
解決方案:
① redis高可用
② 限流降級
③ 數據預熱