为什么redis取出来是null_[2020] Redis 最新面试题
Redis 的數(shù)據(jù)類型(數(shù)據(jù)結(jié)構(gòu))
緩存雪崩(緩存擊穿)
他們出現(xiàn)的原理都是訪問(wèn)緩存的時(shí)候,key 剛好失效,導(dǎo)致直接訪問(wèn) DB,壓垮后臺(tái)。
解決辦法就是讓 key 的過(guò)期時(shí)間分散開(kāi),不要集中失效
分布式鎖
使用 setnx 命令后為了防止死鎖,需要對(duì) key 施加 expire 命令,防止死鎖,但是存在執(zhí)行 expire 命令前宕機(jī),造成死鎖的發(fā)生。
解決辦法就是使用復(fù)雜的 setnx 命令,他可以把 setnx 和 expire 一起原子執(zhí)行
如何尋找有固定前綴的 key
使用 KEYS pattern 命令,如:KEYS alib*
但是因?yàn)?Redis 是單線程的,執(zhí)行該命令后會(huì)導(dǎo)致 Redis 阻塞住。
解決辦法就是使用 scan 命令,scan 命令可以無(wú)阻塞的提取出指定模式的 key 列表,但是會(huì)有一定的重復(fù)概率,在客戶端做一次去重就可以了,但是整體所花費(fèi)的時(shí)間會(huì)比直接用 keys指令長(zhǎng)
scan 命令的特點(diǎn):
Redis中的Scan命令的使用 - MSSQL123 - 博客園?www.cnblogs.com如何用 Redis 做異步隊(duì)列
使用 list 數(shù)據(jù)結(jié)構(gòu),在一遍加入,另一邊取出,若取出來(lái)的是 null,則消費(fèi)線程應(yīng)該 sleep,或者消費(fèi)線程不使用 lpop 或 rpop 命令,改為 blpop 或者 brpop 命令,若沒(méi)有元素可取,它會(huì)阻塞列表直到等待超時(shí)或發(fā)現(xiàn)可彈出元素為止。
如何生產(chǎn)一次,消費(fèi)多次
使用發(fā)布訂閱模式
但是在消費(fèi)者下線的情況下,生產(chǎn)的消息會(huì)丟失,得使用專業(yè)的消息隊(duì)列如 rabbitmq
Redis 如何實(shí)現(xiàn)延時(shí)隊(duì)列
使用 zset ,用時(shí)間戳作為 score,消息會(huì)按照時(shí)間順序排序
然后使用 zrangebyscore key min max [WITHSCORES] [LIMIT offset count] 來(lái)取出比當(dāng)前時(shí)間小的 key 的 value
持久化
Redis 4.0 時(shí)代以 RDB 為主,AOF 只記錄上一次 RDB 到現(xiàn)在的更改記錄
開(kāi)啟混合持久化:aof-use-rdb-preamble yes
工作原理:其實(shí)還是一種 AOF 機(jī)制,但是新增了 RDB 的特性,先看此模式下的 AOF 的數(shù)據(jù)結(jié)構(gòu)圖
- 看圖就知道混合模式指的就是重寫(xiě) AOF 的時(shí)候,將此刻內(nèi)存里面的數(shù)據(jù)做成 RDB,在此過(guò)程中增量的數(shù)據(jù)寫(xiě)入到緩沖區(qū),最終形成新的 aof 文件。接著刪除舊的 AOF。
- 重啟恢復(fù)時(shí)先恢復(fù) RDB,再重放新增的 AOF 指令
持久化的意義在于故障恢復(fù)
- AOF:記錄每一次的寫(xiě)操作到日志上,重啟時(shí)重放日志以重建數(shù)據(jù)
- 每隔一段時(shí)間調(diào)用系統(tǒng)的 fsync 函數(shù)強(qiáng)制將 os cache 里面的數(shù)據(jù)刷新到磁盤(pán)上
- RDB:每隔一段時(shí)間保存一次當(dāng)前時(shí)間點(diǎn)上的數(shù)據(jù)快照
- 快照就是一次又一次地從頭開(kāi)始創(chuàng)造一切,全量的
持久化如何工作的
關(guān)鍵詞:寫(xiě)時(shí)復(fù)制和 fork 子進(jìn)程
- 每當(dāng) Redis 需要轉(zhuǎn)儲(chǔ)數(shù)據(jù)集到磁盤(pán)時(shí),會(huì)發(fā)生:
- Redis 調(diào)用 fork()。于是我們有了父子兩個(gè)進(jìn)程。
- 子進(jìn)程開(kāi)始將數(shù)據(jù)集寫(xiě)入一個(gè)臨時(shí) RDB / AOF 文件。
- 當(dāng)子進(jìn)程完成了新 RDB 文件,替換掉舊文件。
- AOF 的 fork(),與 RDB 不同的是父進(jìn)程會(huì)在一個(gè)內(nèi)存緩沖區(qū)中積累新的變更,同時(shí)將新的變更寫(xiě)入新的 AOF 文件,所以即使重寫(xiě)失敗我們也安全。當(dāng)子進(jìn)程完成重寫(xiě)文件,父進(jìn)程收到一個(gè)信號(hào),追加內(nèi)存緩沖區(qū)到子進(jìn)程創(chuàng)建的文件末尾,接著自動(dòng)重命名文件為新的,然后開(kāi)始追加新數(shù)據(jù)到新文件
- 這個(gè)方法可以讓 Redis 獲益于寫(xiě)時(shí)復(fù)制(copy-on-write)機(jī)制。
AOF 為什么要重寫(xiě)
AOF 記錄的是 Redis 的每一次變更,這個(gè)變更包含了大量的冗余操作,導(dǎo)致 AOF 體積變大,恢復(fù)緩慢。
通過(guò)重寫(xiě)這個(gè)體積大的 AOF 文件,可以實(shí)現(xiàn)新的 AOF 文件不會(huì)包含任何浪費(fèi)空間的冗余命令,通常體積會(huì)較舊 AOF 文件小很多。
Pipeline
將多個(gè)指令一起發(fā)送,減少 IO,提高吞吐量
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ò)程。后續(xù)的增量數(shù)據(jù)通過(guò) AOF 日志同步即可,有點(diǎn)類似數(shù)據(jù)庫(kù)的 binlog
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ǔ)。
Redis 的通訊協(xié)議是什么
答案是文本協(xié)議
雖然文本協(xié)議耗費(fèi)流量,但是解析性能很好
Redis 的事務(wù)
首先 Redis 支持事務(wù),但是它的事務(wù)與MySQL這類傳統(tǒng)的數(shù)據(jù)庫(kù)的事務(wù)不同,不同點(diǎn)為:
具備隔離性:Redis 因?yàn)槭菃尉€程操作,所以在隔離性上有天生的隔離機(jī)制,當(dāng) Redis 執(zhí)行事務(wù)時(shí),Redis 的服務(wù)端保證在執(zhí)行事務(wù)期間不會(huì)對(duì)事務(wù)進(jìn)行中斷,所以,Redis 事務(wù)總是以串行的方式運(yùn)行,事務(wù)也具備隔離性。
不具備一致性:雖然開(kāi)啟持久化之后可以在數(shù)據(jù)出現(xiàn)問(wèn)題是恢復(fù)到之前的狀態(tài),但是因?yàn)镽edis的事務(wù)不是原子性的,不會(huì)回滾數(shù)據(jù),Redis設(shè)計(jì)時(shí)也沒(méi)有考慮ACID特性,所以認(rèn)為Redis不具備一致性
持久性:開(kāi)啟持久化就支持,不開(kāi)啟就不支持
Redis 的樂(lè)觀鎖 Watch 是怎么實(shí)現(xiàn)的
Watch 會(huì)在事務(wù)開(kāi)始之前盯住 1 個(gè)或多個(gè)關(guān)鍵變量,如下圖:
當(dāng)事務(wù)執(zhí)行時(shí),也就是服務(wù)器收到了 exec 指令要順序執(zhí)行緩存的事務(wù)隊(duì)列時(shí), Redis 會(huì)檢查關(guān)鍵變量自 Watch 之后,是否被修改了。
上圖顯示,watch abc 之后執(zhí)行事務(wù)之前,執(zhí)行了一次 incr 操作,所以在 exec 的時(shí)候失敗,watch 的實(shí)現(xiàn)原理不是 CAS 中的 Cmpxchg 指令,而是借助 Redis 的單線程執(zhí)行機(jī)制,采用了 watched_keys 的數(shù)據(jù)結(jié)構(gòu)和串行流程實(shí)現(xiàn)了樂(lè)觀鎖,具體解釋就是:
每一個(gè)被 watch 的 key 都會(huì)被構(gòu)造成一個(gè) watched_keys 數(shù)據(jù)類型,多個(gè)被 watch 的 key 構(gòu)造成鏈表存儲(chǔ)著假設(shè)客戶端 A 和 B 都 watch abc 但是并發(fā)時(shí) Redis Server 中只會(huì)有一個(gè)線程在執(zhí)行, 當(dāng) A 修改了 watch 命令監(jiān)視的 key 后,會(huì)改變 abc 的 watched_keys 的狀態(tài)為 dirty, 客戶端 B 會(huì)檢查這個(gè)被 watch 的 abc,發(fā)現(xiàn)他的狀態(tài)是 dirty 的時(shí)候就會(huì)終止事務(wù)Redis 如何節(jié)省內(nèi)存
關(guān)鍵詞:ziplist、quicklist、對(duì)象共享
Ziplist 是一個(gè)緊湊的數(shù)據(jù)結(jié)構(gòu),每一個(gè)元素之間都是連續(xù)的內(nèi)存,如果在 Redis 中,Redis 啟用的數(shù)據(jù)結(jié)構(gòu)數(shù)據(jù)量很小時(shí),Redis 就會(huì)切換到使用緊湊存儲(chǔ)的形式來(lái)進(jìn)行壓縮存儲(chǔ)。
Quicklist 是 ziplist 的雙向鏈表版本,可以在兩端執(zhí)行 push 和 pop 操作
對(duì)象共享:指的就是多個(gè)key的value是一樣的話,就把多個(gè)key指向同一個(gè)value即可,如下圖:
A和B都指向值100,則A、B 共用同一個(gè)100對(duì)象
Redis 的過(guò)期策略
Redis 同步策略
最簡(jiǎn)單的架構(gòu)模式就是:一臺(tái) master 和多個(gè) slave
僅 master 開(kāi)啟持久化策略,負(fù)責(zé)寫(xiě)入操作,slave 只負(fù)責(zé)讀取操作
同步的目的就是為了【讀寫(xiě)分離】和【容災(zāi)備份】
同步的過(guò)程:
Redis 為什么是單進(jìn)程單線程的
注意:這里的單線程指的是處理 I/O 事件是單線程的,并發(fā)的請(qǐng)求進(jìn)入 Redis 后會(huì)排隊(duì),只有上一個(gè)處理完了,才會(huì)繼續(xù)處理下一個(gè)。
注意:Redis 可不完全是單進(jìn)程的,開(kāi)啟持久化的時(shí)候,會(huì) fork 子進(jìn)程完成 RDB/AOF 的創(chuàng)建
Redis 的線程模型命令處理過(guò)程我們所謂的多線程操作是為了加快計(jì)算,所以開(kāi)啟多個(gè)線程同步操作,而這會(huì)耗費(fèi)大量的 CPU 資源。
Redis 設(shè)計(jì)之初就是純內(nèi)存運(yùn)行,計(jì)算速度夠快了,若再使用多線程操作的話會(huì)因?yàn)榫€程管理問(wèn)題以及上下文切換耗時(shí),反而會(huì)降低性能。Redis 官方測(cè)試中一臺(tái)普通的筆記本電腦沒(méi)鳥(niǎo)的QPS可達(dá)十幾萬(wàn),所以目前來(lái)看沒(méi)有必要使用多線程。
客戶端獲取 value 阻塞時(shí),卻不會(huì)影響后面的命令的執(zhí)行Redis 為什么這么快
談一下 Redis 的哈希槽
Redis 集群使用數(shù)據(jù)分片(sharding)而非一致性哈希(consistency hashing)來(lái)實(shí)現(xiàn)分區(qū)(因?yàn)橐恢滦怨i_(kāi)銷很大)
數(shù)據(jù)分片就是用到了16384個(gè)槽,槽里面可存多個(gè)key
集群使用公式 CRC16(key) % 16384 來(lái)計(jì)算鍵 key 屬于哪個(gè)槽
也就是說(shuō)整個(gè)集群里面不管有幾臺(tái)機(jī)器,只有 16384 個(gè)槽,集群把槽分配給全部的實(shí)例,每個(gè)實(shí)例管理一部分的槽,如圖:
擴(kuò)容、縮容都要涉及槽的遷移;擴(kuò)容后要給新機(jī)器分配槽、縮容后要分配被釋放的槽給其他節(jié)點(diǎn)。
傳統(tǒng)的一致性哈希
后知后覺(jué):面試必備:什么是一致性Hash算法??zhuanlan.zhihu.com總結(jié)
以上是生活随笔為你收集整理的为什么redis取出来是null_[2020] Redis 最新面试题的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 怎样理解“地方舆论的本质实是自利经济体”
- 下一篇: 丰田霸道有2.0排量的吗?