- 概述
- 一恤筛、Redis 概念理解
-
二、Redis 數(shù)據(jù)結(jié)構(gòu)與指令
- 1. Redis 支持的數(shù)據(jù)類型
- 2. Redis 常用的命令有哪些憾赁?
- 3. 一個字符串類型的值能存儲最大容量是多少?
- 4. Redis 各個數(shù)據(jù)類型最大存儲量分別是多少?
- 5. 請介紹一下 Redis 的數(shù)據(jù)類型 SortedSet(zset)以及底層實現(xiàn)機(jī)制散吵?
- 6. Redis 事務(wù)相關(guān)命令有哪些龙考?
- 7. 什么是 Redis 事務(wù)?原理是什么矾睦?
- 8. Redis 事務(wù)的注意點有哪些晦款?
- 9. Redis 為什么不支持回滾?
- 10. 請介紹一下 Redis 的 Pipeline(管道)枚冗,以及使用場景
- 11. 請說明一下 Redis 的批量命令與 Pipeline 有什么不同缓溅?
- 12. 請介紹一下 Redis 的發(fā)布訂閱功能
- 13. Redis 的鏈表數(shù)據(jù)結(jié)構(gòu)的特征有哪些?
- 14. 請介紹一下 Redis 的 String 類型底層實現(xiàn)赁温?
- 15. Redis 的 String 類型使用 SSD 方式實現(xiàn)的好處坛怪?
- 16. 設(shè)置鍵的生存時間和過期時間有哪些命令?
- 三股囊、Redis 高并發(fā)處理策略
-
四、Redis 集群結(jié)構(gòu)以及設(shè)計理念
- 1. Redis 集群架構(gòu)模式有哪幾種赂鲤?
- 2. Redis 集群最大節(jié)點個數(shù)是多少噪径?
- 3. Redis 集群的主從復(fù)制模型是怎樣的?
- 4. 請介紹一下 Redis 集群實現(xiàn)方案
- 5. Redis 集群會有寫操作丟失嗎蛤袒?為什么熄云?
- 6. Redis 慢查詢是什么?通過什么配置妙真?
- 7. Redis 的慢查詢修復(fù)經(jīng)驗有哪些缴允?怎么修復(fù)的?
- 8. 如何優(yōu)化 Redis 服務(wù)的性能?
- 9. Redis 的主從復(fù)制模式有什么優(yōu)缺點?
- 10. Redis sentinel(哨兵)模式優(yōu)缺點有哪些练般?
- 11. 如何設(shè)置 Redis 的最大連接數(shù)矗漾?查看 Redis 的最大連接數(shù)?查看 Redis 的當(dāng)前連接數(shù)薄料?
- 12. 介紹一些 Redis 常用的安全設(shè)置敞贡?
-
五、Redis 緩存管理與持久化機(jī)制
- 1. Redis 持久化機(jī)制有哪些摄职?
- 2. Redis 持久化機(jī)制 AOF 和 RDB 有哪些不同之處誊役?
- 3. 請介紹一下 RDB 持久化機(jī)制的優(yōu)缺點
- 4. 請介紹一下 AOF 持久化機(jī)制的優(yōu)缺點
- 5. 如果 AOF 文件的數(shù)據(jù)出現(xiàn)異常, Redis 服務(wù)怎么處理谷市?
- 6. 常見的淘汰算法有哪些蛔垢?
- 7. Redis 淘汰策略有哪些?
- 8. Redis 緩存失效策略有哪些迫悠?
- 9. Redis 如何做內(nèi)存優(yōu)化鹏漆?
- 10. 什么是 bigkey? 有什么影響创泄?
- 11. 怎么發(fā)現(xiàn) bigkey?
- 12. Redis 的內(nèi)存消耗分類有哪些艺玲?內(nèi)存統(tǒng)計使用什么命令?
- 13. 簡單介紹一下 Redis 的內(nèi)存管理方式有哪些鞠抑?
- 14. 如何設(shè)置 Redis 的內(nèi)存上限饭聚?有什么作用?
- 15. Redis 報內(nèi)存不足怎么處理碍拆?
-
六若治、Redis 應(yīng)用場景設(shè)計
- 1. Redis 適用場景有哪些?
- 2. Redis 常用的業(yè)務(wù)場景有哪些感混?
- 3. Redis 支持的 Java 客戶端有哪些? 簡單說明一下特點礼烈。
- 4. 請簡單描述一下 Jedis 的基本使用方法弧满?
- 5. Jedis 連接池鏈接方法有什么優(yōu)點?
- 6. 什么是分布式鎖此熬?有什么作用庭呜?
- 7. 分布式鎖可以通過什么來實現(xiàn)?
- 8. 介紹一下分布式鎖實現(xiàn)需要注意的事項犀忱?
- 9. Redis 怎么實現(xiàn)分布式鎖募谎?
- 10. 緩存命中率表示什么?
- 11. 怎么提高緩存命中率阴汇?
- 12. 請介紹一下 Spring 注解緩存
- 13. 設(shè)計一下在交易網(wǎng)站首頁展示當(dāng)天最熱門售賣商品的前五十名商品列表?
- 總結(jié)
概述
隨著應(yīng)用研發(fā)技術(shù)的不斷成熟数冬,Redis 緩存技術(shù)已經(jīng)成為后臺研發(fā)同學(xué)必備的能力之一。在很多公司面試的過程中搀庶,都必不可少地考察 Redis 知識點的掌握拐纱。
在這里我將所掌握的 Redis 的面試題目進(jìn)行詳細(xì)的梳理铜异,結(jié)合平時工作遇到的問題以及面試題庫收集的內(nèi)容給大家進(jìn)行分享。
本文將 Redis 知識方向分為六大塊進(jìn)行梳理:
- Redis 概念理解
- Redis 數(shù)據(jù)結(jié)構(gòu)與指令
- Redis 高并發(fā)處理策略
- Redis 集群結(jié)構(gòu)以及設(shè)計理念
- Redis 緩存管理與持久化機(jī)制
- Redis 應(yīng)用場景設(shè)計
通過本文的學(xué)習(xí)秸架,相信對大家未來的面試以及知識點的掌握都會有所助益揍庄。
一、Redis 概念理解
1. 什么是 Redis?
Redis 全稱為:Remote Dictionary Server(遠(yuǎn)程數(shù)據(jù)服務(wù))东抹,是一個基于內(nèi)存且支持持久化的高性能 key-value 數(shù)據(jù)庫蚂子。
具備一下幾個基本特征:
- 多數(shù)據(jù)類型
- 持久化機(jī)制
- 主從同步
2. Redis 的特點有哪些?
- Redis 本質(zhì)上是一個 key-value 類型的數(shù)據(jù)庫
- 整個數(shù)據(jù)庫都是在內(nèi)存中進(jìn)行操作缭黔,可定期刷新到磁盤進(jìn)行持久化存儲
- 由于是在內(nèi)存操作食茎,讀寫能力非常好,每秒可以處理 10 萬次讀寫操作
- Redis 支持多種數(shù)據(jù)結(jié)構(gòu)试浙,提供了豐富的數(shù)據(jù)類型選擇
- Redis 同時支持?jǐn)?shù)據(jù)備份董瞻,主從配置
- Redis 的所有操作都是原子性的
3. Memcache 與 Redis 的區(qū)別都有哪些?
- 存儲方式不同:Memcache 把數(shù)據(jù)全部存在內(nèi)存之中,斷電后會丟失田巴。Redis 所有數(shù)據(jù)加載在內(nèi)存钠糊,但也會持久化到磁盤,保證數(shù)據(jù)的持久性壹哺。
- 支持?jǐn)?shù)據(jù)類型不同:Memcache 對數(shù)據(jù)類型支持相對簡單抄伍,只支持 key-value 結(jié)構(gòu)。Redis 有復(fù)雜的數(shù)據(jù)類型管宵。
- 底層模型不同:底層實現(xiàn)方式以及客戶端通信應(yīng)用協(xié)議不一樣截珍。 Redis 直接自己構(gòu)建了 VM 機(jī)制。
- 運行環(huán)境不同:Redis 目前官方只支持 Linux 上運行箩朴。
4. Redis 相比 Memcached 有哪些優(yōu)勢岗喉?
- Memcached 所有的值均是簡單的字符串,Redis 作為其替代者炸庞,支持更為豐富的數(shù)據(jù)類型
- Redis 的速度比 Memcached 快很多
- Redis 可以持久化其數(shù)據(jù)
5. 如何實現(xiàn)本地緩存钱床?請描述一下你知道的方式
- 程序中定義內(nèi)存數(shù)據(jù)結(jié)構(gòu)來實現(xiàn), 比如說定義一個成員變量Map 或者 List 均可以實現(xiàn)
- 使用開源的緩存框架 Ehcache埠居,Ehcache 封裝了對于內(nèi)存操作的功能
- Guava Cache 是 Google 開源的工具集查牌, 提供了緩存的邊界操作工具
6. Redis 通訊協(xié)議是什么?有什么特點滥壕?
Redis 的通信協(xié)議是 Redis Serialization Protocol纸颜,簡稱 RESP。
有如下特性:
- 是二進(jìn)制安全的
- 在 TCP 層
- 基于請求—響應(yīng)的模式
二绎橘、Redis 數(shù)據(jù)結(jié)構(gòu)與指令
1. Redis 支持的數(shù)據(jù)類型
- String(字符串)
- list(列表):list 是字符串列表胁孙,按照插入順序排序。元素可以在列表的頭部(左邊)或者尾部(右邊)進(jìn)行添加。
- hash(哈希):Redis hash 是一個鍵值對(key-value)集合浊洞。Redis hash 是一個 String 類型的 field 和 value 的映射表牵敷,hash 特別適合用于存儲對象。
- set(集合):Redis 的 set 是 String 類型的無序集合法希。
- zset(sorted set:有序集合):Redis zset 和 set 一樣也是 String 類型元素的集合枷餐,且不允許重復(fù)的成員。不同的 zset 是每個元素都會關(guān)聯(lián)一個 double 類型的分?jǐn)?shù)苫亦。zset 通過這個分?jǐn)?shù)來為集合中所有元素進(jìn)行從小到大的排序毛肋。zset 的成員是唯一的,但分?jǐn)?shù)(score)卻可以重復(fù)屋剑。
2. Redis 常用的命令有哪些润匙?
3. 一個字符串類型的值能存儲最大容量是多少?
512M
4. Redis 各個數(shù)據(jù)類型最大存儲量分別是多少?
- Strings 類型:一個 String 類型的 value 最大可以存儲 512M
- Lists 類型:list 的元素個數(shù)最多為 2^32-1 個唉匾,也就是 4294967295 個孕讳。
- Sets 類型:元素個數(shù)最多為 2^32-1 個,也就是 4294967295 個巍膘。
- Hashes 類型:鍵值對個數(shù)最多為 2^32-1 個厂财,也就是 4294967295 個。
- Sorted sets 類型:跟 Sets 類型相似峡懈。
5. 請介紹一下 Redis 的數(shù)據(jù)類型 SortedSet(zset)以及底層實現(xiàn)機(jī)制璃饱?
zset 有順序,不能重復(fù)肪康。在業(yè)務(wù)場景下荚恶,適合做排行榜之類的事情。
底層實現(xiàn)機(jī)制:
SortedSet 的實現(xiàn)方式可能有兩種:ziplist 或者 skiplist磷支。
當(dāng)有序集合對象同時滿足以下兩個條件時谒撼,對象使用 ziplist 編碼:
保存的元素數(shù)量小于 128;
保存的所有元素長度都小于 64 字節(jié)雾狈。 不能滿足上面兩個條件的使用 skiplist 編碼嗤栓。
ziplist 編碼的有序集合對象使用壓縮列表作為底層實現(xiàn),每個集合元素使用兩個緊挨在一起的壓縮列表節(jié)點來保存箍邮,第一個節(jié)點保存元素的成員,第二個節(jié)點保存元素的分值叨叙。并且壓縮列表內(nèi)的集合元素按分值從小到大的順序進(jìn)行排列锭弊,小的放置在靠近表頭的位置,大的放置在靠近表尾的位置擂错。
skiplist 編碼的有序集合對象使用 zset 結(jié)構(gòu)作為底層實現(xiàn)味滞,一個 zset 結(jié)構(gòu)同時包含一個字典和一個跳躍表。字典的鍵保存元素的值,字典的值則保存元素的分值剑鞍;跳躍表節(jié)點的 object 屬性保存元素的成員昨凡,跳躍表節(jié)點的 score 屬性保存元素的分值。
6. Redis 事務(wù)相關(guān)命令有哪些蚁署?
- discard 命令:取消事務(wù)便脊,丟棄事務(wù)中所有命令。
- exec 命令:執(zhí)行所有事務(wù)內(nèi)的命令光戈。
- multi 命令:標(biāo)記一個事務(wù)開始哪痰。
- unwatch 命令:取消 watch 命令對所有 key 的監(jiān)視。
- watch 命令:監(jiān)視一個(或多個)key久妆,如果在執(zhí)行事務(wù)之前這個(這些)key 被其他命令所改動晌杰,事務(wù)將被打斷。
7. 什么是 Redis 事務(wù)筷弦?原理是什么肋演?
Redis 中的事務(wù)是一組命令的集合,是 Redis 的最小執(zhí)行單位烂琴,一個事務(wù)要么都執(zhí)行爹殊,要么都不執(zhí)行。
Reids 事務(wù)保證一個事務(wù)內(nèi)的命令依次執(zhí)行监右,而不會被其他命令插入边灭。
Redis 事務(wù)的原理是先將屬于一個事務(wù)的命令發(fā)送給 Redis,然后依次執(zhí)行這些命令健盒。
8. Redis 事務(wù)的注意點有哪些绒瘦?
- 不支持回滾,如果事務(wù)中有錯誤的操作扣癣,無法回滾到處理前的狀態(tài)惰帽,需要開發(fā)者處理。
- 在執(zhí)行完當(dāng)前事務(wù)內(nèi)所有指令前父虑,不會同時執(zhí)行其他客戶端的請求该酗。
9. Redis 為什么不支持回滾?
Redis 事務(wù)不支持回滾士嚎,如果遇到問題呜魄,會繼續(xù)執(zhí)行余下的命令。 這一點和關(guān)系型數(shù)據(jù)庫不太一致莱衩。這樣處理的原因有:
- 只有語法錯誤爵嗅,Redis才會執(zhí)行失敗,例如錯誤類型的賦值笨蚁, 這就是說從程序?qū)用嫱耆梢圆东@以及解決這些問題
- 支持回滾需要增加很多工作睹晒,不支持的情況下趟庄,Redis 可以保持簡單、速度快的特性
10. 請介紹一下 Redis 的 Pipeline(管道)伪很,以及使用場景
Redis 客戶端與服務(wù)端通信模型使用的 TCP 協(xié)議進(jìn)行連接戚啥, 那么在單個指令的執(zhí)行過程中,都會存在“交互往返”的時間锉试。
Redis 提供了批量操作命令猫十,例如 mget、mset 等键痛,能夠一定程度上節(jié)省這類時間炫彩,但大部分命令還是不支持批量操作。
因此 Pipeline 功能絮短,能夠改善這一類問題江兢。 Pipeline 將一組 Redis 命令進(jìn)行組裝,一次性傳輸給 Redis丁频,再將這些命令執(zhí)行結(jié)果杉允,按照順序返回給客戶端。
適用場景:有批量的數(shù)據(jù)寫入 Redis席里,并且這些數(shù)據(jù)允許一定比例的寫入失敗叔磷,那么這種場景就可以適用 Pipeline。失敗的數(shù)據(jù)后期進(jìn)行補(bǔ)償即可奖磁。
11. 請說明一下 Redis 的批量命令與 Pipeline 有什么不同改基?
- 批量命令保證原子性的,Pipeline 非原子性
- 批量命令是一個命令對應(yīng)多個 key咖为,Pipeline 支持多個命令
- 批量命令是 Redis 服務(wù)端實現(xiàn)秕狰,而 Pipeline 是需要服務(wù)端和客戶端共同實現(xiàn)
12. 請介紹一下 Redis 的發(fā)布訂閱功能
Redis 提供了基于“發(fā)布/訂閱”模式的消息機(jī)制,消息發(fā)布者和訂閱者不能直接通信躁染,客戶端發(fā)布消息的時候指定發(fā)送的頻道鸣哀,然后訂閱了該頻道的用戶可以接收到該消息。具體指令如下:
- 發(fā)布消息:publish channel message
- 訂閱消息:subscribe channel [……]
- 退訂消息:punsubscribe
13. Redis 的鏈表數(shù)據(jù)結(jié)構(gòu)的特征有哪些吞彤?
- 雙端引用:鏈表的最前和最后節(jié)點都有引用我衬,獲取前后節(jié)點的復(fù)雜度為 o(1)
- 無環(huán)鏈表:對于鏈表的訪問都是以 null 結(jié)束
- 長度計數(shù)器:通過 len 屬性來記錄鏈表長度
14. 請介紹一下 Redis 的 String 類型底層實現(xiàn)?
Redis 底層實現(xiàn)了簡單動態(tài)字符串的類型(SSD)饰恕,來表示 String 類型挠羔。 沒有直接使用 C 語言定義的字符串類型。
struct sdshdr{
//記錄 buf 數(shù)組中已使用字節(jié)的數(shù)量
//等于 SDS 保存字符串的長度
int len;
//記錄 buf 數(shù)組中未使用字節(jié)的數(shù)量
int free;
//字節(jié)數(shù)組埋嵌,用于保存字符串
char buf[];
}
15. Redis 的 String 類型使用 SSD 方式實現(xiàn)的好處褥赊?
- 避免緩沖區(qū)溢出:進(jìn)行字符修改時候,可以根據(jù) len 屬性來檢查空間是否滿足要求
- 減少內(nèi)存分配次數(shù):len 和 free 兩個屬性莉恼,可以協(xié)助進(jìn)行空間預(yù)分配以及惰性空間釋放
- 二進(jìn)制安全:SSD 不是以空字符串來判斷是否結(jié)束拌喉,而是以 len 屬性來判斷字符串是否結(jié)束
- 常數(shù)級別獲取字符串長度:獲取字符串的長度只需要讀取 len 屬性就可以獲取
- 兼容 C 字符串函數(shù):可以重用 C 語言庫的 <string.h style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; text-size-adjust: none; -webkit-font-smoothing: antialiased; outline: 0px !important;">的一部分函數(shù)</string.h>
16. 設(shè)置鍵的生存時間和過期時間有哪些命令?
- EXPIRE 以秒為單位俐银,設(shè)置鍵的生存時間
- PEXPIRE 以毫秒為單位尿背,設(shè)置鍵的生存時間
- EXPIREAT 以秒為單位,設(shè)置鍵的過期 UNIX 時間戳
- PEXPIREAT 以毫秒為單位捶惜,設(shè)置鍵的過期 UNIX 時間戳
三田藐、Redis 高并發(fā)處理策略
1. 為什么 Redis 需要把所有數(shù)據(jù)放到內(nèi)存中?
追求更快的讀寫速度吱七,并異步方式持久化存儲到磁盤汽久。 如果不將數(shù)據(jù)放到內(nèi)存中,磁盤的 I/O 速度會嚴(yán)重影響 Redis 的性能踊餐。
2. Redis 是單線程的嗎景醇?
是。
這里的單線程指的是 Redis 網(wǎng)絡(luò)請求模塊使用了一個線程(所以不需考慮并發(fā)安全性)吝岭,即一個線程處理所有網(wǎng)絡(luò)請求三痰,其他模塊仍用了多個線程。
3. Redis 為什么設(shè)計成單線程的窜管?
- 絕大部分請求是純粹的內(nèi)存操作(非成⒔伲快速)
- 采用單線程,避免了不必要的上下文切換和競爭條件
- 非阻塞 IO幕帆,內(nèi)部采用 epoll获搏,epoll 中的讀、寫失乾、關(guān)閉常熙、連接都轉(zhuǎn)化成了事件,然后利用 epoll 的多路復(fù)用特性仗扬,避免 IO 代價症概。
4. 什么是緩存穿透?怎么解決早芭?
緩存穿透是指緩存中查詢一個不存在的數(shù)據(jù)彼城,需要去數(shù)據(jù)庫中獲取。
如果數(shù)據(jù)庫也查不到結(jié)果退个,將不會同步到緩存募壕,導(dǎo)致這個不存在數(shù)據(jù)每次請求都要到數(shù)據(jù)庫查詢,失去了緩存的意義语盈。
解決方法有兩個:
1. 布隆過濾(Bloom filter)
將所有查詢的參數(shù)都存儲到一個 bitmap 中舱馅,在查詢緩存之前,先再找個 bitmap 里面進(jìn)行驗證刀荒。
如果 bitmap 中存在代嗤,則進(jìn)行底層緩存的數(shù)據(jù)查詢棘钞; 如果 bitmap 中不存在查詢參數(shù),則進(jìn)行攔截干毅,不再進(jìn)行緩存的數(shù)據(jù)查詢宜猜。
適用范圍:可以用來實現(xiàn)數(shù)據(jù)字典,進(jìn)行數(shù)據(jù)的判重硝逢,或者集合求交集
2. 緩存空對象
如果查詢返回的數(shù)據(jù)為空姨拥,仍然把這個空結(jié)果進(jìn)行緩存。那么再次用相同 key 獲取數(shù)據(jù)的時候渠鸽,即使不存在的數(shù)據(jù)叫乌,緩存也可以直接返回空值,避免重復(fù)訪問 DB徽缚。
緩存空對象有兩個不足之處:
- 緩存層將存儲更多的鍵值對憨奸,如果是惡意的隨機(jī)訪問,將造成很多內(nèi)存空間的浪費猎拨。這個不足之處可以通過將這類數(shù)據(jù)設(shè)置很短的過期時間來控制膀藐。
- DB 與緩存數(shù)據(jù)不一致。這種可以考慮通過異步消息來進(jìn)行數(shù)據(jù)更新的通知红省,在一定程度上減少這類不一致的時間额各。
5. 什么是緩存雪崩? 怎么解決吧恃?
在集中的一段時間內(nèi)虾啦,有大量的緩存失效,導(dǎo)致大量的訪問沒有命中緩存痕寓,從而將所有查詢進(jìn)行數(shù)據(jù)庫訪問傲醉,導(dǎo)致數(shù)據(jù)庫的壓力增大,從而造成了緩存雪崩呻率。
比如硬毕,如果要做一個促銷活動,我們將商品信息都刷新到緩存礼仗, 過期時間統(tǒng)一為 30 分鐘吐咳。那么在 30 分鐘之后,這批商品將全部過期元践。這時候這批商品的訪問查詢韭脊,都落到了數(shù)據(jù)庫,對于數(shù)據(jù)庫而言单旁,這一刻的壓力會非常大沪羔。從而造成系統(tǒng)整體性風(fēng)險。
解決方案:
方法 1:分散失效時間
分析緩存數(shù)據(jù)的特點象浑,盡量將熱點緩存的失效時間均勻分布蔫饰。 比如說將相同類型的緩存的失效時間設(shè)置成一個在一定區(qū)間內(nèi)的隨機(jī)值琅豆。從而有效的分散失效時間。
方法 2:DB 訪問限制
對數(shù)據(jù)的訪問進(jìn)行限流性質(zhì)的操作死嗦。比如說對數(shù)據(jù)庫訪問進(jìn)行加鎖的處理或者限流相關(guān)的處理趋距。
方法 3:多級緩存設(shè)計
一級緩存為基礎(chǔ)緩存,緩存失效時間設(shè)置一個較長時間越除, 二級緩存為應(yīng)用緩存,失效時間正常設(shè)置外盯,一般會比較短摘盆。 當(dāng)二級緩存失效的時候,再從一級緩存里面獲取饱苟。
6. 緩存的更新策略有幾種孩擂?分別有什么注意事項?
緩存的更新策略包含:
- 先更新數(shù)據(jù)庫箱熬,再更新緩存
- 先刪除緩存类垦,再更新數(shù)據(jù)庫
- 先更新數(shù)據(jù)庫,再刪除緩存
策略一:先更新數(shù)據(jù)庫城须,再更新緩存
1. 這種策略會導(dǎo)致線程安全問題
例如:線程 1 更新了數(shù)據(jù)庫蚤认,線程 2 也更新數(shù)據(jù)庫, 這時候由于某種原因糕伐,線程 2 首先更新了緩存砰琢,線程 1 后續(xù)更新。 這樣就導(dǎo)致了臟數(shù)據(jù)的問題良瞧。 因為目前數(shù)據(jù)庫中存儲的線程 2 更新后的數(shù)據(jù)陪汽,而緩存存儲的是線程1更新的老數(shù)據(jù)。
2. 更新緩存的復(fù)雜度相對較高
數(shù)據(jù)寫入數(shù)據(jù)庫之后褥蚯,一般存入緩存的數(shù)據(jù)都要經(jīng)過一系列的加工計算挚冤,然后寫入緩存。 這時候更新緩存相比較于直接刪除緩存要比較復(fù)雜赞庶。
策略二:先刪除緩存训挡,再更新數(shù)據(jù)庫
這種策略可能導(dǎo)致數(shù)據(jù)不一致的問題。線程 1 寫數(shù)據(jù)刪除緩存尘执;這時候有線程 2 查詢該緩存舍哄,發(fā)現(xiàn)不存在,則去訪問數(shù)據(jù)庫誊锭,得到舊值放入緩存表悬;線程 1 更新數(shù)據(jù)庫。這時候就出現(xiàn)了數(shù)據(jù)不一致的問題丧靡。 如果緩存沒有過期時間蟆沫,這個臟數(shù)據(jù)一直存在籽暇。
解決方案:在寫數(shù)據(jù)庫成功之后, 再次淘汰緩存一次饭庞。
策略三:先更新數(shù)據(jù)庫戒悠,再刪除緩存
可能會造成比較短暫的數(shù)據(jù)不一致。在更新完成數(shù)據(jù)庫舟山, 還沒有刪除緩存的時刻绸狐,如果有緩存數(shù)據(jù)訪問, 就會造成數(shù)據(jù)不一致的情形累盗。 但這種如果數(shù)據(jù)同步機(jī)制比較科學(xué)寒矿,一般都會比較快, 不一致的影響比較小若债。
7. 請介紹幾個可能導(dǎo)致 Redis 阻塞的原因
內(nèi)部原因:
- Redis 的 API 或者指令數(shù)據(jù)結(jié)構(gòu)使用不合理
- Redis 主機(jī) CPU 負(fù)載過高符相,導(dǎo)致系統(tǒng)崩潰
- 持久化工作資源占用過多
外部原因:
- CPU 競爭
- 內(nèi)存交換
- 網(wǎng)絡(luò)問題
8. 怎么去發(fā)現(xiàn) Redis 阻塞異常情況?
1. 通過應(yīng)用服務(wù)監(jiān)控發(fā)現(xiàn)
當(dāng) Redis 阻塞的時候蠢琳,線上應(yīng)用服務(wù)應(yīng)該會感知發(fā)現(xiàn)啊终。比如說發(fā)現(xiàn) Redis 鏈接超時等。這種就需要應(yīng)用服務(wù)增加對于異常的統(tǒng)計傲须,并針對 Redis 相關(guān)的異常蓝牲,進(jìn)行報警。
2. 通過 Redis 自身監(jiān)控系統(tǒng)
借助 Redis 監(jiān)控系統(tǒng)發(fā)現(xiàn)阻塞問題躏碳,當(dāng)監(jiān)控系統(tǒng)發(fā)現(xiàn)各個監(jiān)控指標(biāo)存在異常的時候搞旭,發(fā)送報警。 指標(biāo)有:CPU/內(nèi)存/磁盤等菇绵, 慢查詢肄渗,命令耗時增加等。
四咬最、Redis 集群結(jié)構(gòu)以及設(shè)計理念
1. Redis 集群架構(gòu)模式有哪幾種翎嫡?
- Redis 單節(jié)點單機(jī)器部署
- Redis 主從節(jié)點部署
- Redis Sentinel(哨兵)模式部署
- Redis 集群模式
2. Redis 集群最大節(jié)點個數(shù)是多少厌秒?
16384 個
3. Redis 集群的主從復(fù)制模型是怎樣的秃嗜?
Redis 中的主從復(fù)制,也就是 Master-Slave 模型藕筋,多個 Redis 實例間的數(shù)據(jù)同步以及 Redis 集群中數(shù)據(jù)同步會使用主從復(fù)制翅雏。
主從復(fù)制主要是數(shù)據(jù)同步圈驼, 數(shù)據(jù)同步分為全量同步和增量同步。
全量同步:
全量同步一般發(fā)生在 Slave 機(jī)器初始化階段望几, 這時候 Slave 需要將 Master 上的所有數(shù)據(jù)都進(jìn)行同步復(fù)制绩脆。
大概步驟如下所示:
- 從服務(wù)器發(fā)送 SYNC 命令,鏈接主服務(wù)器
- 主服務(wù)器收到 SYNC 命令后,進(jìn)行存盤的操作靴迫,并繼續(xù)收集后續(xù)的寫命令惕味,存儲緩沖區(qū)
- 存盤結(jié)束后,將對應(yīng)的數(shù)據(jù)文件發(fā)送到 Slave 中玉锌,完成一次全量同步
- 主服務(wù)數(shù)據(jù)發(fā)送完畢后名挥,將進(jìn)行增量的緩沖區(qū)數(shù)據(jù)同步
- Slave 加載數(shù)據(jù)文件和緩沖區(qū)數(shù)據(jù),開始接受命令請求主守,提供操作
增量更新:
Slave 節(jié)點初始化完成之后禀倔,開始正常工作,Master 節(jié)點進(jìn)行的寫操作都會同步到 Slave 節(jié)點上面参淫。Master 節(jié)點每執(zhí)行一個寫命令都會向從服務(wù)器發(fā)送相同的寫命令蹋艺,從服務(wù)器接收到命令,并執(zhí)行黄刚。
4. 請介紹一下 Redis 集群實現(xiàn)方案
1. Redis Cluster 集群方案(服務(wù)端 Sharding 技術(shù))
Redis Cluster 是 3.0 版本開始正式提供的服務(wù)器 Sharding 技術(shù)。引入 slot(槽)的概念民效,整個集群共有 16384 個槽憔维。根據(jù) key 進(jìn)行散列(CRC16 后 16384 取模),分配到其中一個槽當(dāng)中畏邢。
2. Redis Sharding 集群(客戶端 Sharding 技術(shù))
Redis Sharding 出現(xiàn)先與 Redis Cluster 方案业扒,他是多 Redis 實例集群方案。
客戶端 Sharding 方式舒萎,該向哪個 Redis 節(jié)點操作數(shù)據(jù)程储,由客戶端來進(jìn)行控制。服務(wù)端 Redis 還是一個個相對獨立的 Redis 實例節(jié)點臂寝,沒有做任何變動章鲤。節(jié)點選擇可采用的方法:一致性 hash 算法或者虛擬節(jié)點算法。