Redis學(xué)習(xí)筆記——進(jìn)階篇

一、Redis實(shí)現(xiàn)緩存

1.緩存實(shí)現(xiàn)方式

使用Redis做緩存有兩種方式:直接通過(guò)RedisTemplate來(lái)使用、使用spring cache集成Redis

RedisTemplate

Spring Cache集成Redis

2.數(shù)據(jù)淘汰機(jī)制

前置知識(shí)點(diǎn):key的生存時(shí)間和過(guò)期時(shí)間

volatile-lru 從已設(shè)置過(guò)期時(shí)間的數(shù)據(jù)集中挑選最近最少使用的數(shù)據(jù)淘汰
volatile-ttl 從已設(shè)置過(guò)期時(shí)間的數(shù)據(jù)集中挑選將要過(guò)期的數(shù)據(jù)淘汰
volatile-random從已設(shè)置過(guò)期時(shí)間的數(shù)據(jù)集中任意選擇數(shù)據(jù)淘汰
allkeys-lru從所有數(shù)據(jù)集中挑選最近最少使用的數(shù)據(jù)淘汰
allkeys-random從所有數(shù)據(jù)集中任意選擇數(shù)據(jù)進(jìn)行淘汰
noeviction禁止驅(qū)逐數(shù)據(jù)

Redis中的淘汰機(jī)制(LRU和TTL)都是非精確算法實(shí)現(xiàn)的,主要從性能和可靠性上做平衡,所以并不是完全可靠,在了解Redis淘汰策略之后還應(yīng)在平時(shí)多主動(dòng)設(shè)置或更新key的expire時(shí)間,主動(dòng)刪除沒(méi)有價(jià)值的數(shù)據(jù),提升Redis整體性能和空間

二、緩存相關(guān)問(wèn)題的預(yù)防和解決

1.緩存穿透

緩存穿透是指查詢(xún)一個(gè)一不存在的數(shù)據(jù),從緩存redis沒(méi)有命中,需要從mysql數(shù)據(jù)庫(kù)查詢(xún),查不到數(shù)據(jù)則不寫(xiě)入緩存,這將導(dǎo)致這個(gè)不存在的數(shù)據(jù)每次請(qǐng)求都要到數(shù)據(jù)庫(kù)去查詢(xún),造成緩存穿透。

解決辦法:
1.接口層增加校驗(yàn),對(duì)傳參進(jìn)行校驗(yàn),給key設(shè)置一些格式規(guī)則,濾掉不符合規(guī)則的Key;
2.緩存空值:如果查詢(xún)數(shù)據(jù)庫(kù)也為空,直接設(shè)置空值存放到緩存,這樣第二次到緩沖中獲取就有值了,而不會(huì)繼續(xù)訪(fǎng)問(wèn)數(shù)據(jù)庫(kù)。設(shè)置一個(gè)過(guò)期時(shí)間或者當(dāng)有值的時(shí)候?qū)⒕彺嬷械闹堤鎿Q掉即可。
3.BloomFilter(Redis-避免緩存穿透的利器之BloomFilter

2.緩存擊穿

本應(yīng)該在緩存中的熱點(diǎn)數(shù)據(jù)突然失效,大量請(qǐng)求打到服務(wù)器的數(shù)據(jù)庫(kù)中。

解決辦法:
1.設(shè)置數(shù)據(jù)永不過(guò)期
2.加互斥鎖

3.緩存雪崩

數(shù)據(jù)未加載到緩存中,或者緩存同一時(shí)間大面積的失效,從而導(dǎo)致所有請(qǐng)求都去查數(shù)據(jù)庫(kù),CPU和內(nèi)存負(fù)載過(guò)高,甚至宕機(jī)。

預(yù)防措施:
1.使用集群緩存。降低宕機(jī)概率。
2.在每一個(gè)緩存原有的過(guò)期時(shí)間基礎(chǔ)上加一個(gè)隨機(jī)值,比如1到5分鐘,這樣每一個(gè)緩存的過(guò)期時(shí)間的重復(fù)率就會(huì)降低,就很難引發(fā)集體失效的事件。
3.加阻塞隊(duì)列,每次只有一個(gè)線(xiàn)程在執(zhí)行請(qǐng)求,缺點(diǎn)也顯而易見(jiàn),會(huì)降低系統(tǒng)QPS。

消減措施:
1.二級(jí)緩存
2.降級(jí)+接口限速

三、Redis分布式鎖——SETNX

SETNX是redis的一個(gè)命令,對(duì)應(yīng)的操作是將 key 的值設(shè)為 value,當(dāng)且僅當(dāng) key 不存在。若給定的 key 已經(jīng)存在,則 SETNX 不做任何動(dòng)作。
命令格式:

SETNX key value

返回整數(shù),具體為

  • 1,當(dāng) key 的值被設(shè)置
  • 0,當(dāng) key 的值沒(méi)被設(shè)置

使用 set key value [EX seconds][PX milliseconds][NX|XX] 命令實(shí)現(xiàn)分布式鎖
Redis在 2.6.12 版本開(kāi)始,為 SET 命令增加一系列選項(xiàng):

SET key value[EX seconds][PX milliseconds][NX|XX]

  • EX seconds: 設(shè)定過(guò)期時(shí)間,單位為秒
  • PX milliseconds: 設(shè)定過(guò)期時(shí)間,單位為毫秒
  • NX: 僅當(dāng)key不存在時(shí)設(shè)置值
  • XX: 僅當(dāng)key存在時(shí)設(shè)置值

設(shè)置過(guò)期時(shí)間(避免獲取到鎖的客戶(hù)端意外死掉鎖得不到釋放)
value設(shè)置為隨機(jī)值,釋放鎖之前判斷鎖對(duì)應(yīng)的value是不是自己設(shè)置的,如果是才去釋放(避免錯(cuò)誤釋放別人設(shè)置的鎖)

詳細(xì)內(nèi)容參考這篇博客:基于Redis的分布式鎖實(shí)現(xiàn)

四、Redis數(shù)據(jù)類(lèi)型底層實(shí)現(xiàn)

再來(lái)說(shuō)一說(shuō)Redis支持的幾種數(shù)據(jù)類(lèi)型的底層實(shí)現(xiàn)。

1.string-SDS

Redis是用C語(yǔ)言實(shí)現(xiàn)的,C語(yǔ)言中,字符串其實(shí)就是一個(gè)數(shù)組,但是Redis的字符串底層實(shí)現(xiàn)是SDS,動(dòng)態(tài)字符串,結(jié)構(gòu)如下:


SDS

將字符串長(zhǎng)度保存到len字段,這樣獲取長(zhǎng)度就不用想C語(yǔ)言的字符串去遍歷一遍。
此外,SDS還有如下兩個(gè)特點(diǎn):
1.減少修改字符串時(shí)帶來(lái)的內(nèi)存重分配次數(shù)
free表示還沒(méi)有使用的空間,用來(lái)做空間預(yù)分配和惰性空間釋放。
2.二進(jìn)制安全
字符串是否結(jié)束不是去判斷空字符也就是'\0',而是判斷l(xiāng)en,這樣也保證了SDS的二進(jìn)制安全,讓其可以存圖片、音頻等文件。

2.zset-跳躍表

請(qǐng)參考Redis為什么用跳表而不用平衡樹(shù)?

推薦文集:
Redis系列文章——合集

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容