Redis面试汇总笔记
???????在兩個月前的學習中,我看過一個redis相關的講解視頻,是一個叫諸葛的老師,其中分為幾層進行講述,分別是數據類型、分布式鎖、redis常見問題等。當時有記錄一些內容,下面將按照順序進行分享。
(一)常見的數據類型
???????結合視頻的內容,通過一張結構圖來展示各個數據類型之間的關系:
???????常見的數據類型一般都是圖上的幾種:String、Hash、List、Set、有序集合Set。
(1)String
常用操作:
1)字符串常用操作
set key value;
mset key valye [key value …]; //批量存儲字符串鍵值對
setnx key value; //存入一個不存在的字符串鍵值對
get key [key …];
del key [key …];
expire key seconds //設置一個鍵的過期時間
2)原子加減
incr key //將key中存儲的數字加1
decr key //將key中存儲的數字減1
incrby key increment //將key所存儲的值加上increment
decrby key decrement //將key所存儲的值減去decrement
3)分布式鎖
setnx [key] true //返回1代表取鎖成功,返回0代表獲取鎖失敗
del [key] //釋放鎖,即刪除鎖
set [key] true ex 10nx //防止程序意外終止導致死鎖,即設置過期時間
同時還可以存儲對象數據,不過需要將對象數據轉Json數據格式。
應用場景:
1)計數器
incr article:readcount:{文章id} //針對文章id的閱讀值,做原子性的+1操作
get article:readcount:{文章id} //獲取閱讀數
2)分布式系統全局序列號
increby orderid 100 //redis批量生成序列號提升性能
解釋:一次操作取100個編號,利用自增部分來使用編號。從性能角度分析,原來是操作100次redis進行取值,現在只需要操作一次,從而實現性能提升。
(2)Hash
常用操作:
hset key field value //存儲一個hash表key的值
hsetnx key key field value //存儲一個不存在的hash表的值
hmset key field value [field value …] //在一個哈希表中存儲多個鍵值對
hget key field //獲取哈希表中key對應的field鍵值
hmget key field [key field …] //批量獲取哈希表中的key對應的多個field鍵值
hdel key field [field …] //刪除
hlen key //返回哈希表中key對應的field的數量
hgetall key //返回哈希表中key中所有的鍵值
hincrby key field increment //為哈希表中的key的field鍵的值加上增量increment
應用場景:
1)電商購物車
①以用戶id為key
②商品id為field
③商品數量為value
2)購物車操作
①添加商品->hset cart:1001 10088 1
②增加數量->hincrby cart:1001 10088 1
③商品總數->hlen cart:1001
④刪除商品->hdel cart:1001 10088
⑤獲取購物車所有商品->hgetall cart:1001
(3)List
常用操作:
lpush key value [value …] //將一個或多個值value插入key列表的表頭(最左邊)
rpush key valye [value …] //將一個或多個值value插入key列表的表胃(最右邊)
lpop key //移除并返回key列表的頭元素
rpop key //移除并返回key列表的尾元素
lrange key start top //返回列表key中指定區間內的元素,區間以偏移量start和stop指定。(分正向索引和負向索引)
blpop key [key …] timeout //從key列表表頭彈出一個元素,若列表中沒有元素,阻塞等待timeout秒,如果timeout=0,一直阻塞等待
brpop key [key …] timeout //從key列表表尾彈出一個元素,若列表中沒有元素,阻塞等待timeout秒,如果timeout=0,一直阻塞等待
常用的分布式數據結構:
Stack(棧) = lpush + lpop = FILO
Queue(隊列) = lpush + rpop = FIFO
Blocking MQ(阻塞隊列) = lpush + brpop
應用場景:
1)微博和微信公眾號消息流
???????諸葛老師關注了Caoz,備胎說車等大V。
①CaoZ發微博,消息id為10018
lpush msg:{諸葛老師-ID} 10018
②備胎說車發微博,消息id為10086
lpush msg{諸葛老師-id} 10086
③查看最新微博消息
lrange msg:{諸葛老師-id} 0 4
解釋:可能存在關注同一個人,但是接收到新推送的消息存在延遲,因為底層實現排隊發送,比如優先發送在線人員,在發送不在線的。
(4)Set
常用操作:
(后續補充)
應用場景:
1)抽獎程序(微信小程序等)
2)微信微博點贊、收藏、標簽
3)集合操作實現電商商品篩選
集合的運算(實現關注模型)
1)交集
{a,b,c} {a,c} => {a,c}
2)差集
{a,b,c} {b,d,f,g} => {a,c}
3)并集
{a,b,c} {c,d,f,g} => {a,b,c,d,f,g}
(5)有序Set
常用操作:
(后續補充)
應用場景:
1)實現熱榜排行前十等
底層實現結構:
1)壓縮列表
(后續補充)
2)跳表
???????當壓縮列表達到一個大小時,會從壓縮列表轉化為跳表。跳表結構有點類似mysql底層數據結構,B+tree,即冗余排好序的序號作為結點頭部,利用多路查詢樹的結構進行設計。
(二)分布式鎖
(1)基于原生的redis命令setnx
???????在redis中,基于setnx命令的操作,就可以實現分布式鎖相關業務,與在Java中的redistemplate中是使用setIfAbsent是一致的。
(2)基于redission組件
???????該組件就是基于一系列的分布式場景設置了許多類型的鎖,比如基礎的同步鎖,讀寫鎖等,讀者可以自行探討。
分布式鎖的設計理念:
①對緩存內存進行設置(單值設置,如果存在多個線程進行設置時,只有一個線程能設置成功,其他線程失敗);
②設置緩存失效時間;(解決因程序出錯,導致死鎖的問題)
③通過lua代碼實現一個鎖續命操作,底層成為看門狗,負責檢測當前鎖是否失效,如果沒有,則重新設置鎖的過期時間;注:lua代碼的執行是一個原子性操作,意味著有么就全部操作正常,要么就全部操作失敗;(確保原子性)
(三)緩存問題
???????當業務代碼涉及到先查詢緩存,如果存在,則取出redis中的緩存值,并且返回,否則查詢數據庫,取到對應內容,再設置到緩存中,并且返回,此時就會出現下述前三個問題。
(1)緩存擊穿(緩存失效)
解釋:也叫熱點Key問題,就是一個被高并發訪問并且緩存重建業務較復雜(意味著對數據庫壓力相對較大)的key突然失效了,無數的請求訪問會在瞬間給數據庫帶來巨大的壓力,導致數據庫服務掛掉(可以理解為redis的緩存暫時沒有,此時高并發情況下,所有線程進到接口時,都會判斷當前redis緩存不存在,因此會有大量的請求訪問數據庫)。
解決方法:
1、互斥鎖:當同個業務不同線程訪問redis未命中時,先獲取一把互斥鎖,然后進行數據庫操作,此時另外一個線程未命中時,拿不到鎖,等待一段時間后重新查詢緩存,此時之前的線程已經重新把數據加載到redis之中了,線程二就直接緩存命中。這樣就不會使得大量訪問進入數據庫。
(2)緩存穿透
解釋:有一個商品被刪掉了,但是在高并發情況下,首先去檢查緩存,此時發現緩存沒有,就去查詢數據庫,此時還是查詢不到,然后就返回不了任何數據。
解決方案:當查詢到數據庫發現不存在時,可以設置一個空值,就可以避免所有請求直接訪問數據庫,減輕數據庫壓力。
(3)緩存雪崩
解釋:當緩存在同一時間內大部分失效,此時導致所有的請求訪問接口時,會同時訪問數據庫,造成數據庫服務訪問壓力過大。
解決方法:在設置過期時間時,利用固定時間+隨機數時間進行設置,避免同一時間大面積緩存失效。
(4)緩存和數據庫雙寫不一致的問題
(后續補充)
(5)緩存數據冷熱分離
解釋:由于redis的資源有限,不可能將所有的數據都防止緩存中,因此只需要裝熱數據緩存在redis中即可,冷數據失效。具體實現原理為設置緩存過期時間即可。
總結
以上是生活随笔為你收集整理的Redis面试汇总笔记的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 国内邮箱排名VIP邮箱哪个好?VIP邮箱
- 下一篇: linux cmake编译源码,linu