一蹦锋、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.緩存穿透
緩存穿透是指查詢一個(gè)一不存在的數(shù)據(jù)菩佑,從緩存redis沒(méi)有命中,需要從mysql數(shù)據(jù)庫(kù)查詢欣舵,查不到數(shù)據(jù)則不寫(xiě)入緩存擎鸠,這將導(dǎo)致這個(gè)不存在的數(shù)據(jù)每次請(qǐng)求都要到數(shù)據(jù)庫(kù)去查詢,造成緩存穿透缘圈。
解決辦法:
1.接口層增加校驗(yàn)劣光,對(duì)傳參進(jìn)行校驗(yàn)袜蚕,給key設(shè)置一些格式規(guī)則,濾掉不符合規(guī)則的Key绢涡;
2.緩存空值:如果查詢數(shù)據(jù)庫(kù)也為空牲剃,直接設(shè)置空值存放到緩存,這樣第二次到緩沖中獲取就有值了雄可,而不會(huì)繼續(xù)訪問(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è)線程在執(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í)間(避免獲取到鎖的客戶端意外死掉鎖得不到釋放)
value設(shè)置為隨機(jī)值,釋放鎖之前判斷鎖對(duì)應(yīng)的value是不是自己設(shè)置的,如果是才去釋放(避免錯(cuò)誤釋放別人設(shè)置的鎖)
詳細(xì)內(nèi)容參考這篇博客:基于Redis的分布式鎖實(shí)現(xiàn)
四棱诱、Redis數(shù)據(jù)類型底層實(shí)現(xiàn)
再來(lái)說(shuō)一說(shuō)Redis支持的幾種數(shù)據(jù)類型的底層實(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)如下:
將字符串長(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系列文章——合集