1. 簡單地說一說 Redis 的主從。 主從是指一臺 Redis 做 master,在 master 下面掛 n 個 slave,master 用來寫數(shù)據(jù),寫完同步到 slave 上,slave 用來讀數(shù)據(jù)。Redis 主從主要有兩種種模式: - 一主n從:一個 master 下面掛 n 個 slave,缺點就是這 n 個 slave 都是掛同一個 master 下,master 掛了從機(jī)還是從機(jī),不會變成主機(jī),那么這個主從也就不可用了,可以手動執(zhí)行 slave of one 命令在 slave 中選出新的 master;
- 串聯(lián)主從:A 下面掛著 B,B下面掛著 C,一脈相承;
2. Redis 主從復(fù)制的原理是什么?
- master 會生成一個 RDB 文件發(fā)送給 slave,slave 接收到 RDB 后先寫入磁盤,然后再讀取 RDB 同步數(shù)據(jù)。
3. Redis 集群有哪些方案?
- 哨兵:一主 n 從的自動版,上面說的 master 掛了需要手動選出新的 master,哨兵就是 Redis 會有一個 sentinel 集群去監(jiān)控 Redis 的節(jié)點,一旦發(fā)現(xiàn) master 掛了,就會投票選舉出新的 master。優(yōu)點就是簡單易用,缺點就是只有一個 master 寫數(shù)據(jù),容易成為性能瓶頸。
- Redis-cluster:Redis 官方出的集群模式,它是有 n 個 master,每個 master下面掛 n 個 slave,也就是有 n 個主從。每個 master 之間不會同步數(shù)據(jù),但是可以共享數(shù)據(jù)。寫數(shù)據(jù)的時候,只會寫到其中一個 master 上,然后會同步到這個 master 所屬的 slave 上。讀數(shù)據(jù)的時候,如果你是在沒有那個 key 的節(jié)點上操作的,就會將命令轉(zhuǎn)發(fā)到有那個 key 的節(jié)點上。由于要轉(zhuǎn)發(fā)命令,每個 master 之間采用 gossip 協(xié)議進(jìn)行通信,因此每個 master 都需要開放兩個端口,比如一個是 6379, 那么還要一個加一萬的 16379,用來進(jìn)行通信。redis-cluster 的原理是,它采用了哈希槽的概念,總共有 16384 個哈希槽,然后將其分配給 Redis 的 master 節(jié)點,寫數(shù)據(jù)時,用 crc16 算法對 key 進(jìn)行計算,然后再對 16384 取余,就知道要寫到哪個 master 上。這種方式優(yōu)點就是性能好,支持動態(tài)擴(kuò)容,缺點就是只能使用 0 號庫,且不支持管道技術(shù)。
- 基于客戶端分片:寫數(shù)據(jù)的時候,在程序中就對 key 進(jìn)行計算,判斷好要寫到哪個節(jié)點上。優(yōu)點就是每個 Redis 實例之間沒有關(guān)聯(lián),容易線性擴(kuò)展,缺點就是 Redis 實例一旦增加,key 的映射規(guī)則就需要改。
- 基于代理分片:客戶端請求都發(fā)到代理中,代理再去判斷要發(fā)往哪臺節(jié)點。優(yōu)點是程序不需要關(guān)心有多少臺 Redis 節(jié)點,不需要對 key 做映射規(guī)則,缺點就是多了一層代理,有性能損耗。常見的代理有豌豆莢開源的 codis 和推特開源的 Twemproxy。
4. 你是如何處理雙寫一致性問題的? 雙寫一致性是指數(shù)據(jù)庫數(shù)據(jù)與 Redis 中數(shù)據(jù)的一致性問題。一般是先寫數(shù)據(jù)庫,再寫 Redis,不過這樣會有問題,假如寫完數(shù)據(jù)庫,還沒來得及更新 Redis 的時候,請求進(jìn)來了,讀取到的就是 Redis 中的舊數(shù)據(jù)??梢圆捎秒p刪延遲策略來處理雙寫一致性問題。具體流程: 休眠一段時間再刪的目的是,假如請求 A 進(jìn)來先刪了 Redis 中的數(shù)據(jù),然后再還沒來得及更新數(shù)據(jù)庫的時候,請求 B 進(jìn)來了,讀取到的是數(shù)據(jù)庫的舊數(shù)據(jù);接著請求 A 更新完了 DB,再刪 Redis;然后請求 B 再把讀取到的舊數(shù)據(jù)寫到 Redis 中,這樣還是會導(dǎo)致數(shù)據(jù)庫和 Redis 數(shù)據(jù)不一致。休眠一段時間就可以保證請求 B 能把讀取數(shù)據(jù)庫和寫 Redis 的步驟執(zhí)行完,執(zhí)行完后請求 A 再去刪 Redis,就可以把 Redis 中的舊數(shù)據(jù)刪除。所以休眠的時間應(yīng)該大于請求 B 讀數(shù)據(jù)庫和寫 Redis 的總時間。如果不是要求強(qiáng)一致性,不推薦這種做法,休眠一段時間體驗不太好。
5. 如何處理并發(fā)競爭 key 的問題?
- 并發(fā)競爭 key 是指多個客戶端同時對同一個 key 進(jìn)行操作,可以用分布式鎖,也可以用消息隊列將請求變成串行的,或者寫入的 value 值加個時間戳,寫之前判斷有沒有晚與當(dāng)前時間的時間戳存在,若有,則不寫入。
6. 什么是緩存雪崩?如何解決?
- 緩存雪崩就是同一時刻緩存大面積失效,大量的請求直接落到數(shù)據(jù)庫,把數(shù)據(jù)庫壓垮。解決辦法是為 key 設(shè)置不同的過期時間,避免同一時刻失效,操作數(shù)據(jù)庫的方法加鎖,讓請求串行。
7. 什么是緩存穿透?如何解決?
- 緩存穿透就是大量請求數(shù)據(jù)庫和緩存中都沒有的數(shù)據(jù),造成數(shù)據(jù)庫崩掉。解決辦法是做好參數(shù)校驗,非法請求直接擋掉;用布隆過濾器,將數(shù)據(jù)庫的數(shù)據(jù)緩存到布隆過濾器中,請求數(shù)據(jù)庫之前先判斷布隆過濾器中有沒有,沒有就直接擋掉。
8. 什么是緩存擊穿?如何解決?
- 緩存擊穿就是同時大量請求 Redis 中沒有的一個 key,所有這個 key 的請求都落到數(shù)據(jù)庫,導(dǎo)致數(shù)據(jù)庫崩掉。解決辦法就是用布隆過濾器,設(shè)置熱點數(shù)據(jù)永不過期等。
9. 如何在一億個 key 中找出指定前綴的 key?
- keys prefix*:這種方式會阻塞 Redis,直至查詢完成;
- scan 0 match prefix* count 10:利用游標(biāo),不會阻塞 Redis。這個就表示從 0 開始查詢出 10 條符合條件的 key,第二次就是 scan 10 match prefix* 20。
|