Redis高頻面試題

Redis肉盹,全稱:Remote Dictionary Server萨西,是一個(gè)基于內(nèi)存的高性能key-value數(shù)據(jù)庫妄壶,是應(yīng)用服務(wù)提高效率和性能必不可少的一部分霞扬,因?yàn)楫?dāng)前大部分的應(yīng)用都離不開Redis,所以學(xué)習(xí)并熟練Redis操作已經(jīng)成為一個(gè)必不可少的技能拜轨。當(dāng)然抽减,面試中,Redis也深受面試官喜愛橄碾,下面就為大家整理匯總Redis的高頻面試題卵沉,希望能給鄉(xiāng)親們一點(diǎn)幫助。

1法牲、什么是 Redis?簡(jiǎn)述它的優(yōu)缺點(diǎn)?

Redis 的全稱是:Remote Dictionary.Server史汗,本質(zhì)上是一個(gè) Key-Value 類型的內(nèi)存數(shù)據(jù)庫,很像memcached拒垃,整個(gè)數(shù)據(jù)庫統(tǒng)統(tǒng)加載在內(nèi)存當(dāng)中進(jìn)行操作停撞,定期通過異步操作把數(shù)據(jù)庫數(shù)據(jù) flush 到硬盤 上進(jìn)行保存。
因?yàn)槭羌儍?nèi)存操作悼瓮,Redis 的性能非常出色戈毒,每秒可以處理超過 10 萬次讀寫操作,是已知性能最快的Key-Value DB横堡。
Redis 的出色之處不僅僅是性能埋市,Redis 最大的魅力是支持保存多種數(shù)據(jù)結(jié)構(gòu),此外單個(gè) value 的最大限 制是 1GB命贴,不像 memcached 只能保存 1MB 的數(shù)據(jù)道宅,因此 Redis 可以用來實(shí)現(xiàn)很多有用的功能食听。比方說用他的 List 來做 FIFO 雙向鏈表,實(shí)現(xiàn)一個(gè)輕量級(jí)的高性 能消息隊(duì)列服務(wù)污茵,用他的 Set 可以做高 性能的 tag 系統(tǒng)等等樱报。
另外 Redis 也可以對(duì)存入的 Key-Value 設(shè)置 expire 時(shí)間,因此也可以被當(dāng)作一 個(gè)功能加強(qiáng)版的memcached 來用泞当。
Redis 的主要缺點(diǎn)是數(shù)據(jù)庫容量受到物理內(nèi)存的限制迹蛤,不能用作海量數(shù)據(jù)的高性能 讀寫,因此 Redis 適合的場(chǎng)景主要局限在較小數(shù)據(jù)量的高性能操作和運(yùn)算上襟士。
2笤受、使用redis有哪些好處?

速度快敌蜂,因?yàn)閿?shù)據(jù)存在內(nèi)存中,類似于HashMap津肛,HashMap的優(yōu)勢(shì)就是查找和操作的時(shí)間復(fù)雜度都是O(1)章喉。

支持豐富數(shù)據(jù)類型,支持string身坐,list秸脱,set,sorted set部蛇,hash

支持事務(wù)摊唇,操作都是原子性,所謂的原子性就是對(duì)數(shù)據(jù)的更改要么全部執(zhí)行涯鲁,要么全部不執(zhí)行巷查。

豐富的特性:可用于緩存,消息抹腿,按key設(shè)置過期時(shí)間岛请,過期后將會(huì)自動(dòng)刪除。

3警绩、Redis支持哪幾種數(shù)據(jù)類型崇败?

答:Redis支持五種數(shù)據(jù)類型:string(字符串),hash(哈希)肩祥,list(列表)后室,set(集合)及zset(sorted set:有序集合)。
還有一些數(shù)據(jù)結(jié)構(gòu)如HyperLogLog混狠、Geo岸霹、Pub/Sub等,我們也最好知道檀蹋,另外像Redis Module松申,像BloomFilter云芦,RedisSearch,Redis-ML等贸桶,能有個(gè)印象舅逸,哪怕知其然不知其所以然也比聽都沒聽過好點(diǎn)。

4皇筛、Redis有哪幾種淘汰策略琉历?

Redis的內(nèi)存淘汰策略是指在Redis的用于緩存的內(nèi)存不足時(shí),怎么處理需要新寫入且需要申請(qǐng)額外空間的數(shù)據(jù)水醋。
no-eviction:當(dāng)內(nèi)存不足以容納新寫入數(shù)據(jù)時(shí)旗笔,新寫入操作會(huì)報(bào)錯(cuò)。

allkeys-lru:當(dāng)內(nèi)存不足以容納新寫入數(shù)據(jù)時(shí)拄踪,在鍵空間中蝇恶,移除最近最少使用的key。

allkeys-random:當(dāng)內(nèi)存不足以容納新寫入數(shù)據(jù)時(shí)惶桐,在鍵空間中撮弧,隨機(jī)移除某個(gè)key。

volatile-lru:當(dāng)內(nèi)存不足以容納新寫入數(shù)據(jù)時(shí)姚糊,在設(shè)置了過期時(shí)間的鍵空間中贿衍,移除最近最少使用的key。

volatile-random:當(dāng)內(nèi)存不足以容納新寫入數(shù)據(jù)時(shí)救恨,在設(shè)置了過期時(shí)間的鍵空間中贸辈,隨機(jī)移除某個(gè)key。

volatile-ttl:當(dāng)內(nèi)存不足以容納新寫入數(shù)據(jù)時(shí)肠槽,在設(shè)置了過期時(shí)間的鍵空間中擎淤,有更早過期時(shí)間的key優(yōu)先移除。

注意這里的6種機(jī)制署浩,volatile和allkeys規(guī)定了是對(duì)已設(shè)置過期時(shí)間的數(shù)據(jù)集淘汰數(shù)據(jù)還是從全部數(shù)據(jù)集淘汰數(shù)據(jù)揉燃,后面的lru、ttl以及random是三種不同的淘汰策略筋栋,再加上一種no-enviction永不回收的策略炊汤。  
使用策略規(guī)則:

如果數(shù)據(jù)呈現(xiàn)冪律分布弊攘,也就是一部分?jǐn)?shù)據(jù)訪問頻率高抢腐,一部分?jǐn)?shù)據(jù)訪問頻率低,則使用allkeys-lru

如果數(shù)據(jù)呈現(xiàn)平等分布襟交,也就是所有的數(shù)據(jù)訪問頻率都相同迈倍,則使用allkeys-random

5、為什么 Redis 需要把所有數(shù)據(jù)放到內(nèi)存中?

答:Redis 為了達(dá)到最快的讀寫速度將數(shù)據(jù)都讀到內(nèi)存中捣域,并通過異步的方式將數(shù)據(jù)寫入磁盤啼染。所以 redis 具有快速和數(shù)據(jù)持久化的特征宴合,如果不將數(shù)據(jù)放在內(nèi)存中,磁盤 I/O 速度為嚴(yán)重影響 redis 的 性能迹鹅。
在內(nèi)存越來越便宜的今天卦洽,redis 將會(huì)越來越受歡迎, 如果設(shè)置了最大使用的內(nèi)存斜棚,則數(shù)據(jù)已有記錄數(shù)達(dá) 到內(nèi)存限值后不能繼續(xù)插入新值阀蒂。
6、Redis 有哪些適合的場(chǎng)景?

(1)會(huì)話緩存(Session Cache)
最常用的一種使用 Redis 的情景是會(huì)話緩存(sessioncache)弟蚀,用 Redis 緩存會(huì)話比其他存儲(chǔ)(如Memcached)的優(yōu)勢(shì)在于:Redis 提供持久化蚤霞。當(dāng)維護(hù)一個(gè)不是嚴(yán)格要求一致性的緩存時(shí),如果用戶的 購物車信息全部丟失义钉,大部分人都會(huì)不高興的昧绣,現(xiàn)在,他們還會(huì)這樣嗎?
幸運(yùn)的是捶闸,隨著 Redis 這些年的改進(jìn)滞乙,很容易找到怎么恰當(dāng)?shù)氖褂?Redis 來緩存會(huì)話的文檔。甚至廣為 人知的商業(yè)平臺(tái) Magento 也提供 Redis 的插件鉴嗤。
(2)全頁緩存(FPC)

除基本的會(huì)話 token 之外,Redis 還提供很簡(jiǎn)便的 FPC 平臺(tái)序调∽砉回到一致性問題,即使重啟了 Redis 實(shí) 例发绢,因?yàn)橛写疟P的持久化硬耍,用戶也不會(huì)看到頁面加載速度的下降,這是一個(gè)極大改進(jìn)边酒,類似 PHP 本地FPC经柴。

再次以 Magento 為例,Magento 提供一個(gè)插件來使用 Redis 作為全頁緩存后端墩朦。此外坯认,對(duì) WordPress 的用戶來說,Pantheon 有一個(gè)非常好的插件 wp-redis氓涣,這個(gè)插件能幫助你以最快 速度加載你曾瀏覽過的頁面牛哺。
(3)隊(duì)列

Reids 在內(nèi)存存儲(chǔ)引擎領(lǐng)域的一大優(yōu)點(diǎn)是提供 list 和 set 操作,這使得 Redis 能作為一個(gè)很好的消息隊(duì)列 平臺(tái)來使用劳吠。Redis 作為隊(duì)列使用的操作引润,就類似于本地程序語言(如 Python)對(duì) list 的 push/pop操作。

如果你快速的在 Google 中搜索“Redis queues”痒玩,你馬上就能找到大量的開源項(xiàng)目淳附,這些項(xiàng)目的目的 就是利用 Redis 創(chuàng)建非常好的后端工具议慰,以滿足各種隊(duì)列需求。例如奴曙,Celery 有一個(gè)后臺(tái)就是使用Redis 作為 broker别凹,你可以從這里去查看。
(4)排行榜/計(jì)數(shù)器

Redis 在內(nèi)存中對(duì)數(shù)字進(jìn)行遞增或遞減的操作實(shí)現(xiàn)的非常好缆毁。集合(Set)和有序集合(SortedSet)也使 得我們?cè)趫?zhí)行這些操作的時(shí)候變的非常簡(jiǎn)單番川,Redis 只是正好提供了這兩種數(shù)據(jù)結(jié)構(gòu)。所以脊框,我們要從排序集合中獲取到排名最靠前的 10 個(gè)用戶–我們稱之為“user_scores”颁督,我們只需要像 下面一樣執(zhí)行即可: 當(dāng)然,這是假定你是根據(jù)你用戶的分?jǐn)?shù)做遞增的排序浇雹。如果你想返回用戶及用戶的分?jǐn)?shù)沉御,你需要這樣執(zhí) 行:
ZRANGE user_scores 0 10 WITHSCORES

Agora Games 就是一個(gè)很好的例子,用 Ruby 實(shí)現(xiàn)的昭灵,它的排行榜就是使用 Redis 來存儲(chǔ)數(shù)據(jù)的吠裆,你可 以在這里看到。
(5)發(fā)布/訂閱

最后(但肯定不是最不重要的)是 Redis 的發(fā)布/訂閱功能烂完。發(fā)布/訂閱的使用場(chǎng)景確實(shí)非常多试疙。我已看見 人們?cè)谏缃痪W(wǎng)絡(luò)連接中使用,還可作為基于發(fā)布/訂閱的腳本觸發(fā)器抠蚣,甚至用 Redis 的發(fā)布/訂閱功能來建 立聊天系統(tǒng)!

7祝旷、說說 Redis 哈希槽的概念?

Redis 集群沒有使用一致性 hash,而是引入了哈希槽的概念,Redis 集群有 16384 個(gè)哈希槽嘶窄,每個(gè) key 通 過 CRC16 校驗(yàn)后對(duì) 16384 取模來決定放置哪個(gè)槽怀跛,集群的每個(gè)節(jié)點(diǎn)負(fù)責(zé)一部分 hash 槽。

8柄冲、Redis 集群的主從復(fù)制模型是怎樣的?

為了使在部分節(jié)點(diǎn)失敗或者大部分節(jié)點(diǎn)無法通信的情況下集群仍然可用吻谋,所以集群使用了主從復(fù)制模型,每個(gè)節(jié)點(diǎn)都會(huì)有 N-1 個(gè)復(fù)制品。

9现横、Redis 集群會(huì)有寫操作丟失嗎?為什么?

Redis 并不能保證數(shù)據(jù)的強(qiáng)一致性漓拾,這意味這在實(shí)際中集群在特定的條件下可能會(huì)丟失寫操作。

10戒祠、Redis 集群之間是如何復(fù)制的?
答:異步復(fù)制

11晦攒、Redis 中的管道有什么用?
一次請(qǐng)求/響應(yīng)服務(wù)器能實(shí)現(xiàn)處理新的請(qǐng)求即使舊的請(qǐng)求還未被響應(yīng),這樣就可以將多個(gè)命令發(fā)送到服務(wù) 器得哆,而不用等待回復(fù)脯颜,最后在一個(gè)步驟中讀取該答復(fù)。這就是管道(pipelining)贩据,是一種幾十年來廣泛使用的技術(shù)栋操。例如許多 POP3 協(xié)議已經(jīng)實(shí)現(xiàn)支持這個(gè)功 能闸餐,大大加快了從服務(wù)器下載新郵件的過程。

12矾芙、怎么理解 Redis 事務(wù)?

事務(wù)是一個(gè)單獨(dú)的隔離操作:事務(wù)中的所有命令都會(huì)序列化舍沙、按順序地執(zhí)行,事務(wù)在執(zhí)行的過程中剔宪,不會(huì) 被其他客戶端發(fā)送來的命令請(qǐng)求所打斷拂铡。

事務(wù)是一個(gè)原子操作:事務(wù)中的命令要么全部被執(zhí)行,要么全部都不執(zhí)行葱绒。

13感帅、Redis 事務(wù)相關(guān)的命令有哪幾個(gè)?

MULTI、EXEC地淀、DISCARD失球、WATCH

14、Redis key 的過期時(shí)間和永久有效分別怎么設(shè)置?

EXPIRE 和 PERSIST 命令

15帮毁、Redis 如何做內(nèi)存優(yōu)化?

盡可能使用散列表(hashes)实苞,散列表(是說散列表里面存儲(chǔ)的數(shù)少)使用的內(nèi)存非常小,所以你應(yīng)該 盡可能的將你的數(shù)據(jù)模型抽象到一個(gè)散列表里面烈疚。
比如你的 web 系統(tǒng)中有一個(gè)用戶對(duì)象黔牵,不要為這個(gè)用戶的名稱,姓氏爷肝,郵箱荧止,密碼設(shè)置單獨(dú)的 key,而是 應(yīng)該把這個(gè)用戶的所有信息存儲(chǔ)到一張散列表里面。

16阶剑、Redis 回收進(jìn)程如何工作的?
一個(gè)客戶端運(yùn)行了新的命令,添加了新的數(shù)據(jù)危号。Redi 檢查內(nèi)存使用情況牧愁,如果大于 maxmemory 的限制, 則根據(jù)設(shè)定好的策略進(jìn)行回收。一個(gè)新的命令被執(zhí)行外莲,等等猪半。所以我們不斷地穿越內(nèi)存限制的邊界,通過不斷達(dá)到邊界然后不斷地回收回到邊界以下偷线。如果一個(gè)命令的結(jié)果導(dǎo)致大量?jī)?nèi)存被使用(例如很大的集合的交集保存到一個(gè)新的鍵)磨确,不用多久內(nèi)存限 制就會(huì)被這個(gè)內(nèi)存使用量超越。

17声邦、Redis集群最大節(jié)點(diǎn)個(gè)數(shù)是多少乏奥?
答:16384個(gè)。

18亥曹、Redis集群如何選擇數(shù)據(jù)庫邓了?
答:Redis集群目前無法做數(shù)據(jù)庫選擇恨诱,默認(rèn)在0數(shù)據(jù)庫。

19骗炉、都有哪些辦法可以降低Redis的內(nèi)存使用情況呢照宝?

答:如果你使用的是32位的Redis實(shí)例,可以好好利用Hash,list,sorted set,set等集合類型數(shù)據(jù)句葵,因?yàn)橥ǔG闆r下很多小的Key-Value可以用更緊湊的方式存放到一起厕鹃。

20、Redis的內(nèi)存用完了會(huì)發(fā)生什么乍丈?

答:如果達(dá)到設(shè)置的上限剂碴,Redis的寫命令會(huì)返回錯(cuò)誤信息(但是讀命令還可以正常返回。)或者你可以將Redis當(dāng)緩存來使用配置淘汰機(jī)制诗赌,當(dāng)Redis達(dá)到內(nèi)存上限時(shí)會(huì)沖刷掉舊的內(nèi)容汗茄。

21、一個(gè)Redis實(shí)例最多能存放多少的keys铭若?List洪碳、Set、Sorted Set他們最多能存放多少元素叼屠?

答:理論上Redis可以處理多達(dá)232的keys瞳腌,并且在實(shí)際中進(jìn)行了測(cè)試,每個(gè)實(shí)例至少存放了2億5千萬的keys镜雨。我們正在測(cè)試一些較大的值嫂侍。任何list、set荚坞、和sorted set都可以放232個(gè)元素挑宠。換句話說,Redis的存儲(chǔ)極限是系統(tǒng)中的可用內(nèi)存值颓影。

22各淀、假如Redis里面有1億個(gè)key,其中有10w個(gè)key是以某個(gè)固定的已知的前綴開頭的诡挂,如果將它們?nèi)空页鰜恚?/p>

答:使用keys指令可以掃出指定模式的key列表碎浇。

23、如果這個(gè)redis正在給線上的業(yè)務(wù)提供服務(wù)璃俗,那使用keys指令會(huì)有什么問題奴璃?

答:redis的單線程的。keys指令會(huì)導(dǎo)致線程阻塞一段時(shí)間城豁,線上服務(wù)會(huì)停頓苟穆,直到指令執(zhí)行完畢,服務(wù)才能恢復(fù)。這個(gè)時(shí)候可以使用scan指令鞭缭,scan指令可以無阻塞的提取出指定模式的key列表剖膳,但是會(huì)有一定的重復(fù)概率,在客戶端做一次去重就可以了岭辣,但是整體所花費(fèi)的時(shí)間會(huì)比直接用keys指令長吱晒。

24、如果有大量的key需要設(shè)置同一時(shí)間過期沦童,一般需要注意什么仑濒?

答:如果大量的key過期時(shí)間設(shè)置的過于集中,到過期的那個(gè)時(shí)間點(diǎn)偷遗,redis可能會(huì)出現(xiàn)短暫的卡頓現(xiàn)象墩瞳。一般需要在時(shí)間上加一個(gè)隨機(jī)值,使得過期時(shí)間分散一些氏豌。

25喉酌、Redis 集群方案應(yīng)該怎么做?都有哪些方案泵喘?

codis:目前用的最多的集群方案泪电,基本和 twemproxy 一致的效果,但它支持在節(jié)點(diǎn)數(shù)量改變情況下纪铺,舊節(jié)點(diǎn)數(shù)據(jù)可恢復(fù)到新 hash 節(jié)點(diǎn)相速。

redis cluster3.0 自帶的集群,特點(diǎn)在于他的分布式算法不是一致性 hash鲜锚,而是 hash 槽的概念突诬,以及自身支持節(jié)點(diǎn)設(shè)置從節(jié)點(diǎn)。具體看官方文檔介紹芜繁。

在業(yè)務(wù)代碼層實(shí)現(xiàn)旺隙,起幾個(gè)毫無關(guān)聯(lián)的 redis 實(shí)例,在代碼層骏令,對(duì) key 進(jìn)行 hash 計(jì)算蔬捷,然后去對(duì)應(yīng)的redis 實(shí)例操作數(shù)據(jù)。這種方式對(duì) hash 層代碼要求比較高伏社,考慮部分包括,節(jié)點(diǎn)失效后的替代算法方案塔淤,數(shù)據(jù)震蕩后的自動(dòng)腳本恢復(fù)摘昌,實(shí)例的監(jiān)控,等等高蜂。

26聪黎、使用過 Redis 分布式鎖么,它是怎么實(shí)現(xiàn)的?

答:先拿 setnx 來爭(zhēng)搶鎖,搶到之后稿饰,再用 expire 給鎖加一個(gè)過期時(shí)間防止鎖忘記了釋放锦秒。

27、如果在 setnx 之后執(zhí)行 expire 之前進(jìn)程意外 crash 或者要重啟維護(hù)了喉镰,那會(huì)怎么樣?

答:set 指令有非常復(fù)雜的參數(shù)旅择,這個(gè)應(yīng)該是可以同時(shí)把 setnx 和 expire 合成一條指令來用的!

28、使用過 Redis 做異步隊(duì)列么侣姆,你是怎么用的?有什么缺點(diǎn)?

一般使用 list 結(jié)構(gòu)作為隊(duì)列生真,rpush 生產(chǎn)消息,lpop 消費(fèi)消息捺宗。當(dāng) lpop 沒有消息的時(shí)候柱蟀,要適當(dāng) sleep 一會(huì)再重試。
缺點(diǎn):在消費(fèi)者下線的情況下蚜厉,生產(chǎn)的消息會(huì)丟失长已,得使用專業(yè)的消息隊(duì)列如 rabbitmq 等。
能不能生產(chǎn)一次消費(fèi)多次呢?
使用 pub/sub 主題訂閱者模式昼牛,可以實(shí)現(xiàn) 1:N 的消息隊(duì)列术瓮。

29、緩存穿透匾嘱、緩存擊穿斤斧、緩存雪崩解決方案?

緩存穿透:指查詢一個(gè)一定不存在的數(shù)據(jù),如果從存儲(chǔ)層查不到數(shù)據(jù)則不寫入緩存霎烙,這將 導(dǎo)致這個(gè)不存在的數(shù)據(jù)每次請(qǐng)求都要到 DB 去查詢撬讽,可能導(dǎo)致 DB 掛掉。

解決方案:

1.查詢返回的數(shù)據(jù)為空悬垃,仍把這個(gè)空結(jié)果進(jìn)行緩存游昼,但過期時(shí)間會(huì)比較短;

2.布 隆過濾器:將所有可能存在的數(shù)據(jù)哈希到一個(gè)足夠大的 bitmap 中,一個(gè)一定不存在的數(shù)據(jù) 會(huì)被這個(gè) bitmap 攔截掉尝蠕,從而避免了對(duì) DB 的查詢烘豌。

緩存擊穿:對(duì)于設(shè)置了過期時(shí)間的 key,緩存在某個(gè)時(shí)間點(diǎn)過期的時(shí)候看彼,恰好這時(shí)間點(diǎn)對(duì) 這個(gè) Key 有大量的并發(fā)請(qǐng)求過來廊佩,這些請(qǐng)求發(fā)現(xiàn)緩存過期一般都會(huì)從后端 DB 加載數(shù)據(jù)并 回設(shè)到緩存,這個(gè)時(shí)候大并發(fā)的請(qǐng)求可能會(huì)瞬間把 DB 壓垮靖榕。

解決方案:

1.使用互斥鎖:當(dāng)緩存失效時(shí)标锄,不立即去load db,先使用如Redis的setnx去設(shè) 置一個(gè)互斥鎖茁计,當(dāng)操作成功返回時(shí)再進(jìn)行l(wèi)oad db的操作并回設(shè)緩存料皇,否則重試get緩存的 方法。

2.永遠(yuǎn)不過期:物理不過期,但邏輯過期(后臺(tái)異步線程去刷新)践剂。

緩存雪崩:設(shè)置緩存時(shí)采用了相同的過期時(shí)間鬼譬,導(dǎo)致緩存在某一時(shí)刻同時(shí)失效,請(qǐng)求全部 轉(zhuǎn)發(fā)到 DB逊脯,DB 瞬時(shí)壓力過重雪崩优质。與緩存擊穿的區(qū)別:雪崩是很多 key,擊穿是某一個(gè)key 緩存男窟。

解決方案:

將緩存失效時(shí)間分散開盆赤,比如可以在原有的失效時(shí)間基礎(chǔ)上增加一個(gè)隨機(jī)值, 比如 1-5 分鐘隨機(jī)歉眷,這樣每一個(gè)緩存的過期時(shí)間的重復(fù)率就會(huì)降低牺六,就很難引發(fā)集體失效 的事件。

30汗捡、為什么redis單線程還是那么快淑际?

答:redis利用隊(duì)列技術(shù)將并發(fā)訪問變?yōu)榇性L問,消除了傳統(tǒng)數(shù)據(jù)庫串行控制的開銷扇住。
31春缕、使用 redis 如何設(shè)計(jì)分布式鎖?說一下實(shí)現(xiàn)思路?使用 zk 可以嗎?如何實(shí)現(xiàn)?這兩種有什 么區(qū)別?

redis:

線程 A setnx(上鎖的對(duì)象,超時(shí)時(shí)的時(shí)間戳 t1),如果返回 true艘蹋,獲得鎖锄贼。

線程 B 用 get 獲取 t1,與當(dāng)前時(shí)間戳比較,判斷是是否超時(shí),沒超時(shí) false,若超時(shí)執(zhí)行第 3 步。

計(jì)算新的超時(shí)時(shí)間 t2,使用 getset 命令返回 t3(該值可能其他線程已經(jīng)修改過),如果t1==t3女阀,獲得鎖宅荤,如果 t1!=t3 說明鎖被其他線程獲取了。4.獲取鎖后浸策,處理完業(yè)務(wù)邏輯冯键,再去判斷鎖是否超時(shí),如果沒超時(shí)刪除鎖庸汗,如果已超時(shí)惫确, 不用處理(防止刪除其他線程的鎖)。

zk:

客戶端對(duì)某個(gè)方法加鎖時(shí)蚯舱,在 zk 上的與該方法對(duì)應(yīng)的指定節(jié)點(diǎn)的目錄下改化,生成一個(gè)唯一 的瞬時(shí)有序節(jié)點(diǎn) node1。

客戶端獲取該路徑下所有已經(jīng)創(chuàng)建的子節(jié)點(diǎn)枉昏,如果發(fā)現(xiàn)自己創(chuàng)建的 node1 的序號(hào)是最小 的陈肛,就認(rèn)為這個(gè)客戶端獲得了鎖。

如果發(fā)現(xiàn) node1 不是最小的凶掰,則監(jiān)聽比自己創(chuàng)建節(jié)點(diǎn)序號(hào)小的最大的節(jié)點(diǎn)燥爷,進(jìn)入等待。

獲取鎖后懦窘,處理完邏輯前翎,刪除自己創(chuàng)建的 node1 即可。

區(qū)別:zk 性能差一些畅涂,開銷大港华,實(shí)現(xiàn)簡(jiǎn)單。

32午衰、知道 redis 的持久化嗎?底層如何實(shí)現(xiàn)的?有什么優(yōu)點(diǎn)缺點(diǎn)?

RDB(Redis DataBase:在不同的時(shí)間點(diǎn)將 redis 的數(shù)據(jù)生成的快照同步到磁盤等介質(zhì)上):內(nèi)存 到硬盤的快照立宜,定期更新。缺點(diǎn):耗時(shí)臊岸,耗性能(fork+io 操作)橙数,易丟失數(shù)據(jù)。
AOF(Append Only File:將redis所執(zhí)行過的所有指令都記錄下來帅戒,在下次redis重啟時(shí)灯帮,只 需要執(zhí)行指令就可以了):寫日志。缺點(diǎn):體積大逻住,恢復(fù)速度慢钟哥。

bgsave 做鏡像全量持久化,aof 做增量持久化瞎访。因?yàn)?bgsave 會(huì)消耗比較長的時(shí)間腻贰,不夠?qū)?時(shí),在停機(jī)的時(shí)候會(huì)導(dǎo)致大量的數(shù)據(jù)丟失扒秸,需要 aof 來配合播演,在 redis 實(shí)例重啟時(shí),優(yōu)先使 用 aof 來恢復(fù)內(nèi)存的狀態(tài)鸦采,如果沒有 aof 日志宾巍,就會(huì)使用 rdb 文件來恢復(fù)。Redis 會(huì)定期做aof 重寫渔伯,壓縮 aof 文件日志大小顶霞。Redis4.0 之后有了混合持久化的功能,將 bgsave 的全量 和 aof 的增量做了融合處理锣吼,這樣既保證了恢復(fù)的效率又兼顧了數(shù)據(jù)的安全性选浑。bgsave 的 原理,fork 和 cow, fork 是指 redis 通過創(chuàng)建子進(jìn)程來進(jìn)行 bgsave 操作玄叠,cow 指的是 copy on write古徒,子進(jìn)程創(chuàng)建后,父子進(jìn)程共享數(shù)據(jù)段读恃,父進(jìn)程繼續(xù)提供讀寫服務(wù)隧膘,寫臟的頁面數(shù)據(jù) 會(huì)逐漸和子進(jìn)程分離開來代态。

33、redis 過期策略都有哪些?LRU 算法知道嗎?寫一下 java 代碼實(shí)現(xiàn)?

過期策略:

定時(shí)過期(一 key 一定時(shí)器)疹吃。

惰性過期:只有使用 key 時(shí)才判斷 key 是否已過期蹦疑,過期則清除。

定期過期:前兩者折中萨驶。

LRU:

new LinkedHashMap<K, V>(capacity, DEFAULT_LOAD_FACTORY, true);
//第三個(gè)參數(shù)置為 true歉摧,代表 linkedlist 按訪問順序排序,可作為 LRU 緩存;設(shè)為 false 代表 按插入順序排序腔呜,可作為 FIFO 緩存

LRU 算法實(shí)現(xiàn):

1.通過雙向鏈表來實(shí)現(xiàn)叁温,新數(shù)據(jù)插入到鏈表頭部;

2.每當(dāng)緩存命中(即緩存 數(shù)據(jù)被訪問),則將數(shù)據(jù)移到鏈表頭部;

3.當(dāng)鏈表滿的時(shí)候核畴,將鏈表尾部的數(shù)據(jù)丟棄膝但。

LinkedHashMap:HashMap 和雙向鏈表合二為一即是 LinkedHashMap。HashMap 是無序 的谤草,LinkedHashMap 通過維護(hù)一個(gè)額外的雙向鏈表保證了迭代順序锰镀。該迭代順序可以是插 入順序(默認(rèn)),也可以是訪問順序咖刃。

34泳炉、緩存與數(shù)據(jù)庫不一致怎么辦?
答:假設(shè)采用的主存分離嚎杨,讀寫分離的數(shù)據(jù)庫花鹅,
如果一個(gè)線程 A 先刪除緩存數(shù)據(jù),然后將數(shù)據(jù)寫入到主庫當(dāng)中枫浙,這個(gè)時(shí)候刨肃,主庫和從庫同 步?jīng)]有完成,線程 B 從緩存當(dāng)中讀取數(shù)據(jù)失敗箩帚,從從庫當(dāng)中讀取到舊數(shù)據(jù)真友,然后更新至緩 存,這個(gè)時(shí)候紧帕,緩存當(dāng)中的就是舊的數(shù)據(jù)盔然。
發(fā)生上述不一致的原因在于,主從庫數(shù)據(jù)不一致問題是嗜,加入了緩存之后愈案,主從不一致的時(shí)間被拉長了。
處理思路:在從庫有數(shù)據(jù)更新之后鹅搪,將緩存當(dāng)中的數(shù)據(jù)也同時(shí)進(jìn)行更新站绪,即當(dāng)從庫發(fā)生了
數(shù)據(jù)更新之后,向緩存發(fā)出刪除丽柿,淘汰這段時(shí)間寫入的舊數(shù)據(jù)恢准。

35魂挂、主從數(shù)據(jù)庫不一致如何解決?

場(chǎng)景描述馁筐,對(duì)于主從庫锰蓬,讀寫分離,如果主從庫更新同步有時(shí)差眯漩,就會(huì)導(dǎo)致主從庫數(shù)據(jù)的
不一致,解決方法:

忽略這個(gè)數(shù)據(jù)不一致麻顶,在數(shù)據(jù)一致性要求不高的業(yè)務(wù)下赦抖,未必需要時(shí)時(shí)一致性。

強(qiáng)制讀主庫辅肾,使用一個(gè)高可用的主庫队萤,數(shù)據(jù)庫讀寫都在主庫,添加一個(gè)緩存矫钓,提升數(shù)據(jù)讀取的性能要尔。

選擇性讀主庫,添加一個(gè)緩存新娜,用來記錄必須讀主庫的數(shù)據(jù)赵辕,將哪個(gè)庫,哪個(gè)表概龄,哪個(gè) 主鍵还惠,作為緩存的 key,設(shè)置緩存失效的時(shí)間為主從庫同步的時(shí)間,如果緩存當(dāng)中有這個(gè)數(shù) 據(jù)私杜,直接讀取主庫蚕键,如果緩存當(dāng)中沒有這個(gè)主鍵,就到對(duì)應(yīng)的從庫中讀取衰粹。

36锣光、Redis 常見的性能問題和解決方案

master 最好不要做持久化工作,如 RDB 內(nèi)存快照和 AOF 日志文件铝耻。

如果數(shù)據(jù)比較重要誊爹,某個(gè) slave 開啟 AOF 備份,策略設(shè)置成每秒同步一次瓢捉。

為了主從復(fù)制的速度和連接的穩(wěn)定性替废,master 和 Slave 最好在一個(gè)局域網(wǎng)內(nèi)。

盡量避免在壓力大得主庫上增加從庫5泊柬、主從復(fù)制不要采用網(wǎng)狀結(jié)構(gòu)椎镣,盡量是線性結(jié)構(gòu),Master<--Slave1<----Slave2 ....

37兽赁、為什么要做Redis分區(qū)状答?
答:分區(qū)可以讓Redis管理更大的內(nèi)存冷守,Redis將可以使用所有機(jī)器的內(nèi)存。如果沒有分區(qū)惊科,你最多只能使用一臺(tái)機(jī)器的內(nèi)存拍摇。分區(qū)使Redis的計(jì)算能力通過簡(jiǎn)單地增加計(jì)算機(jī)得到成倍提升,Redis的網(wǎng)絡(luò)帶寬也會(huì)隨著計(jì)算機(jī)和網(wǎng)卡的增加而成倍增長。

38馆截、你知道有哪些Redis分區(qū)實(shí)現(xiàn)方案充活?

答:客戶端分區(qū)就是在客戶端就已經(jīng)決定數(shù)據(jù)會(huì)被存儲(chǔ)到哪個(gè)redis節(jié)點(diǎn)或者從哪個(gè)redis節(jié)點(diǎn)讀取。大多數(shù)客戶端已經(jīng)實(shí)現(xiàn)了客戶端分區(qū)蜡娶。
代理分區(qū)意味著客戶端將請(qǐng)求發(fā)送給代理混卵,然后代理決定去哪個(gè)節(jié)點(diǎn)寫數(shù)據(jù)或者讀數(shù)據(jù)。代理根據(jù)分區(qū)規(guī)則決定請(qǐng)求哪些Redis實(shí)例窖张,然后根據(jù)Redis的響應(yīng)結(jié)果返回給客戶端幕随。redis和memcached的一種代理實(shí)現(xiàn)就是Twemproxy

查詢路由(Query routing) 的意思是客戶端隨機(jī)地請(qǐng)求任意一個(gè)redis實(shí)例,然后由Redis將請(qǐng)求轉(zhuǎn)發(fā)給正確的Redis節(jié)點(diǎn)宿接。Redis Cluster實(shí)現(xiàn)了一種混合形式的查詢路由赘淮,但并不是直接將請(qǐng)求從一個(gè)redis節(jié)點(diǎn)轉(zhuǎn)發(fā)到另一個(gè)redis節(jié)點(diǎn),而是在客戶端的幫助下直接redirected到正確的redis節(jié)點(diǎn)睦霎。

39梢卸、Redis分區(qū)有什么缺點(diǎn)?

涉及多個(gè)key的操作通常不會(huì)被支持副女。例如你不能對(duì)兩個(gè)集合求交集低剔,因?yàn)樗麄兛赡鼙淮鎯?chǔ)到不同的Redis實(shí)例(實(shí)際上這種情況也有辦法,但是不能直接使用交集指令)肮塞。
同時(shí)操作多個(gè)key,則不能使用Redis事務(wù)襟齿。
分區(qū)使用的粒度是key,不能使用一個(gè)非常長的排序key存儲(chǔ)一個(gè)數(shù)據(jù)集(The partitioning granularity is the key, so it is not possible to shard a dataset with a single huge key like a very big sorted set)枕赵。
當(dāng)使用分區(qū)的時(shí)候猜欺,數(shù)據(jù)處理會(huì)非常復(fù)雜,例如為了備份你必須從不同的Redis實(shí)例和主機(jī)同時(shí)收集RDB / AOF文件拷窜。
分區(qū)時(shí)動(dòng)態(tài)擴(kuò)容或縮容可能非常復(fù)雜巫橄。Redis集群在運(yùn)行時(shí)增加或者刪除Redis節(jié)點(diǎn)豪椿,能做到最大程度對(duì)用戶透明地?cái)?shù)據(jù)再平衡蹬敲,但其他一些客戶端分區(qū)或者代理分區(qū)方法則不支持這種特性午磁。然而,有一種預(yù)分片的技術(shù)也可以較好的解決這個(gè)問題懊昨。

40窄潭、Redis持久化數(shù)據(jù)和緩存怎么做擴(kuò)容?

答:如果Redis被當(dāng)做緩存使用酵颁,使用一致性哈希實(shí)現(xiàn)動(dòng)態(tài)擴(kuò)容縮容嫉你。
如果Redis被當(dāng)做一個(gè)持久化存儲(chǔ)使用月帝,必須使用固定的keys-to-nodes映射關(guān)系,節(jié)點(diǎn)的數(shù)量一旦確定不能變化幽污。否則的話(即Redis節(jié)點(diǎn)需要?jiǎng)討B(tài)變化的情況)嚷辅,必須使用可以在運(yùn)行時(shí)進(jìn)行數(shù)據(jù)再平衡的一套系統(tǒng),而當(dāng)前只有Redis集群可以做到這樣距误。

41簸搞、redis的并發(fā)競(jìng)爭(zhēng)問題如何解決?

答:Redis為單進(jìn)程單線程模式,采用隊(duì)列模式將并發(fā)訪問變?yōu)榇性L問准潭。Redis本身沒有鎖的概念趁俊,Redis對(duì)于多個(gè)客戶端連接并不存在競(jìng)爭(zhēng),但是在Jedis客戶端對(duì)Redis進(jìn)行并發(fā)訪問時(shí)會(huì)發(fā)生連接超時(shí)惋鹅、數(shù)據(jù)轉(zhuǎn)換錯(cuò)誤、阻塞殉簸、客戶端關(guān)閉連接等問題闰集,這些問題均是由于客戶端連接混亂造成。

對(duì)此有2種解決方法:

1.客戶端角度般卑,為保證每個(gè)客戶端間正常有序與Redis進(jìn)行通信武鲁,對(duì)連接進(jìn)行池化,同時(shí)對(duì)客戶端讀寫Redis操作采用內(nèi)部鎖synchronized蝠检。
2.服務(wù)器角度沐鼠,利用setnx實(shí)現(xiàn)鎖。
注:對(duì)于第一種叹谁,需要應(yīng)用程序自己處理資源的同步饲梭,可以使用的方法比較通俗,可以使用synchronized也可以使用lock焰檩;第二種需要用到Redis的setnx命令憔涉,但是需要注意一些問題。

42析苫、簡(jiǎn)述redis的哨兵模式

答:哨兵是對(duì)redis進(jìn)行實(shí)時(shí)的監(jiān)控兜叨,主要有兩個(gè)功能。

監(jiān)測(cè)主數(shù)據(jù)庫和從數(shù)據(jù)庫是否正常運(yùn)行衩侥。

當(dāng)主數(shù)據(jù)庫出現(xiàn)故障的時(shí)候国旷,可以自動(dòng)將一個(gè)從數(shù)據(jù)庫轉(zhuǎn)換為主數(shù)據(jù)庫,實(shí)現(xiàn)自動(dòng)切換茫死。

43跪但、redis的哨兵的監(jiān)控機(jī)制是怎樣的?

答:哨兵監(jiān)控也是有集群的峦萎,會(huì)有多個(gè)哨兵進(jìn)行監(jiān)控特漩,當(dāng)判斷發(fā)生故障的哨兵達(dá)到一定數(shù)量的時(shí)候才進(jìn)行修復(fù)吧雹。一個(gè)健壯的部署至少需要三個(gè)哨兵實(shí)例。

1.每個(gè)Sentinel以每秒鐘一次的頻率向它所知的Master涂身,Slave以及其他 Sentinel 實(shí)例發(fā)送一個(gè) PING 命令

2.如果一個(gè)實(shí)例(instance)距離最后一次有效回復(fù) PING 命令的時(shí)間超過 down-after-milliseconds 選項(xiàng)所指定的值雄卷, 則這個(gè)實(shí)例會(huì)被 Sentinel 標(biāo)記為主觀下線。

3.如果一個(gè)Master被標(biāo)記為主觀下線蛤售,則正在監(jiān)視這個(gè)Master的所有 Sentinel 要以每秒一次的頻率確認(rèn)Master的確進(jìn)入了主觀下線狀態(tài)丁鹉。

4.當(dāng)有足夠數(shù)量的 Sentinel(大于等于配置文件指定的值)在指定的時(shí)間范圍內(nèi)確認(rèn)Master的確進(jìn)入了主觀下線狀態(tài), 則Master會(huì)被標(biāo)記為客觀下線

5.在一般情況下悴能, 每個(gè) Sentinel 會(huì)以每 10 秒一次的頻率向它已知的所有Master揣钦,Slave發(fā)送 INFO 命令

6.當(dāng)Master被 Sentinel 標(biāo)記為客觀下線時(shí),Sentinel 向下線的 Master 的所有 Slave 發(fā)送 INFO 命令的頻率會(huì)從 10 秒一次改為每秒一次

7.若沒有足夠數(shù)量的 Sentinel 同意 Master 已經(jīng)下線漠酿, Master 的客觀下線狀態(tài)就會(huì)被移除冯凹。若 Master 重新向 Sentinel 的 PING 命令返回有效回復(fù), Master 的主觀下線狀態(tài)就會(huì)被移除炒嘲。

Redis高頻面試題就整理到這兒宇姚,總感覺遺漏了點(diǎn)什么,又忽然間想不起來夫凸,希望看完的鄉(xiāng)親們?nèi)缬醒a(bǔ)充的浑劳,麻煩留言告訴一聲,讓我補(bǔ)充的更完整一些夭拌。

更多面試題可以關(guān)注我的個(gè)人公眾號(hào)【碼之初】魔熏,真心的希望可以給你的面試之路助上一臂之力,愿你被生活溫柔以待鸽扁,加油蒜绽!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市桶现,隨后出現(xiàn)的幾起案子滓窍,更是在濱河造成了極大的恐慌,老刑警劉巖巩那,帶你破解...
    沈念sama閱讀 217,185評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件吏夯,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡即横,警方通過查閱死者的電腦和手機(jī)噪生,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來东囚,“玉大人跺嗽,你說我怎么就攤上這事。” “怎么了桨嫁?”我有些...
    開封第一講書人閱讀 163,524評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵植兰,是天一觀的道長。 經(jīng)常有香客問我璃吧,道長楣导,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,339評(píng)論 1 293
  • 正文 為了忘掉前任畜挨,我火速辦了婚禮筒繁,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘巴元。我一直安慰自己毡咏,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評(píng)論 6 391
  • 文/花漫 我一把揭開白布逮刨。 她就那樣靜靜地躺著呕缭,像睡著了一般。 火紅的嫁衣襯著肌膚如雪修己。 梳的紋絲不亂的頭發(fā)上恢总,一...
    開封第一講書人閱讀 51,287評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音箩退,去河邊找鬼离熏。 笑死佳谦,一個(gè)胖子當(dāng)著我的面吹牛戴涝,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播钻蔑,決...
    沈念sama閱讀 40,130評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼啥刻,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了咪笑?” 一聲冷哼從身側(cè)響起可帽,我...
    開封第一講書人閱讀 38,985評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎窗怒,沒想到半個(gè)月后映跟,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,420評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡扬虚,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評(píng)論 3 334
  • 正文 我和宋清朗相戀三年努隙,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片辜昵。...
    茶點(diǎn)故事閱讀 39,779評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡荸镊,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情躬存,我是刑警寧澤张惹,帶...
    沈念sama閱讀 35,477評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站岭洲,受9級(jí)特大地震影響宛逗,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜钦椭,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評(píng)論 3 328
  • 文/蒙蒙 一拧额、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧彪腔,春花似錦侥锦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至格嗅,卻和暖如春番挺,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背屯掖。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評(píng)論 1 269
  • 我被黑心中介騙來泰國打工玄柏, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人贴铜。 一個(gè)月前我還...
    沈念sama閱讀 47,876評(píng)論 2 370
  • 正文 我出身青樓粪摘,卻偏偏與公主長得像,于是被迫代替她去往敵國和親绍坝。 傳聞我的和親對(duì)象是個(gè)殘疾皇子徘意,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容