理論:第四章:Redis支持的數(shù)據(jù)類(lèi)型以及使用場(chǎng)景,持久化,哨兵機(jī)制,緩存雪崩,緩存穿透,雙刪策略
簡(jiǎn)單介紹一個(gè)redis?
redis是內(nèi)存中的數(shù)據(jù)結(jié)構(gòu)存儲(chǔ)系統(tǒng),一個(gè)key-value類(lèi)型的非關(guān)系型數(shù)據(jù)庫(kù),可持久化的數(shù)據(jù)庫(kù),相對(duì)于關(guān)系型數(shù)據(jù)庫(kù)(數(shù)據(jù)主要存在硬盤(pán)中),性能高,因此我們一般用redis來(lái)做緩存使用;并且redis支持豐富的數(shù)據(jù)類(lèi)型,比較容易解決各種問(wèn)題,因此redis可以用來(lái)作為注冊(cè)中心,?數(shù)據(jù)庫(kù)、緩存和消息中間件。Redis的Value支持5種數(shù)據(jù)類(lèi)型,string、hash、list、set、zset(sorted set);
String類(lèi)型:一個(gè)key對(duì)應(yīng)一個(gè)value
Hash類(lèi)型:它的key是string類(lèi)型,value又是一個(gè)map(key-value),適合存儲(chǔ)對(duì)象。
List類(lèi)型:按照插入順序的字符串鏈表(雙向鏈表),主要命令是LPUSH和RPUSH,能夠支持反向查找和遍歷
Set類(lèi)型:用哈希表類(lèi)型的字符串序列,沒(méi)有順序,集合成員是唯一的,沒(méi)有重復(fù)數(shù)據(jù),底層主要是由一個(gè)value永遠(yuǎn)為null的hashmap來(lái)實(shí)現(xiàn)的。
zset類(lèi)型:和set類(lèi)型基本一致,不過(guò)它會(huì)給每個(gè)元素關(guān)聯(lián)一個(gè)double類(lèi)型的分?jǐn)?shù)(score),這樣就可以為成員排序,并且插入是有序的。
你還用過(guò)其他的緩存嗎?這些緩存有什么區(qū)別?都在什么場(chǎng)景下去用?
對(duì)于緩存了解過(guò)redis和memcache
Memcache和redis的區(qū)別:
數(shù)據(jù)支持的類(lèi)型:redis不僅僅支持簡(jiǎn)單的k/v類(lèi)型的數(shù)據(jù),同時(shí)還支持list、set、zset、hash等數(shù)據(jù)結(jié)構(gòu)的存儲(chǔ);memcache只支持簡(jiǎn)單的k/v類(lèi)型的數(shù)據(jù),key和value都是string類(lèi)型
可靠性:memcache不支持?jǐn)?shù)據(jù)持久化,斷電或重啟后數(shù)據(jù)消失,但其穩(wěn)定性是有保證的;redis支持?jǐn)?shù)據(jù)持久化和數(shù)據(jù)恢復(fù),允許單點(diǎn)故障,但是同時(shí)也會(huì)付出性能的代價(jià)
性能上:對(duì)于存儲(chǔ)大數(shù)據(jù),memcache的性能要高于redis
應(yīng)用場(chǎng)景:
Memcache:適合多讀少寫(xiě),大數(shù)據(jù)量的情況(一些官網(wǎng)的文章信息等)
Redis:適用于對(duì)讀寫(xiě)效率要求高、數(shù)據(jù)處理業(yè)務(wù)復(fù)雜、安全性要求較高的系統(tǒng)
案例:分布式系統(tǒng),存在session之間的共享問(wèn)題,因此在做單點(diǎn)登錄的時(shí)候,我們利用redis來(lái)模擬了session的共享,來(lái)存儲(chǔ)用戶的信息,實(shí)現(xiàn)不同系統(tǒng)的session共享;
對(duì)redis的持久化了解不?
redis的持久化方式有兩種:
RDB(半持久化方式):按照配置不定期的通過(guò)異步的方式、快照的形式直接把內(nèi)存中的數(shù)據(jù)持久化到磁盤(pán)的一個(gè)dump.rdb文件(二進(jìn)制的臨時(shí)文件)中,redis默認(rèn)的持久化方式,它在配置文件(redis.conf)中。
優(yōu)點(diǎn):只包含一個(gè)文件,將一個(gè)單獨(dú)的文件轉(zhuǎn)移到其他存儲(chǔ)媒介上,對(duì)于文件備份、災(zāi)難恢復(fù)而言,比較實(shí)用。
缺點(diǎn):系統(tǒng)一旦在持久化策略之前出現(xiàn)宕機(jī)現(xiàn)象,此前沒(méi)有來(lái)得及持久化的數(shù)據(jù)將會(huì)產(chǎn)生丟失
RDB持久化配置:
Redis會(huì)將數(shù)據(jù)集的快照dump到dump.rdb文件中。此外,我們也可以通過(guò)配置文件來(lái)修改Redis服務(wù)器dump快照的頻率,在打開(kāi)6379.conf文件之后,我們搜索save,可以看到下面的配置信息:
save 900 1 #在900秒(15分鐘)之后,如果至少有1個(gè)key發(fā)生變化,則dump內(nèi)存快照。
save 300 10 #在300秒(5分鐘)之后,如果至少有10個(gè)key發(fā)生變化,則dump內(nèi)存快照。
save 60 10000 #在60秒(1分鐘)之后,如果至少有10000個(gè)key發(fā)生變化,則dump內(nèi)存快照。
AOF(全持久化的方式):把每一次數(shù)據(jù)變化都通過(guò)write()函數(shù)將你所執(zhí)行的命令追加到一個(gè)appendonly.aof文件里面,Redis默認(rèn)是不支持這種全持久化方式的,需要在配置文件(redis.conf)中將appendonly no改成appendonly yes
優(yōu)點(diǎn):數(shù)據(jù)安全性高,對(duì)日志文件的寫(xiě)入操作采用的是append模式,因此在寫(xiě)入過(guò)程中即使出現(xiàn)宕機(jī)問(wèn)題,也不會(huì)破壞日志文件中已經(jīng)存在的內(nèi)容;
缺點(diǎn):對(duì)于數(shù)量相同的數(shù)據(jù)集來(lái)說(shuō),aof文件通常要比rdb文件大,因此rdb在恢復(fù)大數(shù)據(jù)集時(shí)的速度大于AOF;
AOF持久化配置:
在Redis的配置文件中存在三種同步方式,它們分別是:
appendfsync always #每次有數(shù)據(jù)修改發(fā)生時(shí)都會(huì)都調(diào)用fsync刷新到aof文件,非常慢,但是安全;
appendfsync everysec #每秒鐘都調(diào)用fsync刷新到aof文件中,很快,但是可能丟失一秒內(nèi)的數(shù)據(jù),推薦使用,兼顧了速度和安全;
appendfsync no #不會(huì)自動(dòng)同步到磁盤(pán)上,需要依靠OS(操作系統(tǒng))進(jìn)行刷新,效率快,但是安全性就比較差;
二種持久化方式區(qū)別:
AOF在運(yùn)行效率上往往慢于RDB,每秒同步策略的效率是比較高的,同步禁用策略的效率和RDB一樣高效;
如果緩存數(shù)據(jù)安全性要求比較高的話,用aof這種持久化方式(比如項(xiàng)目中的購(gòu)物車(chē));
如果對(duì)于大數(shù)據(jù)集要求效率高的話,就可以使用默認(rèn)的。而且這兩種持久化方式可以同時(shí)使用。
做過(guò)redis的集群?jiǎn)??你們做集群的時(shí)候搭建了幾臺(tái),都是怎么搭建的?
Redis的數(shù)據(jù)是存放在內(nèi)存中的,不適合存儲(chǔ)大數(shù)據(jù),大數(shù)據(jù)存儲(chǔ)一般公司常用hadoop中的Hbase或者M(jìn)ogoDB。redis主要用來(lái)處理高并發(fā)的,用我們的項(xiàng)目來(lái)說(shuō),電商項(xiàng)目如果并發(fā)大的話,一臺(tái)單獨(dú)的redis是不能足夠支持我們的并發(fā),這就需要我們擴(kuò)展多臺(tái)設(shè)備協(xié)同合作,即用到集群。
Redis搭建集群的方式有多種,例如:客戶端分片、Twemproxy、Codis等,但是redis3.0之后就支持redis-cluster集群,這種方式采用的是無(wú)中心結(jié)構(gòu),每個(gè)節(jié)點(diǎn)保存數(shù)據(jù)和整個(gè)集群的狀態(tài),每個(gè)節(jié)點(diǎn)都和其他所有節(jié)點(diǎn)連接。如果使用的話就用redis-cluster集群。集群這塊是公司運(yùn)維搭建的,具體怎么搭建不是太了解。
我們項(xiàng)目中redis集群主要搭建了6臺(tái),3主(為了保證redis的投票機(jī)制)3從(高可用),每個(gè)主服務(wù)器都有一個(gè)從服務(wù)器,作為備份機(jī)。所有的節(jié)點(diǎn)都通過(guò)PING-PONG機(jī)制彼此互相連接;客戶端與redis集群連接,只需要連接集群中的任何一個(gè)節(jié)點(diǎn)即可;Redis-cluster中內(nèi)置了16384個(gè)哈希槽,Redis-cluster把所有的物理節(jié)點(diǎn)映射到【0-16383】slot上,負(fù)責(zé)維護(hù)。
redis有事務(wù)嗎?
Redis是有事務(wù)的,redis中的事務(wù)是一組命令的集合,這組命令要么都執(zhí)行,要不都不執(zhí)行,保證一個(gè)事務(wù)中的命令依次執(zhí)行而不被其他命令插入。redis的事務(wù)是不支持回滾操作的。redis事務(wù)的實(shí)現(xiàn),需要用到MULTI(事務(wù)的開(kāi)始)和EXEC(事務(wù)的結(jié)束)命令 ;
緩存穿透
緩存查詢(xún)一般都是通過(guò)key去查找value,如果不存在對(duì)應(yīng)的value,就要去數(shù)據(jù)庫(kù)中查找。如果這個(gè)key對(duì)應(yīng)的value在數(shù)據(jù)庫(kù)中也不存在,并且對(duì)該key并發(fā)請(qǐng)求很大,就會(huì)對(duì)數(shù)據(jù)庫(kù)產(chǎn)生很大的壓力,這就叫緩存穿透
解決方案:
1.對(duì)所有可能查詢(xún)的參數(shù)以hash形式存儲(chǔ),在控制層先進(jìn)行校驗(yàn),不符合則丟棄。
2.將所有可能存在的數(shù)據(jù)哈希到一個(gè)足夠大的bitmap中,一個(gè)一定不存在的數(shù)據(jù)會(huì)被這個(gè)bitmap攔截掉,從而避免了對(duì)底層存儲(chǔ)系統(tǒng)的查詢(xún)壓力。
3.如果一個(gè)查詢(xún)返回的數(shù)據(jù)為空(不管是數(shù) 據(jù)不存在,還是系統(tǒng)故障),我們?nèi)匀话堰@個(gè)空結(jié)果進(jìn)行緩存,但它的過(guò)期時(shí)間會(huì)很短,最長(zhǎng)不超過(guò)五分鐘。
緩存雪崩
當(dāng)緩存服務(wù)器重啟或者大量緩存集中在一段時(shí)間內(nèi)失效,發(fā)生大量的緩存穿透,這樣在失效的瞬間對(duì)數(shù)據(jù)庫(kù)的訪問(wèn)壓力就比較大,所有的查詢(xún)都落在數(shù)據(jù)庫(kù)上,造成了緩存雪崩。 這個(gè)沒(méi)有完美解決辦法,但可以分析用戶行為,盡量讓失效時(shí)間點(diǎn)均勻分布。大多數(shù)系統(tǒng)設(shè)計(jì)者考慮用加鎖或者隊(duì)列的方式保證緩存的單線程(進(jìn)程)寫(xiě),從而避免失效時(shí)大量的并發(fā)請(qǐng)求落到底層存儲(chǔ)系統(tǒng)上。
解決方案:
1.在緩存失效后,通過(guò)加鎖或者隊(duì)列來(lái)控制讀數(shù)據(jù)庫(kù)寫(xiě)緩存的線程數(shù)量。比如對(duì)某個(gè)key只允許一個(gè)線程查詢(xún)數(shù)據(jù)和寫(xiě)緩存,其他線程等待。
2.可以通過(guò)緩存reload機(jī)制,預(yù)先去更新緩存,再即將發(fā)生大并發(fā)訪問(wèn)前手動(dòng)觸發(fā)加載緩存
3.不同的key,設(shè)置不同的過(guò)期時(shí)間,讓緩存失效的時(shí)間點(diǎn)盡量均勻
4.做二級(jí)緩存,或者雙緩存策略。A1為原始緩存,A2為拷貝緩存,A1失效時(shí),可以訪問(wèn)A2,A1緩存失效時(shí)間設(shè)置為短期,A2設(shè)置為長(zhǎng)期。
redis的安全機(jī)制(你們公司redis的安全這方面怎么考慮的?)
漏洞介紹:redis默認(rèn)情況下,會(huì)綁定在bind 0.0.0.0:6379,這樣就會(huì)將redis的服務(wù)暴露到公網(wǎng)上,如果在沒(méi)有開(kāi)啟認(rèn)證的情況下,可以導(dǎo)致任意用戶在訪問(wèn)目標(biāo)服務(wù)器的情況下,未授權(quán)就可訪問(wèn)redis以及讀取redis的數(shù)據(jù),攻擊者就可以在未授權(quán)訪問(wèn)redis的情況下可以利用redis的相關(guān)方法,成功在redis服務(wù)器上寫(xiě)入公鑰,進(jìn)而可以直接使用私鑰進(jìn)行直接登錄目標(biāo)主機(jī);
解決方案:
禁止一些高危命令。修改redis.conf文件,用來(lái)禁止遠(yuǎn)程修改DB文件地址,比如 rename-command FLUSHALL "" 、rename-command CONFIG"" 、rename-command EVAL “”等;
以低權(quán)限運(yùn)行redis服務(wù)。為redis服務(wù)創(chuàng)建單獨(dú)的用戶和根目錄,并且配置禁止登錄;
為redis添加密碼驗(yàn)證。修改redis.conf文件,添加requirepass mypassword;
禁止外網(wǎng)訪問(wèn)redis。修改redis.conf文件,添加或修改 bind 127.0.0.1,使得redis服務(wù)只在當(dāng)前主機(jī)使用;
做log監(jiān)控,及時(shí)發(fā)現(xiàn)攻擊;
redis的哨兵機(jī)制(redis2.6以后出現(xiàn)的)
哨兵機(jī)制:
監(jiān)控:監(jiān)控主數(shù)據(jù)庫(kù)和從數(shù)據(jù)庫(kù)是否正常運(yùn)行;
提醒:當(dāng)被監(jiān)控的某個(gè)redis出現(xiàn)問(wèn)題的時(shí)候,哨兵可以通過(guò)API向管理員或者其他應(yīng)用程序發(fā)送通知;
自動(dòng)故障遷移:主數(shù)據(jù)庫(kù)出現(xiàn)故障時(shí),可以自動(dòng)將從數(shù)據(jù)庫(kù)轉(zhuǎn)化為主數(shù)據(jù)庫(kù),實(shí)現(xiàn)自動(dòng)切換;
具體的配置步驟參考的網(wǎng)上的文檔。要注意的是,如果master主服務(wù)器設(shè)置了密碼,記得在哨兵的配置文件(sentinel.conf)里面配置訪問(wèn)密碼
redis中對(duì)于生存時(shí)間的應(yīng)用
Redis中可以使用expire命令設(shè)置一個(gè)鍵的生存時(shí)間,到時(shí)間后redis會(huì)自動(dòng)刪除;
應(yīng)用場(chǎng)景:
設(shè)置限制的優(yōu)惠活動(dòng)的信息;
一些及時(shí)需要更新的數(shù)據(jù),積分排行榜;
手機(jī)驗(yàn)證碼的時(shí)間;
限制網(wǎng)站訪客訪問(wèn)頻率;
(數(shù)據(jù)庫(kù)和redis的數(shù)據(jù)如何保持一致)雙刪策略
https://blog.csdn.net/bntX2jSQfEHy7/article/details/80416687?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromBaidu-1.nonecase&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromBaidu-1.nonecase
redis本人被問(wèn)到的較少,所以只是寫(xiě)了簡(jiǎn)單的一些面試題