兩個(gè)通宵熬出來(lái)的互聯(lián)網(wǎng)大廠最新面試題收集整理1000道(四-Redis),歡迎點(diǎn)贊收藏!!!
最近接觸到很多面試相關(guān)的內(nèi)容,所以就專(zhuān)門(mén)整理了以下,內(nèi)容涵蓋:Java、MyBatis、ZooKeeper、Dubbo、Elasticsearch、Memcached、Redis、MySQL、Spring、Spring Boot、Spring Cloud、RabbitMQ、Kafka、Linux 等技術(shù)棧。
后續(xù)會(huì)出專(zhuān)門(mén)的面試視頻專(zhuān)題,歡迎關(guān)注。
Redis 面試題
1、什么是Redis?
Redis 是完全開(kāi)源免費(fèi)的, 遵守 BSD 協(xié)議, 是一個(gè)高性能的 key-value 數(shù)據(jù)庫(kù)。
Redis 與其他 key - value 緩存產(chǎn)品有以下三個(gè)特點(diǎn):
Redis 支持?jǐn)?shù)據(jù)的持久化,可以將內(nèi)存中的數(shù)據(jù)保存在磁盤(pán)中,重啟的時(shí)候可以再次加載進(jìn)行使用。
Redis 不僅僅支持簡(jiǎn)單的 key-value 類(lèi)型的數(shù)據(jù), 同時(shí)還提供 list, set, zset, hash 等數(shù)據(jù)結(jié)構(gòu)的存儲(chǔ)。
Redis 支持?jǐn)?shù)據(jù)的備份, 即 master-slave 模式的數(shù)據(jù)備份。
Redis 優(yōu) 勢(shì)
性能極高: Redis 能讀的速度是 110000 次/s,寫(xiě)的速度是 81000 次/s 。
豐富的數(shù)據(jù)類(lèi)型: Redis 支持二進(jìn)制案例的 Strings, Lists, Hashes, Sets 及Ordered Sets 數(shù)據(jù)類(lèi)型操作。
原子 : Redis 的所有操作都是原子性的,意思就是要么成功執(zhí)行要么失敗完全不執(zhí)行。單個(gè)操作是原子性的。多個(gè)操作也支持事務(wù),即原子性,通過(guò) MULTI 和 EXEC 指令包起來(lái)。
豐富的特性: Redis 還支持 publish/subscribe, 通知, key 過(guò)期等等特性。
Redis 與其他 key-value 存儲(chǔ)有什么不同?
Redis 有著更為復(fù)雜的數(shù)據(jù)結(jié)構(gòu)并且提供對(duì)他們的原子性操作,這是一個(gè)不同于其他數(shù)據(jù)庫(kù)的進(jìn)化路徑。Redis 的數(shù)據(jù)類(lèi)型都是基于基本數(shù)據(jù)結(jié)構(gòu)的同時(shí)對(duì)程序員透明, 無(wú)需進(jìn)行額外的抽象。
Redis 運(yùn)行在內(nèi)存中但是可以持久化到磁盤(pán),所以在對(duì)不同數(shù)據(jù)集進(jìn)行高速讀寫(xiě)時(shí)需要權(quán)衡內(nèi)存, 因?yàn)閿?shù)據(jù)量不能大于硬件內(nèi)存。在內(nèi)存數(shù)據(jù)庫(kù)方面的另一個(gè)優(yōu)點(diǎn)是,相比在磁盤(pán)上相同的復(fù)雜的數(shù)據(jù)結(jié)構(gòu),在內(nèi)存中操作起來(lái)非常簡(jiǎn)單,這樣 Redis 可以做很多內(nèi)部復(fù)雜性很強(qiáng)的事情。同時(shí), 在磁盤(pán)格式方面他們是緊湊的以追加的方式產(chǎn)生的, 因?yàn)樗麄儾⒉恍枰M(jìn)行隨機(jī)訪問(wèn)。
2、Redis 的數(shù)據(jù)類(lèi)型?
Redis 支持五種數(shù)據(jù)類(lèi)型: string( 字符串),hash( 哈希), list( 列表), set( 集合) 及 zsetsorted set: 有序集合)。
我們實(shí)際項(xiàng)目中比較常用的是 string,hash 如果你是 Redis 中高級(jí)用戶(hù),還需要加上下面幾種數(shù)據(jù)結(jié)構(gòu) HyperLogLog、Geo、Pub/Sub。如果你說(shuō)還玩過(guò) Redis Module,像 BloomFilter,RedisSearch,Redis-ML,面試官得眼睛就開(kāi)始發(fā)亮了。
3、使用Redis 有哪些好處?
速度快, 因?yàn)閿?shù)據(jù)存在內(nèi)存中, 類(lèi)似于 HashMap, HashMap 的優(yōu)勢(shì)就是查找和操作的時(shí)間復(fù)雜度都是 O1)
支持豐富數(shù)據(jù)類(lèi)型, 支持 string, list, set, Zset, hash 等
支持事務(wù), 操作都是原子性, 所謂的原子性就是對(duì)數(shù)據(jù)的更改要么全部執(zhí)行, 要么全部不執(zhí)行
豐富的特性:可用于緩存,消息,按 key 設(shè)置過(guò)期時(shí)間,過(guò)期后將會(huì)自動(dòng)刪除
4、Redis 相比Memcached 有哪些優(yōu)勢(shì)?
Memcached 所有的值均是簡(jiǎn)單的字符串, redis 作為其替代者, 支持更為豐富的數(shù)據(jù)類(lèi)
Redis 的速度比 Memcached 快很
Redis 可以持久化其數(shù)據(jù)
5、Memcache 與Redis 的區(qū)別都有哪些?
存儲(chǔ)方式 Memecache 把數(shù)據(jù)全部存在內(nèi)存之中, 斷電后會(huì)掛掉, 數(shù)據(jù)不能超過(guò)內(nèi)存大小。 Redis 有部份存在硬盤(pán)上, 這樣能保證數(shù)據(jù)的持久性。
數(shù)據(jù)支持類(lèi)型 Memcache 對(duì)數(shù)據(jù)類(lèi)型支持相對(duì)簡(jiǎn)單。 Redis 有復(fù)雜的數(shù)據(jù)類(lèi)型。
使用底層模型不同 它們之間底層實(shí)現(xiàn)方式 以及與客戶(hù)端之間通信的應(yīng)用協(xié)議不一樣。Redis 直接自己構(gòu)建了 VM 機(jī)制 ,因?yàn)橐话愕南到y(tǒng)調(diào)用系統(tǒng)函數(shù)的話, 會(huì)浪費(fèi)一定的時(shí)間去移動(dòng)和請(qǐng)求。
6、Redis 是單進(jìn)程單線程的?
Redis 是單進(jìn)程單線程的, redis 利用隊(duì)列技術(shù)將并發(fā)訪問(wèn)變?yōu)榇性L問(wèn), 消除了傳統(tǒng)數(shù)據(jù)庫(kù)串行控制的開(kāi)銷(xiāo)。
7、一個(gè)字符串類(lèi)型的值能存儲(chǔ)最大容量是多少?
512M
8、Redis 的持久化機(jī)制是什么?各自的優(yōu)缺點(diǎn)?
Redis 提供兩種持久化機(jī)制 RDB 和 AOF 機(jī)制:
1 、RDBRedis DataBase) 持久化方式: 是指用數(shù)據(jù)集快照的方式半持久化模式) 記錄 redis 數(shù)據(jù)庫(kù)的所有鍵值對(duì),在某個(gè)時(shí)間點(diǎn)將數(shù)據(jù)寫(xiě)入一個(gè)臨時(shí)文件, 持久化結(jié)束后, 用這個(gè)臨時(shí)文件替換上次持久化的文件, 達(dá)到數(shù)據(jù)恢復(fù)。
優(yōu)點(diǎn):
只有一個(gè)文件 dump.rdb, 方便持久化。
容災(zāi)性好, 一個(gè)文件可以保存到安全的磁盤(pán)。
性能最大化, fork 子進(jìn)程來(lái)完成寫(xiě)操作, 讓主進(jìn)程繼續(xù)處理命令, 所以是 IO 最大化。使用單獨(dú)子進(jìn)程來(lái)進(jìn)行持久化,主進(jìn)程不會(huì)進(jìn)行任何 IO 操作,保證了 redis 的高性能) 4.相對(duì)于數(shù)據(jù)集大時(shí), 比 AOF 的啟動(dòng)效率更高。
缺點(diǎn):
數(shù)據(jù)安全性低。RDB 是間隔一段時(shí)間進(jìn)行持久化,如果持久化之間 redis 發(fā)生故障, 會(huì)發(fā)生數(shù)據(jù)丟失。所以這種方式更適合數(shù)據(jù)要求不嚴(yán)謹(jǐn)?shù)臅r(shí)候)
2、AOFAppend-only file)持久化方式: 是指所有的命令行記錄以 redis 命令請(qǐng)求協(xié)議的格式完全持久化存儲(chǔ))保存為 aof 文件。
優(yōu)點(diǎn):
數(shù)據(jù)安全, aof 持久化可以配置 appendfsync 屬性, 有 always, 每進(jìn)行一次命令操作就記錄到 aof 文件中一次。
通過(guò) append 模式寫(xiě)文件, 即使中途服務(wù)器宕機(jī), 可以通過(guò) redis-check-aof 工具解決數(shù)據(jù)一致性問(wèn)題。
AOF 機(jī)制的 rewrite 模式。AOF 文件沒(méi)被 rewrite 之前( 文件過(guò)大時(shí)會(huì)對(duì)命令進(jìn)行合并重寫(xiě)), 可以刪除其中的某些命令( 比如誤操作的 flushall))
缺點(diǎn):
AOF 文件比 RDB 文件大, 且恢復(fù)速度慢。
數(shù)據(jù)集大的時(shí)候, 比 rdb 啟動(dòng)效率低。
9、Redis 常見(jiàn)性能問(wèn)題和解決方案:
1、Master 最好不要寫(xiě)內(nèi)存快照,如果Master 寫(xiě)內(nèi)存快照,save 命令調(diào)度 rdb Save 函數(shù), 會(huì)阻塞主線程的工作, 當(dāng)快照比較大時(shí)對(duì)性能影響是非常大的, 會(huì)間斷性暫停服務(wù)
2、如果數(shù)據(jù)比較重要, 某個(gè) Slave 開(kāi)啟 AOF 備份數(shù)據(jù), 策略設(shè)置為每秒同步一
3、為了主從復(fù)制的速度和連接的穩(wěn)定性, Master 和 Slave 最好在同一個(gè)局域網(wǎng)
4、盡量避免在壓力很大的主庫(kù)上增加從
5、主從復(fù)制不要用圖狀結(jié)構(gòu), 用單向鏈表結(jié)構(gòu)更為穩(wěn)定, 即:Master <- Slave1<- Slave2 <- Slave3 … 這樣的結(jié)構(gòu)方便解決單點(diǎn)故障問(wèn)題,實(shí)現(xiàn) Slave 對(duì) Master 的替換。如果 Master 掛了, 可以立刻啟用 Slave1 做 Master, 其他不變。
10、redis 過(guò)期鍵的刪除策略?
1、定時(shí)刪除:在設(shè)置鍵的過(guò)期時(shí)間的同時(shí),創(chuàng)建一個(gè)定時(shí)器 timer). 讓定時(shí)器在鍵的過(guò)期時(shí)間來(lái)臨時(shí), 立即執(zhí)行對(duì)鍵的刪除操作。
2、惰性刪除:放任鍵過(guò)期不管,但是每次從鍵空間中獲取鍵時(shí),都檢查取得的鍵是 否過(guò)期, 如果過(guò)期的話, 就刪除該鍵;如果沒(méi)有過(guò)期, 就返回該鍵。
3、定期刪除:每隔一段時(shí)間程序就對(duì)數(shù)據(jù)庫(kù)進(jìn)行一次檢查,刪除里面的過(guò)期鍵。至 于要?jiǎng)h除多少過(guò)期鍵, 以及要檢查多少個(gè)數(shù)據(jù)庫(kù), 則由算法決定。
11、Redis 的回收策略(淘汰策略)?
volatile-lru: 從已設(shè)置過(guò)期時(shí)間的數(shù)據(jù)集( server.db[i].expires)中挑選最近最少使用的數(shù)據(jù)淘汰
volatile-ttl: 從已設(shè)置過(guò)期時(shí)間的數(shù)據(jù)集( server.db[i].expires) 中挑選將要過(guò)期的數(shù)據(jù)淘汰
volatile-random: 從已設(shè)置過(guò)期時(shí)間的數(shù)據(jù)集( server.db[i].expires) 中任意選擇數(shù)據(jù)淘汰
allkeys-lru: 從數(shù)據(jù)集( server.db[i].dict) 中挑選最近最少使用的數(shù)據(jù)淘汰
allkeys-random: 從數(shù)據(jù)集( server.db[i].dict) 中任意選擇數(shù)據(jù)淘汰
no-enviction( 驅(qū)逐) : 禁止驅(qū)逐數(shù)據(jù)
注意這里的 6 種機(jī)制,volatile 和 allkeys 規(guī)定了是對(duì)已設(shè)置過(guò)期時(shí)間的數(shù)據(jù)集淘汰數(shù)據(jù)還是從全部數(shù)據(jù)集淘汰數(shù)據(jù), 后面的 lru、ttl 以及 random 是三種不同的淘汰策略, 再加上一種 no-enviction 永不回收的策略。
使用策略規(guī)則:
1、如果數(shù)據(jù)呈現(xiàn)冪律分布,也就是一部分?jǐn)?shù)據(jù)訪問(wèn)頻率高,一部分?jǐn)?shù)據(jù)訪問(wèn)頻率 低, 則使用 allkeys-lru
2、如果數(shù)據(jù)呈現(xiàn)平等分布, 也就是所有的數(shù)據(jù)訪問(wèn)頻率都相同, 則使用allkeys-random
12、為什么 edis 需要把所有數(shù)據(jù)放到內(nèi)存中?
Redis 為了達(dá)到最快的讀寫(xiě)速度將數(shù)據(jù)都讀到內(nèi)存中,并通過(guò)異步的方式將數(shù)據(jù)寫(xiě)入磁盤(pán)。所以 redis 具有快速和數(shù)據(jù)持久化的特征。如果不將數(shù)據(jù)放在內(nèi)存中, 磁盤(pán) I/O 速度為嚴(yán)重影響 redis 的性能。在內(nèi)存越來(lái)越便宜的今天, redis 將會(huì)越來(lái)越受歡迎。如果設(shè)置了最大使用的內(nèi)存, 則數(shù)據(jù)已有記錄數(shù)達(dá)到內(nèi)存限值后不能繼續(xù)插入新值。
13、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ò)程。
14、Pipeline 有什么好處,為什么要用pipeline?
可以將多次 IO 往返的時(shí)間縮減為一次,前提是 pipeline 執(zhí)行的指令之間沒(méi)有因果相關(guān)性。使用 redis-benchmark 進(jìn)行壓測(cè)的時(shí)候可以發(fā)現(xiàn)影響 redis 的 QPS 峰值的一個(gè)重要因素是 pipeline 批次指令的數(shù)目。
15、是否使用過(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ǔ)。
16、Redis 集群方案什么情況下會(huì)導(dǎo)致整個(gè)集群不可用?
有 A, B, C 三個(gè)節(jié)點(diǎn)的集群,在沒(méi)有復(fù)制模型的情況下,如果節(jié)點(diǎn) B 失敗了, 那么整個(gè)集群就會(huì)以為缺少 5501-11000 這個(gè)范圍的槽而不可用。
17、Redis 支持的Java 客戶(hù)端都有哪些?官方推薦用哪個(gè)?
Redisson、Jedis、lettuce 等等, 官方推薦使用 Redisson。
18、Jedis 與 Redisson 對(duì)比有什么優(yōu)缺點(diǎn)?
Jedis 是 Redis 的 Java 實(shí)現(xiàn)的客戶(hù)端, 其 API 提供了比較全面的 Redis 命令的支持;Redisson 實(shí)現(xiàn)了分布式和可擴(kuò)展的 Java 數(shù)據(jù)結(jié)構(gòu),和 Jedis 相比,功能較為簡(jiǎn)單, 不支持字符串操作, 不支持排序、事務(wù)、管道、分區(qū)等 Redis 特性。Redisson 的宗旨是促進(jìn)使用者對(duì) Redis 的關(guān)注分離,從而讓使用者能夠?qū)⒕Ω械胤旁谔幚順I(yè)務(wù)邏輯上。
19、Redis 如何設(shè)置密碼及驗(yàn)證密碼?
設(shè)置密碼: config set requirepass 123456 授權(quán)密碼: auth 123456
20、說(shuō)說(shuō) Redis 哈希槽的概念?
Redis 集群沒(méi)有使用一致性 hash,而是引入了哈希槽的概念, Redis 集群有16384 個(gè)哈希槽,每個(gè) key 通過(guò) CRC16 校驗(yàn)后對(duì) 16384 取模來(lái)決定放置哪個(gè)槽, 集群的每個(gè)節(jié)點(diǎn)負(fù)責(zé)一部分 hash 槽。
21、Redis 集群的主從復(fù)制模型是怎樣的?
為了使在部分節(jié)點(diǎn)失敗或者大部分節(jié)點(diǎn)無(wú)法通信的情況下集群仍然可用, 所以集群使用了主從復(fù)制模型,每個(gè)節(jié)點(diǎn)都會(huì)有 N-1 個(gè)復(fù)制品.
22、Redis 集群會(huì)有寫(xiě)操作丟失嗎?為什么?
Redis 并不能保證數(shù)據(jù)的強(qiáng)一致性,這意味這在實(shí)際中集群在特定的條件下可能會(huì)丟失寫(xiě)操作。
23、Redis 集群之間是如何復(fù)制的?
異步復(fù)制
24、Redis 集群最大節(jié)點(diǎn)個(gè)數(shù)是多少?
16384 個(gè)。
25、Redis 集群如何選擇數(shù)據(jù)庫(kù)?
Redis 集群目前無(wú)法做數(shù)據(jù)庫(kù)選擇, 默認(rèn)在 0 數(shù)據(jù)庫(kù)。
26、怎么測(cè)試 Redis 的連通性?
使用 ping 命令。
27、怎么理解 Redis 事務(wù)?
事務(wù)是一個(gè)單獨(dú)的隔離操作: 事務(wù)中的所有命令都會(huì)序列化、按順序地執(zhí)行。事務(wù)在執(zhí)行的過(guò)程中, 不會(huì)被其他客戶(hù)端發(fā)送來(lái)的命令請(qǐng)求所打斷。
事務(wù)是一個(gè)原子操作: 事務(wù)中的命令要么全部被執(zhí)行, 要么全部都不執(zhí)行。
28、Redis 事務(wù)相關(guān)的命令有哪幾個(gè)?
MULTI、EXEC、DISCARD、WATCH
29、Redis key 的過(guò)期時(shí)間和永久有效分別怎么設(shè)置?
EXPIRE 和 PERSIST 命令。
30、Redis 如何做內(nèi)存優(yōu)化?
盡可能使用散列表( hashes), 散列表( 是說(shuō)散列表里面存儲(chǔ)的數(shù)少) 使用的內(nèi)存非常小, 所以你應(yīng)該盡可能的將你的數(shù)據(jù)模型抽象到一個(gè)散列表里面。比如你的 web 系統(tǒng)中有一個(gè)用戶(hù)對(duì)象, 不要為這個(gè)用戶(hù)的名稱(chēng), 姓氏, 郵箱, 密碼設(shè)置單獨(dú)的 key,而是應(yīng)該把這個(gè)用戶(hù)的所有信息存儲(chǔ)到一張散列表里面.
31、Redis 回收進(jìn)程如何工作的?
一個(gè)客戶(hù)端運(yùn)行了新的命令, 添加了新的數(shù)據(jù)。Redi 檢查內(nèi)存使用情況, 如果大于 maxmemory 的限制, 則根據(jù)設(shè)定好的策略進(jìn)行回收。一個(gè)新的命令被執(zhí)行, 等等。所以我們不斷地穿越內(nèi)存限制的邊界, 通過(guò)不斷達(dá)到邊界然后不斷地回收回到邊界以下。如果一個(gè)命令的結(jié)果導(dǎo)致大量?jī)?nèi)存被使用( 例如很大的集合的交集保存到一個(gè)新的鍵), 不用多久內(nèi)存限制就會(huì)被這個(gè)內(nèi)存使用量超越。
32、都有哪些辦法可以降低 Redis 的內(nèi)存使用情況呢?
如果你使用的是 32 位的 Redis 實(shí)例,可以好好利用 Hash,list,sorted set,set 等集合類(lèi)型數(shù)據(jù), 因?yàn)橥ǔG闆r下很多小的 Key-Value 可以用更緊湊的方式存放到一起。
33、Redis 的內(nèi)存用完了會(huì)發(fā)生什么?
如果達(dá)到設(shè)置的上限,Redis 的寫(xiě)命令會(huì)返回錯(cuò)誤信息( 但是讀命令還可以正常返回。) 或者你可以將 Redis 當(dāng)緩存來(lái)使用配置淘汰機(jī)制, 當(dāng) Redis 達(dá)到內(nèi)存上限時(shí)會(huì)沖刷掉舊的內(nèi)容。
34、一個(gè) Redis 實(shí)例最多能存放多少的 keys?List、Set、Sorted Set 他們最多能存放多少元素?
理論上 Redis 可以處理多達(dá) 232 的 keys,并且在實(shí)際中進(jìn)行了測(cè)試,每個(gè)實(shí)例至少存放了 2 億 5 千萬(wàn)的 keys。我們正在測(cè)試一些較大的值。任何 list、set、和 sorted set 都可以放 232 個(gè)元素。換句話說(shuō), Redis 的存儲(chǔ)極限是系統(tǒng)中的可用內(nèi)存值。
35、MySQL 里有 2000w 數(shù)據(jù),redis 中只存 20w 的數(shù)據(jù),如何保證redis 中的數(shù)據(jù)都是熱點(diǎn)數(shù)據(jù)?
Redis 內(nèi)存數(shù)據(jù)集大小上升到一定大小的時(shí)候, 就會(huì)施行數(shù)據(jù)淘汰策略。相關(guān)知識(shí): Redis 提供 6 種數(shù)據(jù)淘汰策略:
volatile-lru: 從已設(shè)置過(guò)期時(shí)間的數(shù)據(jù)集( server.db[i].expires)中挑選最近最少使用的數(shù)據(jù)淘汰
volatile-ttl: 從已設(shè)置過(guò)期時(shí)間的數(shù)據(jù)集( server.db[i].expires) 中挑選將要過(guò)期的數(shù)據(jù)淘汰
volatile-random: 從已設(shè)置過(guò)期時(shí)間的數(shù)據(jù)集( server.db[i].expires) 中任意選擇數(shù)據(jù)淘汰
allkeys-lru: 從數(shù)據(jù)集( server.db[i].dict) 中挑選最近最少使用的數(shù)據(jù)淘汰
allkeys-random: 從數(shù)據(jù)集( server.db[i].dict) 中任意選擇數(shù)據(jù)淘汰
no-enviction( 驅(qū)逐) : 禁止驅(qū)逐數(shù)據(jù)
36、Redis 最適合的場(chǎng)景?
1、會(huì)話緩存( Session Cache)
最常用的一種使用 Redis 的情景是會(huì)話緩存( session cache)。用 Redis 緩存會(huì)話比其他存儲(chǔ)( 如Memcached)的優(yōu)勢(shì)在于: Redis 提供持久化。當(dāng)維護(hù)一個(gè)不是嚴(yán)格要求一致性的緩存時(shí), 如果用戶(hù)的購(gòu)物車(chē)信息全部丟失, 大部分人都會(huì)不高興的, 現(xiàn)在, 他們還會(huì)這樣嗎? 幸運(yùn)的是, 隨著 Redis 這些年的改進(jìn), 很容易找到怎么恰當(dāng)?shù)氖褂?Redis 來(lái)緩存會(huì)話的文檔。甚至廣為人知的商業(yè)平臺(tái)Magento 也提供 Redis 的插件。
2、全頁(yè)緩存( FPC)
除基本的會(huì)話 token 之外, Redis 還提供很簡(jiǎn)便的 FPC 平臺(tái)。回到一致性問(wèn)題, 即使重啟了 Redis 實(shí)例, 因?yàn)橛写疟P(pán)的持久化, 用戶(hù)也不會(huì)看到頁(yè)面加載速度的下降,這是一個(gè)極大改進(jìn),類(lèi)似 PHP 本地 FPC。 再次以 Magento 為例,Magento 提供一個(gè)插件來(lái)使用 Redis 作為全頁(yè)緩存后端。 此外, 對(duì) WordPress 的用戶(hù)來(lái)說(shuō), Pantheon 有一個(gè)非常好的插件 wp-redis, 這個(gè)插件能幫助你以最快速度加載你曾瀏覽過(guò)的頁(yè)面。
3、隊(duì)列
Reids 在內(nèi)存存儲(chǔ)引擎領(lǐng)域的一大優(yōu)點(diǎn)是提供 list 和 set 操作, 這使得 Redis 能作為一個(gè)很好的消息隊(duì)列平臺(tái)來(lái)使用。Redis 作為隊(duì)列使用的操作,就類(lèi)似于本地程序語(yǔ)言( 如Python) 對(duì) list 的 push/pop 操 作 。 如 果 你 快 速 的 在 Google 中 搜 索 “ Redis queues”, 你馬上就能找到大量的開(kāi)源項(xiàng)目, 這些項(xiàng)目的目的就是利用 Redis 創(chuàng)建非常好的后端工具, 以滿(mǎn)足各種隊(duì)列需求。例如, Celery 有一個(gè)后臺(tái)就是使用 Redis 作為broker, 你可以從這里去查看。
4, 排行榜/計(jì)數(shù)器
Redis 在內(nèi)存中對(duì)數(shù)字進(jìn)行遞增或遞減的操作實(shí)現(xiàn)的非常好。集合( Set) 和有序集合
( Sorted Set)也使得我們?cè)趫?zhí)行這些操作的時(shí)候變的非常簡(jiǎn)單,Redis 只是正好提供了這兩種數(shù)據(jù)結(jié)構(gòu)。所以, 我們要從排序集合中獲取到排名最靠前的 10 個(gè)用戶(hù)– 我們稱(chēng)之為“ user_scores”, 我們只需要像下面一樣執(zhí)行即可: 當(dāng)然, 這是假定你是根據(jù)你用戶(hù)的分?jǐn)?shù)做遞增的排序。如果你想返回用戶(hù)及用戶(hù)的分?jǐn)?shù), 你需要這樣執(zhí)行: ZRANGE user_scores 0 10 WITHSCORES Agora Games 就是一個(gè)很好的例子, 用 Ruby 實(shí)現(xiàn)的, 它的排行榜就是使用 Redis 來(lái)存儲(chǔ)數(shù)據(jù)的, 你可以在這里看到。
5、發(fā)布/訂閱
最后( 但肯定不是最不重要的)是 Redis 的發(fā)布/訂閱功能。發(fā)布/訂閱的使用場(chǎng)景確實(shí)非常多。我已看見(jiàn)人們?cè)谏缃痪W(wǎng)絡(luò)連接中使用, 還可作為基于發(fā)布/訂閱的腳本觸發(fā)器, 甚至用 Redis 的發(fā)布/訂閱功能來(lái)建立聊天系統(tǒng)!
37、假如 Redis 里面有 1 億個(gè)key,其中有 10w 個(gè)key 是以某個(gè)固定的已知的前綴開(kāi)頭的,如果將它們?nèi)空页鰜?lái)?
使用 keys 指令可以掃出指定模式的 key 列表。
對(duì)方接著追問(wèn): 如果這個(gè) redis 正在給線上的業(yè)務(wù)提供服務(wù), 那使用 keys 指令會(huì)有什么問(wèn)題?
這個(gè)時(shí)候你要回答 redis 關(guān)鍵的一個(gè)特性:redis 的單線程的。keys 指令會(huì)導(dǎo)致線程阻塞一段時(shí)間, 線上服務(wù)會(huì)停頓, 直到指令執(zhí)行完畢, 服務(wù)才能恢復(fù)。這個(gè)時(shí)候可以使用scan 指令, scan 指令可以無(wú)阻塞的提取出指定模式的 key 列表, 但是會(huì)有一定的重復(fù)概率, 在客戶(hù)端做一次去重就可以了, 但是整體所花費(fèi)的時(shí)間會(huì)比直接用 keys 指令長(zhǎng)。
38、如果有大量的 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í)間分散一些。
39、使用過(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)者下線的情況下,生產(chǎn)的消息會(huì)丟失,得使用專(zhuān)業(yè)的消息隊(duì)列如 RabbitMQ 等。
如果對(duì)方追問(wèn) redis 如何實(shí)現(xiàn)延時(shí)隊(duì)列?
我估計(jì)現(xiàn)在你很想把面試官一棒打死如果你手上有一根棒球棍的話, 怎么問(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ì)你豎起了大拇指。但是他不知道的是此刻你卻豎起了中指, 在椅子背后。
40、使用過(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 的相關(guān)面試題我們就介紹到這里哦!歡迎關(guān)注加哦!
Redis 數(shù)據(jù)結(jié)構(gòu)
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶(hù)投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。