面试题—Redis篇
1、Redis是什么?
?
?
- NoSql數(shù)據(jù)庫(kù)、內(nèi)存數(shù)據(jù)庫(kù);key-value形式存儲(chǔ),存儲(chǔ)在內(nèi)存上;優(yōu)點(diǎn)是結(jié)構(gòu)簡(jiǎn)單速度快
2、Redis有哪幾種數(shù)據(jù)類型?
- String:熱點(diǎn)數(shù)據(jù)
- HashTable:熱點(diǎn)數(shù)據(jù)、用戶信息、視頻信息
- LinkedList:微博時(shí)間軸
- Set:標(biāo)簽、點(diǎn)贊、收藏、關(guān)注
- ZSet:排行榜
3、利用redis的bitmap實(shí)現(xiàn)用戶簽到、統(tǒng)計(jì)活躍用戶、用戶在線狀態(tài)
- Redis從2.2.0版本開始新增了setbit,getbit,bitcount等幾個(gè)bitmap相關(guān)命令。雖然是新命令,但是并沒有新增新的數(shù)據(jù)類型,因?yàn)閟etbit等命令只不過是在set上的擴(kuò)展。
4、微信微博點(diǎn)贊、收藏、標(biāo)簽、關(guān)注(使用HashMap數(shù)據(jù)結(jié)構(gòu))
- 用戶某篇文章的點(diǎn)贊數(shù):HashMap中的key為articleId,value為Set,Set中的值為用戶ID,即HashMap<String, Set<String>>
- 用戶總的點(diǎn)贊數(shù):HashMap中的key為userId,value為String記錄總的點(diǎn)贊數(shù)
- 用戶點(diǎn)贊、收藏的文章:HashMap中的key為userId,value為Set,Set中的值為文章ID,即HashMap<String, Set<String>>
- 標(biāo)簽、關(guān)注功能:HashMap中的key為userId,value為Set,Set中的值為標(biāo)簽,即HashMap<String, Set<String>>
5、Redis命令
- 用于查找所有符合給定模式 pattern 的 key:KEYS PATTERN(比如KEYS runoob*)
- 如果Redis有1億個(gè)key,使用keys命令是否會(huì)影響線上服務(wù)?執(zhí)行keys命令,redis會(huì)鎖定,如果數(shù)據(jù)龐大的話可能需要幾秒或更長(zhǎng),對(duì)于生產(chǎn)服務(wù)器上鎖定幾秒這絕對(duì)是災(zāi)難了
6、Redis緩存穿透和緩存雪崩是什么?
- 緩存穿透:redis中沒有需要去查數(shù)據(jù)庫(kù);這個(gè)正常時(shí)候是沒問題的,但是被黑客利用發(fā)送大量空請(qǐng)求會(huì)導(dǎo)致數(shù)據(jù)庫(kù)宕機(jī);解決方案是增加布隆過濾器或者緩存空對(duì)象
- 緩存雪崩:大量key同一時(shí)間點(diǎn)全部失效,同時(shí)又有大量請(qǐng)求打進(jìn)來,導(dǎo)致流量直接打在DB上,造成DB不可用。
7、MySQL里有2000w數(shù)據(jù),redis中只存20w的數(shù)據(jù),如何保證redis中的數(shù)據(jù)都是熱點(diǎn)數(shù)據(jù)?
- Redis有過期刪除策略和內(nèi)存淘汰機(jī)制(針對(duì)未設(shè)置過期時(shí)間的key)
8、過期刪除策略
- 立即刪除:過期立馬刪除,弊端是cpu繁忙給cpu增加了壓力
- 惰性刪除:下次使用時(shí)發(fā)現(xiàn)過期刪除
- 定期刪除:每個(gè)一段時(shí)間執(zhí)行一次刪除
9、內(nèi)存淘汰管理機(jī)制
- no-enviction(驅(qū)逐):禁止驅(qū)逐數(shù)據(jù)
- volatile-lru:從已設(shè)置過期時(shí)間的數(shù)據(jù)集(server.db[i].expires)中挑選最近最少使用的數(shù)據(jù)淘汰
- volatile-ttl:從已設(shè)置過期時(shí)間的數(shù)據(jù)集(server.db[i].expires)中挑選將要過期的數(shù)據(jù)淘汰
- volatile-random:從已設(shè)置過期時(shí)間的數(shù)據(jù)集(server.db[i].expires)中任意選擇數(shù)據(jù)淘汰
- allkeys-lru:從數(shù)據(jù)集(server.db[i].dict)中挑選最近最少使用的數(shù)據(jù)淘汰
- allkeys-random:從數(shù)據(jù)集(server.db[i].dict)中任意選擇數(shù)據(jù)淘汰
10、數(shù)據(jù)可靠性:持久化機(jī)制
- 為什么需要持久化:Redis數(shù)據(jù)存在內(nèi)存中,如果沒有配置持久化,redis重啟后數(shù)據(jù)就全丟失了,于是需要開啟redis的持久化功能,將數(shù)據(jù)保存到磁盤上,當(dāng)redis重啟后,可以從磁盤中恢復(fù)數(shù)據(jù)
- 持久化方式:快照持久化RDB、追加日志持久化AOF文件
- RDB快照文件:save和bgsave命令打快照;優(yōu)點(diǎn)是全量備份,缺點(diǎn)時(shí)持久化期間可能存在數(shù)據(jù)丟失
- AOF命令文件:保存每個(gè)命令;aof文件太大會(huì)進(jìn)行瘦身;優(yōu)點(diǎn)是可靠性高,缺點(diǎn)是aof文件太大,且啟動(dòng)aof會(huì),qps會(huì)下降
11、數(shù)據(jù)一致性
- 數(shù)據(jù)庫(kù)處理強(qiáng)一致性數(shù)據(jù),redis不處理強(qiáng)一致性數(shù)據(jù);
- 讀寫策略:讀數(shù)據(jù)先讀redis;寫數(shù)據(jù),高并發(fā)直接寫rediscover,定期刷新到redis,非高并發(fā)的話先寫數(shù)據(jù)庫(kù)在刷新到redis
12、Redis集群策略
- 單機(jī)模式:
- 主從復(fù)制:一個(gè)master多個(gè)slave
- 哨兵模式:監(jiān)聽者機(jī)制(與zookeeper一樣),master下線后自動(dòng)進(jìn)行故障轉(zhuǎn)移、通知
- 集群模式:proxy型與直連型
13、redis是多線程還是單線程?
redis中io多路復(fù)用器模塊是單線程執(zhí)行,事件處理器也是單線程執(zhí)行,兩個(gè)線程不一樣。所以實(shí)際redis應(yīng)該是單進(jìn)程多線程,只是不同的模塊都用的單線程實(shí)現(xiàn)。(redis4.0以前所有模塊是單線程的,4.0以后是異步刪除模塊和6.0的I/O讀寫是多線程的)兩個(gè)維度來舉例:
- 若是client發(fā)送命令到server的話,server處理命令是單線程逐條進(jìn)行的。
- server內(nèi)部可以是多線程的,比如aof持久化,假設(shè)策略每秒,那就是再單獨(dú)開啟一個(gè)線程去執(zhí)行aof文件持久化操作,這就是多線程了。
14、Redis主線程既然是單線程,為什么還這么快?
基于內(nèi)存操作、數(shù)據(jù)結(jié)構(gòu)簡(jiǎn)單、多路復(fù)用和非阻塞IO、避免上下文切換
15、Redis6.0的多線程?
Redis4.0引入了多線程,但4.0的多線程只支持大數(shù)量的異步刪除。6.0中引入的多線程用于提高IO的讀寫能力,主要實(shí)現(xiàn)思路是將主線程的IO讀寫任務(wù)拆分給一組獨(dú)立的線程去執(zhí)行,這樣就可以使用多個(gè)socket的讀寫并行化了,但Redis的命令依然是主線程串行執(zhí)行的
16、Redis的多路復(fù)用是什么?
socket的讀寫方法默認(rèn)是阻塞的,Redis的非阻塞IO是指IO的讀寫流程不再是阻塞的,讀寫方法都是瞬間完成并且返回的,也就是它會(huì)采用能讀多少就讀多少、能寫多少就寫多少的策略來執(zhí)行IO操作。非阻塞的IO也面臨一個(gè)問題,那就是當(dāng)執(zhí)行讀寫操作時(shí),有可能只讀寫了一部分?jǐn)?shù)據(jù),那么生效的數(shù)據(jù)何時(shí)寫就成了一個(gè)問題。而IO的多路復(fù)用就是解決上面的這個(gè)問題的,使用IO多路復(fù)用最簡(jiǎn)單的方式就是使用select函數(shù),此函數(shù)是操作系統(tǒng)提供給用戶程序的API接口,用于監(jiān)控多個(gè)文件描述符的可讀和可寫情況的,這樣就可以監(jiān)控到文件描述符的讀寫事件了。當(dāng)監(jiān)控到相應(yīng)的時(shí)間之后就可以通知線程處理相應(yīng)的業(yè)務(wù)了,這樣就保證了Redis讀寫功能的正常執(zhí)行。
【不過現(xiàn)在的操作系統(tǒng)已經(jīng)基本上不適用select函數(shù)了,改為調(diào)用epoll函數(shù)(Linux)了,macOS則是使用Kqueue(繼承與Unix),因?yàn)閟elect函數(shù)在文件描述符非常多的時(shí)候性能非常差。】
總結(jié)
以上是生活随笔為你收集整理的面试题—Redis篇的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 面试题—Mysql篇
- 下一篇: MySQL—通过Adjacency Li