Redis有哪些數(shù)據(jù)結(jié)構(gòu)性湿?
字符串String、字典Hash襟衰、列表List贴铜、集合Set、有序集合SortedSet瀑晒。
如果你是Redis中高級(jí)用戶(hù)阀湿,還需要加上下面幾種數(shù)據(jù)結(jié)構(gòu)HyperLogLog、Geo瑰妄、Pub/Sub陷嘴。
如果你說(shuō)還玩過(guò)Redis Module,像BloomFilter间坐,RedisSearch灾挨,Redis-ML,面試官得眼睛就開(kāi)始發(fā)亮了竹宋。
使用過(guò)Redis分布式鎖么劳澄,它是什么回事?
先拿setnx來(lái)爭(zhēng)搶鎖蜈七,搶到之后秒拔,再用expire給鎖加一個(gè)過(guò)期時(shí)間防止鎖忘記了釋放。
這時(shí)候?qū)Ψ綍?huì)告訴你說(shuō)你回答得不錯(cuò)飒硅,然后接著問(wèn)如果在setnx之后執(zhí)行expire之前進(jìn)程意外crash或者要重啟維護(hù)了砂缩,那會(huì)怎么樣作谚?
這時(shí)候你要給予驚訝的反饋:唉,是喔庵芭,這個(gè)鎖就永遠(yuǎn)得不到釋放了妹懒。緊接著你需要抓一抓自己得腦袋,故作思考片刻双吆,好像接下來(lái)的結(jié)果是你主動(dòng)思考出來(lái)的眨唬,然后回答:我記得set指令有非常復(fù)雜的參數(shù),這個(gè)應(yīng)該是可以同時(shí)把setnx和expire合成一條指令來(lái)用的好乐!對(duì)方這時(shí)會(huì)顯露笑容匾竿,心里開(kāi)始默念:摁,這小子還不錯(cuò)蔚万。
假如Redis里面有1億個(gè)key搂橙,其中有10w個(gè)key是以某個(gè)固定的已知的前綴開(kāi)頭的,如果將它們?nèi)空页鰜?lái)笛坦?
使用keys指令可以?huà)叱鲋付J降膋ey列表区转。
對(duì)方接著追問(wèn):如果這個(gè)redis正在給線(xiàn)上的業(yè)務(wù)提供服務(wù),那使用keys指令會(huì)有什么問(wèn)題版扩?
這個(gè)時(shí)候你要回答redis關(guān)鍵的一個(gè)特性:redis的單線(xiàn)程的废离。keys指令會(huì)導(dǎo)致線(xiàn)程阻塞一段時(shí)間,線(xiàn)上服務(wù)會(huì)停頓礁芦,直到指令執(zhí)行完畢蜻韭,服務(wù)才能恢復(fù)。這個(gè)時(shí)候可以使用scan指令柿扣,scan指令可以無(wú)阻塞的提取出指定模式的key列表肖方,但是會(huì)有一定的重復(fù)概率,在客戶(hù)端做一次去重就可以了未状,但是整體所花費(fèi)的時(shí)間會(huì)比直接用keys指令長(zhǎng)俯画。
使用過(guò)Redis做異步隊(duì)列么,你是怎么用的司草?
一般使用list結(jié)構(gòu)作為隊(duì)列艰垂,rpush生產(chǎn)消息,lpop消費(fèi)消息埋虹。當(dāng)lpop沒(méi)有消息的時(shí)候猜憎,要適當(dāng)sleep一會(huì)再重試。
如果對(duì)方追問(wèn)可不可以不用sleep呢搔课?list還有個(gè)指令叫blpop胰柑,在沒(méi)有消息的時(shí)候,它會(huì)阻塞住直到消息到來(lái)。
如果對(duì)方追問(wèn)能不能生產(chǎn)一次消費(fèi)多次呢柬讨?使用pub/sub主題訂閱者模式崩瓤,可以實(shí)現(xiàn)1:N的消息隊(duì)列。
如果對(duì)方追問(wèn)pub/sub有什么缺點(diǎn)姐浮?在消費(fèi)者下線(xiàn)的情況下,生產(chǎn)的消息會(huì)丟失葬馋,得使用專(zhuān)業(yè)的消息隊(duì)列如rabbitmq等卖鲤。
如果對(duì)方追問(wèn)redis如何實(shí)現(xiàn)延時(shí)隊(duì)列?我估計(jì)現(xiàn)在你很想把面試官一棒打死如果你手上有一根棒球棍的話(huà)畴嘶,怎么問(wèn)的這么詳細(xì)蛋逾。但是你很克制,然后神態(tài)自若的回答道:使用sortedset窗悯,拿時(shí)間戳作為score区匣,消息內(nèi)容作為key調(diào)用zadd來(lái)生產(chǎn)消息,消費(fèi)者用zrangebyscore指令獲取N秒之前的數(shù)據(jù)輪詢(xún)進(jìn)行處理蒋院。
到這里亏钩,面試官暗地里已經(jīng)對(duì)你豎起了大拇指。但是他不知道的是此刻你卻豎起了中指欺旧,在椅子背后姑丑。
如果有大量的key需要設(shè)置同一時(shí)間過(guò)期,一般需要注意什么辞友?
如果大量的key過(guò)期時(shí)間設(shè)置的過(guò)于集中栅哀,到過(guò)期的那個(gè)時(shí)間點(diǎn),redis可能會(huì)出現(xiàn)短暫的卡頓現(xiàn)象称龙。一般需要在時(shí)間上加一個(gè)隨機(jī)值留拾,使得過(guò)期時(shí)間分散一些。
Redis如何做持久化的鲫尊?
bgsave做鏡像全量持久化痴柔,aof做增量持久化。因?yàn)閎gsave會(huì)耗費(fèi)較長(zhǎng)時(shí)間疫向,不夠?qū)崟r(shí)竞帽,在停機(jī)的時(shí)候會(huì)導(dǎo)致大量丟失數(shù)據(jù),所以需要aof來(lái)配合使用鸿捧。在redis實(shí)例重啟時(shí)屹篓,會(huì)使用bgsave持久化文件重新構(gòu)建內(nèi)存,再使用aof重放近期的操作指令來(lái)實(shí)現(xiàn)完整恢復(fù)重啟之前的狀態(tài)匙奴。
對(duì)方追問(wèn)那如果突然機(jī)器掉電會(huì)怎樣堆巧?取決于aof日志sync屬性的配置,如果不要求性能,在每條寫(xiě)指令時(shí)都sync一下磁盤(pán)谍肤,就不會(huì)丟失數(shù)據(jù)啦租。但是在高性能的要求下每次都sync是不現(xiàn)實(shí)的,一般都使用定時(shí)sync荒揣,比如1s1次篷角,這個(gè)時(shí)候最多就會(huì)丟失1s的數(shù)據(jù)。
對(duì)方追問(wèn)bgsave的原理是什么系任?你給出兩個(gè)詞匯就可以了恳蹲,fork和cow。fork是指redis通過(guò)創(chuàng)建子進(jìn)程來(lái)進(jìn)行bgsave操作俩滥,cow指的是copy on write嘉蕾,子進(jìn)程創(chuàng)建后,父子進(jìn)程共享數(shù)據(jù)段霜旧,父進(jìn)程繼續(xù)提供讀寫(xiě)服務(wù)错忱,寫(xiě)臟的頁(yè)面數(shù)據(jù)會(huì)逐漸和子進(jìn)程分離開(kāi)來(lái)。
Pipeline有什么好處挂据,為什么要用pipeline以清?
可以將多次IO往返的時(shí)間縮減為一次,前提是pipeline執(zhí)行的指令之間沒(méi)有因果相關(guān)性崎逃。使用redis-benchmark進(jìn)行壓測(cè)的時(shí)候可以發(fā)現(xiàn)影響redis的QPS峰值的一個(gè)重要因素是pipeline批次指令的數(shù)目玖媚。
Redis的同步機(jī)制了解么?
Redis可以使用主從同步婚脱,從從同步今魔。第一次同步時(shí),主節(jié)點(diǎn)做一次bgsave障贸,并同時(shí)將后續(xù)修改操作記錄到內(nèi)存buffer错森,待完成后將rdb文件全量同步到復(fù)制節(jié)點(diǎn),復(fù)制節(jié)點(diǎn)接受完成后將rdb鏡像加載到內(nèi)存篮洁。加載完成后涩维,再通知主節(jié)點(diǎn)將期間修改的操作記錄同步到復(fù)制節(jié)點(diǎn)進(jìn)行重放就完成了同步過(guò)程。
是否使用過(guò)Redis集群袁波,集群的原理是什么瓦阐?
Redis Sentinal著眼于高可用,在master宕機(jī)時(shí)會(huì)自動(dòng)將slave提升為master篷牌,繼續(xù)提供服務(wù)睡蟋。
Redis Cluster著眼于擴(kuò)展性,在單個(gè)redis內(nèi)存不足時(shí)枷颊,使用Cluster進(jìn)行分片存儲(chǔ)戳杀。