面試分析分布式架構(gòu)Redis熱點key大Value解決方案
引言
關(guān)于 Redis 熱點數(shù)據(jù) & 大 key 大 value 問題也是容易被問的高階問題,不如一次痛快點說完,讓面試官無話可說,個人工作經(jīng)驗中,熱點數(shù)據(jù)問題在工作中相比雪崩更容易遇到,只是大部分時候熱點不夠熱,都會被提前告警解決,但這個問題一旦控制不了造成的線上問題也是足夠讓你今年績效墊底了,廢話不說進(jìn)入正題。
正常情況下,Redis 集群中數(shù)據(jù)都是均勻分配到每個節(jié)點,請求也會均勻的分布到每個分片上,但在一些特殊場景中,比如外部爬蟲、攻擊、熱點商品等,最典型的就是明星在微博上宣布離婚,吃瓜群眾紛紛涌入留言,導(dǎo)致微博評論功能崩潰,這種短時間內(nèi)某些 key 訪問量過于大,對于這種相同的 key 會請求到同一臺數(shù)據(jù)分片上,導(dǎo)致該分片負(fù)載較高成為瓶頸問題,導(dǎo)致雪崩等一系列問題。
1、面試官:你在項目中有沒有遇到 Redis 熱點數(shù)據(jù)問題,一般都是什么原因引起的?
問題分析:上次聽群里大佬面試阿里 p7 就被問到這個問題,難度指數(shù)五顆星,對我等小白著實是加分項。
答:關(guān)于熱點數(shù)據(jù)問題我有話要說,這個問題我早在剛剛學(xué)習(xí)使用 Redis 時就從已經(jīng)意識到了,所以在使用時會刻意避免,堅決不會給自己挖坑,熱點數(shù)據(jù)最大的問題會造成 Reids 集群負(fù)載不均衡(也就是數(shù)據(jù)傾斜)導(dǎo)致的故障,這些問題對于 Redis 集群都是致命打擊。
先說說造成 Reids 集群負(fù)載不均衡故障的主要原因:
- 高訪問量的 Key,也就是熱 key,根據(jù)過去的維護(hù)經(jīng)驗一個 key 訪問的 QPS 超過 1000 就要高度關(guān)注了,比如熱門商品,熱門話題等。
- 大 Value,有些 key 訪問 QPS 雖然不高,但是由于 value 很大,造成網(wǎng)卡負(fù)載較大,網(wǎng)卡流量被打滿,單臺機(jī)器可能出現(xiàn)千兆 / 秒,IO 故障。
- 熱點 Key + 大 Value 同時存在,服務(wù)器殺手。
那么熱點 key 或大 Value 會造成哪些故障呢:
- 數(shù)據(jù)傾斜問題:大 Value 會導(dǎo)致集群不同節(jié)點數(shù)據(jù)分布不均勻,造成數(shù)據(jù)傾斜問題,大量讀寫比例非常高的請求都會落到同一個 redis server 上,該 redis 的負(fù)載就會嚴(yán)重升高,容易打掛。
- QPS 傾斜:分片上的 QPS 不均。
- 大 Value 會導(dǎo)致 Redis 服務(wù)器緩沖區(qū)不足,造成 get 超時。
- 由于 Value 過大,導(dǎo)致機(jī)房網(wǎng)卡流量不足。
- Redis 緩存失效導(dǎo)致數(shù)據(jù)庫層被擊穿的連鎖反應(yīng)。
2、面試官:真實項目中,那熱點數(shù)據(jù)問題你是如何準(zhǔn)確定位的呢?
答:這個問題的解決辦法比較寬泛,要具體看不同業(yè)務(wù)場景,比如公司組織促銷活動,那參加促銷的商品肯定是有辦法提前統(tǒng)計的,這種場景就可以通過預(yù)估法。對于突發(fā)事件,不確定因素,Redis 會自己監(jiān)控?zé)狳c數(shù)據(jù)。大概歸納下:
提前獲知法:
根據(jù)業(yè)務(wù),人肉統(tǒng)計 or 系統(tǒng)統(tǒng)計可能會成為熱點的數(shù)據(jù),如,促銷活動商品,熱門話題,節(jié)假日話題,紀(jì)念日活動等。
Redis 客戶端收集法:
調(diào)用端通過計數(shù)的方式統(tǒng)計 key 的請求次數(shù),但是無法預(yù)知 key 的個數(shù),代碼侵入性強(qiáng)。
public Connection sendCommand(final ProtocolCommand cmd, final byte[]... args) { //從參數(shù)中獲取key String key = analysis(args); //計數(shù) counterKey(key); //ignore }
Redis 集群代理層統(tǒng)計:
像 Twemproxy,codis 這些基于代理的 Redis 分布式架構(gòu),統(tǒng)一的入口,可以在 Proxy 層做收集上報,但是缺點很明顯,并非所有的 Redis 集群架構(gòu)都有 proxy。
Redis 服務(wù)端收集:
監(jiān)控 Redis 單個分片的 QPS,發(fā)現(xiàn) QPS 傾斜到一定程度的節(jié)點進(jìn)行 monitor,獲取熱點 key, Redis 提供了 monitor 命令,可以統(tǒng)計出一段時間內(nèi)的某 Redis 節(jié)點上的所有命令,分析熱點 key,在高并發(fā)條件下,會存在內(nèi)存暴漲和 Redis 性能的隱患,所以此種方法適合在短時間內(nèi)使用;同樣只能統(tǒng)計一個 Redis 節(jié)點的熱點 key,對于集群需要匯總統(tǒng)計,業(yè)務(wù)角度講稍微麻煩一點。
以上為說的這 4 個方法都是現(xiàn)在業(yè)界比較常用的,方法,我通過學(xué)習(xí) Redis 源碼還有一個新的想法。第 5 種:修改 Redis 源碼。
修改 Redis 源代碼:(從讀源碼中想到的思路)
我發(fā)現(xiàn) Redis4.0 為我們帶來了許多新特性,其中便包括基于 LFU 的熱點 key 發(fā)現(xiàn)機(jī)制,有了這個新特性,我們就可以在此基礎(chǔ)上實現(xiàn)熱點 key 的統(tǒng)計,這個只是我的個人思路。
面試官心理:小伙子還挺有想法,思路挺開闊,還打起了修改源碼的注意,我都沒這個野心。團(tuán)隊里就需要這樣的人。
(發(fā)現(xiàn)問題,分析問題,解決問題,不等面試官發(fā)問,直接講述如何解決熱點數(shù)據(jù)問題,這才是核心內(nèi)容)
3、如何解決熱點數(shù)據(jù)問題
答:關(guān)于如何治理熱點數(shù)據(jù)問題,解決這個問題主要從兩個方面考慮,第一是數(shù)據(jù)分片,讓壓力均攤到集群的多個分片上,防止單個機(jī)器打掛,第二是遷移隔離。
概括總結(jié):
key 拆分:
如果當(dāng)前 key 的類型是一個二級數(shù)據(jù)結(jié)構(gòu),例如哈希類型。如果該哈希元素個數(shù)較多,可以考慮將當(dāng)前 hash 進(jìn)行拆分,這樣該熱點 key 可以拆分為若干個新的 key 分布到不同 Redis 節(jié)點上,從而減輕壓力
遷移熱點 key:
以 Redis Cluster 為例,可以將熱點 key 所在的 slot 單獨遷移到一個新的 Redis 節(jié)點上,這樣這個熱點 key 即使 QPS 很高,也不會影響到整個集群的其他業(yè)務(wù),還可以定制化開發(fā),熱點 key 自動遷移到獨立節(jié)點上,這種方案也較多副本。
熱點 key 限流:
對于讀命令我們可以通過遷移熱點 key 然后添加從節(jié)點來解決,對于寫命令我們可以通過單獨針對這個熱點 key 來限流。
增加本地緩存:
對于數(shù)據(jù)一致性不是那么高的業(yè)務(wù),可以將熱點 key 緩存到業(yè)務(wù)機(jī)器的本地緩存中,因為是業(yè)務(wù)端的本地內(nèi)存中,省去了一次遠(yuǎn)程的 IO 調(diào)用。但是當(dāng)數(shù)據(jù)更新時,可能會造成業(yè)務(wù)和 Redis 數(shù)據(jù)不一致。
面試官:你回答得很好,考慮得很全面。
4、面試官:關(guān)于 Redis 最后一個問題,Redis 支持豐富的數(shù)據(jù)類型,那么這些數(shù)據(jù)類型存儲的大 Value 如何解決,線上有遇到這種情況嗎?
問題分析:相比熱點 key 大概念,大 Value 的概念比好好理解,由于 Redis 是單線程運行的,如果一次操作的 value 很大會對整個 redis 的響應(yīng)時間造成負(fù)面影響,因為 Redis 是 Key - Value 結(jié)構(gòu)數(shù)據(jù)庫,大 value 就是單個 value 占用內(nèi)存較大,對 Redis 集群造成最直接的影響就是數(shù)據(jù)傾斜。
答:(想難倒我?我可是有備而來。)
我先說說多大的 Value 算大,根據(jù)公司基礎(chǔ)架構(gòu)給出的經(jīng)驗值可做以下劃分:
注:(經(jīng)驗值不是標(biāo)準(zhǔn),都是根據(jù)集群運維人員長期觀察線上 case 總結(jié)出來的)
大:string 類型 value > 10K,set、list、hash、zset 等集合數(shù)據(jù)類型中的元素個數(shù) > 1000。
超大: string 類型 value > 100K,set、list、hash、zset 等集合數(shù)據(jù)類型中的元素個數(shù) > 10000。
由于 Redis 是單線程運行的,如果一次操作的 value 很大會對整個 redis 的響應(yīng)時間造成負(fù)面影響,所以,業(yè)務(wù)上能拆則拆,下面舉幾個典型的分拆方案:
- 一個較大的 key-value 拆分成幾個 key-value ,將操作壓力平攤到多個 redis 實例中,降低對單個 redis 的 IO 影響
- 將分拆后的幾個 key-value 存儲在一個 hash 中,每個 field 代表一個具體的屬性,使用 hget,hmget 來獲取部分的 value,使用 hset,hmset 來更新部分屬性。
- hash、set、zset、list 中存儲過多的元素
類似于場景一中的第一個做法,可以將這些元素分拆。
以 hash 為例,原先的正常存取流程是:
hget(hashKey, field); hset(hashKey, field, value)
現(xiàn)在,固定一個桶的數(shù)量,比如 10000,每次存取的時候,先在本地計算 field 的 hash 值,模除 10000,確定該 field 落在哪個 key 上,核心思想就是將 value 打散,每次只 get 你需要的。
newHashKey = hashKey + (hash(field) % 10000); hset(newHashKey, field, value); hget(newHashKey, field)
面試官已經(jīng)被我折服,終于放棄了 Redis 的追問。
總結(jié)
如果你對 Redis 真對不是很熟悉,有些人干脆說自己項目小,壓根沒有用過 Redis,只知道一些理論知識,那么我建議你讀者重點掌握《 說說 Redis 中有哪些數(shù)據(jù)結(jié)構(gòu)及底層實現(xiàn)原理》《緩存必問:Redis 持久化,高可用集群》《Redis 雪崩,穿透,擊穿三連問》這三篇,至于 Redis 熱點數(shù)據(jù)問題,如果想要多談點工資盡量掌握。推薦閱讀《Redis 開發(fā)與運維》
以上就是面試分析分布式架構(gòu)Redis熱點key大Value解決方案的詳細(xì)內(nèi)容,更多關(guān)于分布式架構(gòu)面試Redis熱點key大Value的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
使用Redis存儲SpringBoot項目中Session的詳細(xì)步驟
在開發(fā)Spring Boot項目時,我們通常會遇到如何高效管理Session的問題,默認(rèn)情況下,Spring Boot會將Session存儲在內(nèi)存中,今天,我們將學(xué)習(xí)如何將Session存儲從內(nèi)存切換到Redis,并驗證配置是否成功,需要的朋友可以參考下2024-06-06Redis Redisson lock和tryLock的原理分析
這篇文章主要介紹了Redis Redisson lock和tryLock的原理分析,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-04-04