Redis常考的知識點都在這了镇辉!


title: Redis陈潘耄考的知識點
categories: 數(shù)據(jù)庫
tags: Redis


一、Redis是什么忽肛,有什么功能村砂?

? Redis 是一個使用 C 語言開發(fā)的數(shù)據(jù)庫,也是一種Key-Value數(shù)據(jù)庫,數(shù)據(jù)存儲在內(nèi)存中屹逛,常用作緩存數(shù)據(jù)庫箍镜,速度較快。

功能:常用來作緩存煎源,分布式鎖色迂,消息隊列,排行榜等功能

二手销、Redis 和 Memcached 的對比
  1. Memcached 只支持String類型歇僧,Reids支持更為豐富的數(shù)據(jù)類型

  2. Redis支持?jǐn)?shù)據(jù)的持久化

  3. Redis的速度更快

  4. Memcached 是多線程,非阻塞IO復(fù)用的網(wǎng)絡(luò)模型锋拖,Redis使用單線程的IO復(fù)用

    相同點就是都是內(nèi)存型數(shù)據(jù)庫诈悍,都有過期策略,性能都不錯兽埃,常用來做緩存

?

三侥钳、Redis支持的數(shù)據(jù)類型以及底層數(shù)據(jù)結(jié)構(gòu)
  1. ? string,底層數(shù)據(jù)結(jié)構(gòu)為簡單動態(tài)字符串(simple dynamic string柄错,SDS)舷夺,SDS 可以保存二進(jìn)制數(shù)據(jù)苦酱,并且獲取字符串長度復(fù)雜度為 O(1)(C 字符串為 O(N)),此外,Redis 的 SDS API 是安全的,不會造成緩沖區(qū)溢出给猾。
  2. list疫萤,底層數(shù)據(jù)結(jié)構(gòu)是鏈表,C 語言并沒有實現(xiàn)鏈表敢伸,所以 Redis 實現(xiàn)了自己的鏈表數(shù)據(jù)結(jié)構(gòu)扯饶。Redis 的 list 的實現(xiàn)為一個 雙向鏈表,即可以支持反向查找和遍歷池颈,更方便操作尾序,不過帶來了部分額外的內(nèi)存開銷,獲取表頭表尾和鏈表長度都是O(1)復(fù)雜度
  3. set躯砰,是一種無序集合蹲诀,集合中的元素沒有先后順序。需要存儲一個列表數(shù)據(jù)弃揽,又不希望出現(xiàn)重復(fù)時,可以選擇set则北,并且 set 提供了判斷某個成員是否在一個 set 集合內(nèi)的重要接口
  4. hash矿微,底層是字典結(jié)構(gòu),字典在Redis中廣泛被使用尚揣,包括數(shù)據(jù)庫和哈希鍵涌矢,每個字典有兩個哈希表,哈希表使用的是鏈地址法解決哈希沖突快骗,擴(kuò)容時采用的是漸進(jìn)式哈希
  5. Zset 娜庇,有點像是 Java 中 HashMap 和 TreeSet 的結(jié)合體,底層使用跳表實現(xiàn)
四方篮、Redis為什么是單線程名秀?

? Redis核心就是我所有數(shù)據(jù)都在內(nèi)存里,單線程操作效率就是最高的藕溅,為什么要多線程呢匕得?多線程會有一個代價,就是上下文切換巾表,對于當(dāng)個CPU綁定一塊內(nèi)存的數(shù)據(jù)汁掠,沒有上下文切換就是效率最高的;相反集币,如果是多次磁盤IO的話考阱,多線程更優(yōu),因為在尋道和選擇的時間鞠苟,線程在阻塞的等待磁盤乞榨,這個時間CPU可以去處理其他線程秽之。

? 總之就是CPU不是redis的瓶頸,reids的瓶頸是機(jī)器內(nèi)存和網(wǎng)絡(luò)帶寬姜凄,而單線程既不會成為瓶頸政溃,又容易實現(xiàn),那肯定單線程态秧。

五董虱、Redis是單線程嗎?

? 將第五題和第四題放在一起就是為了分辨一個大部分人的誤區(qū)申鱼,大家稱Redis是單線程愤诱,但是Redis并不是單線程,比如持久化的時候就會fork子線程捐友,包括網(wǎng)絡(luò)IO也不是單線程淫半,Redis的單線程指的是事件處理模型的單線程

? Redis 基于 Reactor 模式開發(fā)了自己的網(wǎng)絡(luò)事件處理器:這個處理器被稱為文件事件處理器(file event handler)匣砖,通過IO 多路復(fù)用程序 來監(jiān)聽來自客戶端的大量連接(或者說是監(jiān)聽多個 socket)科吭,它會將感興趣的事件及類型(讀、寫)注冊到內(nèi)核中并監(jiān)聽每個事件是否發(fā)生猴鲫。

? 文件事件處理器(file event handler)主要是包含 4 個部分:

  • 多個 socket(客戶端連接)
  • IO 多路復(fù)用程序(支持多個客戶端連接的關(guān)鍵)
  • 文件事件分派器(將 socket 關(guān)聯(lián)到相應(yīng)的事件處理器)
  • 事件處理器(連接應(yīng)答處理器对人、命令請求處理器、命令回復(fù)處理器)
六拂共、什么是緩存雪崩牺弄,什么是緩存穿透?

? 緩存雪崩是指緩存中數(shù)據(jù)大批量到過期時間宜狐,而查詢數(shù)據(jù)量巨大势告,引起數(shù)據(jù)庫壓力過大甚至down機(jī)。

? 解決方案就是:

  1. ? 設(shè)置緩存添加隨機(jī)過期時間抚恒,防止大量緩存同時失效
  2. 采用Reids高可用架構(gòu)比如主從或者Redis Cluster咱台,避免Redis掛掉
  3. 及時利用本地緩存和限流,防止下游數(shù)據(jù)庫崩潰
  4. 開啟持久化俭驮,重啟后快速恢復(fù)數(shù)據(jù)

? 緩存穿透是指緩存和數(shù)據(jù)庫中都沒有的數(shù)據(jù)吵护,而用戶不斷發(fā)起請求,如發(fā)起為id為“-1”的數(shù)據(jù)或id為特別大不存在的數(shù)據(jù)表鳍。這時的用戶很可能是攻擊者馅而,攻擊會導(dǎo)致數(shù)據(jù)庫壓力過大

? 解決方案就是:

  1. 訪問一個不存在的參數(shù)時,將這個結(jié)果進(jìn)行緩存譬圣,下次直接返回null

  2. 使用布隆過濾器進(jìn)行過濾

七瓮恭、Redis的過期鍵的刪除策略
  1. ? 惰性刪除 :只會在取出key的時候才對數(shù)據(jù)進(jìn)行過期檢查。這樣對CPU最友好厘熟,但是可能會造成太多過期 key 沒有被刪除屯蹦。

  2. ? 定期刪除 : 每隔一段時間抽取一批 key 執(zhí)行刪除過期key操作维哈。并且,Redis 底層會通過限制刪除操作執(zhí)行的時長和頻率來減少刪除操作對CPU時間的影響登澜。

八阔挠、Redis的內(nèi)存淘汰機(jī)制

? Redis 提供 6 種數(shù)據(jù)淘汰策略:

  1. volatile-lru(least recently used):從已設(shè)置過期時間的數(shù)據(jù)集(server.db[i].expires)中挑選最近最少使用的數(shù)據(jù)淘汰
  2. volatile-ttl:從已設(shè)置過期時間的數(shù)據(jù)集(server.db[i].expires)中挑選將要過期的數(shù)據(jù)淘汰
  3. volatile-random:從已設(shè)置過期時間的數(shù)據(jù)集(server.db[i].expires)中任意選擇數(shù)據(jù)淘汰
  4. allkeys-lru(least recently used):當(dāng)內(nèi)存不足以容納新寫入數(shù)據(jù)時,在鍵空間中脑蠕,移除最近最少使用的 key(這個是最常用的)
  5. allkeys-random:從數(shù)據(jù)集(server.db[i].dict)中任意選擇數(shù)據(jù)淘汰
  6. no-eviction:禁止驅(qū)逐數(shù)據(jù)购撼,也就是說當(dāng)內(nèi)存不足以容納新寫入數(shù)據(jù)時,新寫入操作會報錯谴仙。這個應(yīng)該沒人使用吧迂求!

4.0 版本后增加以下兩種:

  1. volatile-lfu(least frequently used):從已設(shè)置過期時間的數(shù)據(jù)集(server.db[i].expires)中挑選最不經(jīng)常使用的數(shù)據(jù)淘汰
  2. allkeys-lfu(least frequently used):當(dāng)內(nèi)存不足以容納新寫入數(shù)據(jù)時,在鍵空間中晃跺,移除最不經(jīng)常使用的 key
九揩局、Reids和數(shù)據(jù)庫的雙寫一致性

? a. 先更新數(shù)據(jù)再更新緩存的話是不行的,更新結(jié)束掀虎,更新緩存失敗豈不是gg

? b. 先刪緩存再更新數(shù)據(jù)庫看起來可以凌盯,實際上也有問題:

? i. A刪緩存,B拿舊數(shù)據(jù)烹玉,放到緩存里驰怎,A更新數(shù)據(jù)庫,就出問題了

? ii. 解決方案:延時雙刪(但是第二次刪除還是會出現(xiàn)不一致問題)春霍,(要設(shè)置過期時間,保證最終一致性)

? c. 先更新數(shù)據(jù)庫再刪緩存

? i. 問題:緩存剛好失效叶眉,然后A拿到舊數(shù)據(jù)址儒,然后B更新緩存刪緩存,A把舊數(shù)據(jù)放到數(shù)據(jù)庫衅疙,但是碰上緩存剛好失效的概率比較低

十莲趣、Redis的持久化方式

? 快照(snapshotting)持久化(RDB):Redis 可以通過創(chuàng)建快照來獲得存儲在內(nèi)存里面的數(shù)據(jù)在某個時間點上的副本。Redis 創(chuàng)建快照之后饱溢,可以對快照進(jìn)行備份喧伞,可以將快照復(fù)制到其他服務(wù)器從而創(chuàng)建具有相同數(shù)據(jù)的服務(wù)器副本(Redis 主從結(jié)構(gòu),主要用來提高 Redis 性能)绩郎,還可以將快照留在原地以便重啟服務(wù)器的時候使用潘鲫。快照持久化是 Redis 默認(rèn)采用的持久化方式

? AOF(append-only file)持久化:與快照持久化相比肋杖,AOF 持久化 的實時性更好溉仑,因此已成為主流的持久化方案。默認(rèn)情況下 Redis 沒有開啟 AOF(append only file)方式的持久化状植,可以通過 appendonly 參數(shù)開啟

十一浊竟、Redis的漸進(jìn)式擴(kuò)容

? 每個字典有兩個哈希表怨喘,一個ht[0],一個ht[1],擴(kuò)展或收縮哈希表需要將 ht[0] 里面的所有鍵值對 rehash 到 ht[1] 里面振定。如果哈希表里保存的鍵值對數(shù)量非常大必怜, 那么要一次性將這些鍵值對全部 rehash 到 ht[1] 的話, 龐大的計算量可能會導(dǎo)致服務(wù)器在一段時間內(nèi)停止服務(wù)后频。為了避免此情況梳庆,所以采用漸進(jìn)式哈希。

? 哈希表漸進(jìn)式 rehash 的詳細(xì)步驟:

  1. ht[1] 分配空間徘郭, 讓字典同時持有 ht[0]ht[1] 兩個哈希表靠益。
  2. 在字典中維持一個索引計數(shù)器變量 rehashidx , 并將它的值設(shè)置為 0 残揉, 表示 rehash 工作正式開始胧后。
  3. 在 rehash 進(jìn)行期間, 每次對字典執(zhí)行添加抱环、刪除壳快、查找或者更新操作時, 程序除了執(zhí)行指定的操作以外镇草, 還會順帶將 ht[0] 哈希表在 rehashidx 索引上的所有鍵值對 rehash 到 ht[1] 眶痰, 當(dāng) rehash 工作完成之后, 程序?qū)?rehashidx 屬性的值增一梯啤。
  4. 隨著字典操作的不斷執(zhí)行竖伯, 最終在某個時間點上, ht[0] 的所有鍵值對都會被 rehash 至 ht[1] 因宇, 這時程序?qū)?rehashidx 屬性的值設(shè)為 -1七婴, 表示 rehash 操作已完成。

在漸進(jìn)式 rehash 進(jìn)行期間察滑, 字典的刪除(delete)打厘、查找(find)、更新(update)等操作會在兩個哈希表上進(jìn)行: 比如說贺辰, 要在字典里面查找一個鍵的話户盯, 程序會先在 ht[0] 里面進(jìn)行查找, 如果沒找到的話饲化, 就會繼續(xù)到 ht[1] 里面進(jìn)行查找莽鸭, 諸如此類。

另外吃靠, 在漸進(jìn)式 rehash 執(zhí)行期間蒋川, 新添加到字典的鍵值對一律會被保存到 ht[1] 里面, 而 ht[0] 則不再進(jìn)行任何添加操作

十二撩笆、Redis分布式鎖(后續(xù)會有單獨文章)

? 方法一:SETNX key value

? 將 key 的值設(shè)為 value捺球,當(dāng)且僅當(dāng) key 不存在缸浦。
? 若給定的 key 已經(jīng)存在,則 SETNX 不做任何動作氮兵。
? SETNX 是SET if Not eXists的簡寫

? 方法二(Redlock算法):

? 起 5 個 master 節(jié)點裂逐,分布在不同的機(jī)房盡量保證可用性。為了獲得鎖泣栈,client 會進(jìn)行如下操作:

  1. 得到當(dāng)前的時間卜高,微秒單位
  2. 嘗試順序地在 5 個實例上申請鎖,當(dāng)然需要使用相同的 key 和 random value南片,這里一個 client 需要合理設(shè)置與 master 節(jié)點溝通的 timeout 大小掺涛,避免長時間和一個 fail 了的節(jié)點浪費時間
  3. 當(dāng) client 在大于等于 3 個 master 上成功申請到鎖的時候,且它會計算申請鎖消耗了多少時間疼进,這部分消耗的時間采用獲得鎖的當(dāng)下時間減去第一步獲得的時間戳得到薪缆,如果鎖的持續(xù)時長(lock validity time)比流逝的時間多的話,那么鎖就真正獲取到了伞广。
  4. 如果鎖申請到了拣帽,那么鎖真正的 lock validity time 應(yīng)該是 origin(lock validity time) - 申請鎖期間流逝的時間
  5. 如果 client 申請鎖失敗了,那么它就會在少部分申請成功鎖的 master 節(jié)點上執(zhí)行釋放鎖的操作嚼锄,重置狀態(tài)

后續(xù)將會推送Reids集群的知識减拭,敬請期待!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末区丑,一起剝皮案震驚了整個濱河市拧粪,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌沧侥,老刑警劉巖可霎,帶你破解...
    沈念sama閱讀 218,122評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異正什,居然都是意外死亡啥纸,警方通過查閱死者的電腦和手機(jī)号杏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評論 3 395
  • 文/潘曉璐 我一進(jìn)店門婴氮,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人盾致,你說我怎么就攤上這事主经。” “怎么了庭惜?”我有些...
    開封第一講書人閱讀 164,491評論 0 354
  • 文/不壞的土叔 我叫張陵罩驻,是天一觀的道長。 經(jīng)常有香客問我护赊,道長惠遏,這世上最難降的妖魔是什么砾跃? 我笑而不...
    開封第一講書人閱讀 58,636評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮节吮,結(jié)果婚禮上抽高,老公的妹妹穿的比我還像新娘。我一直安慰自己透绩,他們只是感情好翘骂,可當(dāng)我...
    茶點故事閱讀 67,676評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著帚豪,像睡著了一般碳竟。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上狸臣,一...
    開封第一講書人閱讀 51,541評論 1 305
  • 那天莹桅,我揣著相機(jī)與錄音,去河邊找鬼固棚。 笑死统翩,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的此洲。 我是一名探鬼主播厂汗,決...
    沈念sama閱讀 40,292評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼呜师!你這毒婦竟也來了娶桦?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,211評論 0 276
  • 序言:老撾萬榮一對情侶失蹤汁汗,失蹤者是張志新(化名)和其女友劉穎衷畦,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體知牌,經(jīng)...
    沈念sama閱讀 45,655評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡祈争,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,846評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了角寸。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片菩混。...
    茶點故事閱讀 39,965評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖扁藕,靈堂內(nèi)的尸體忽然破棺而出沮峡,到底是詐尸還是另有隱情,我是刑警寧澤亿柑,帶...
    沈念sama閱讀 35,684評論 5 347
  • 正文 年R本政府宣布邢疙,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏疟游。R本人自食惡果不足惜呼畸,卻給世界環(huán)境...
    茶點故事閱讀 41,295評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望颁虐。 院中可真熱鬧役耕,春花似錦、人聲如沸聪廉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽板熊。三九已至框全,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間干签,已是汗流浹背津辩。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留容劳,地道東北人喘沿。 一個月前我還...
    沈念sama閱讀 48,126評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像竭贩,于是被迫代替她去往敵國和親蚜印。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,914評論 2 355

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