最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

一文了解發(fā)現(xiàn)并解決Redis熱key與大key問題

 更新時(shí)間:2024年05月12日 16:00:52   作者:CoLiuRs  
熱key是服務(wù)端的常見問題,本文主要介紹Redis熱key與大key問題的解決方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

使用緩存

為什么使用緩存

緩存就是數(shù)據(jù)交換的緩沖區(qū)(稱作Cache),目的就是提高我們的接口性能,特別是那些需要大量CPU計(jì)算和I/O獲取的數(shù)據(jù)。

使用緩存帶來的問題

緩存雖然能夠提高應(yīng)用程序的性能,但也會(huì)帶來一些問題。比如:緩存失效,緩存擊穿,緩存雪崩,數(shù)據(jù)一致性問題

緩存雪崩

緩存失效為什么會(huì)帶來問題呢?試想一下,單個(gè)的緩存失效其實(shí)并不會(huì)引發(fā)多大的問題,問題在于當(dāng)大量的Key同時(shí)失效時(shí),在高并發(fā)的情況下,大量的請(qǐng)求同時(shí)到數(shù)據(jù)庫層,會(huì)給數(shù)據(jù)庫層帶來壓力,從而引發(fā)其他的問題。

解決方案

優(yōu)化過期時(shí)間

既然是同時(shí)失效,那么我們只需要在Key的失效時(shí)間上再加上一個(gè)隨機(jī)時(shí)間就好了,也就是失效時(shí)間 + 隨機(jī)時(shí)間。go-zero 上已經(jīng)有相關(guān)的代碼,我簡單摘抄出來看下

// A Unstable is used to generate random value around the mean value base on given deviation.
type Unstable struct {
	deviation float64
	r         *rand.Rand
	lock      *sync.Mutex
}


// AroundDuration returns a random duration with given base and deviation.
func (u Unstable) AroundDuration(base time.Duration) time.Duration {
	u.lock.Lock()
	val := time.Duration((1 + u.deviation - 2*u.deviation*u.r.Float64()) * float64(base))
	u.lock.Unlock()
	return val
}

優(yōu)化緩存

采用多級(jí)緩存,不同級(jí)別緩存設(shè)置的超時(shí)時(shí)間不同,及時(shí)某個(gè)級(jí)別緩存都過期,也有其他級(jí)別緩存兜底。代碼如下,完整代碼見:cache_redis.go

func (r *RedisCacheClient) Get(ctx context.Context, key string, fetch fetchFunc) (result []byte, err error) {
	var byteValue []byte
	fullKey := getFullKey(r.prefix, key)
	fullKeyByte, _ := json.Marshal(fullKey)
	if val, err := r.localCache.Get(fullKeyByte); err == nil {
		r.status.IncrementLocalCacheHit()
		return val, nil
	}
	r.status.IncrementLocalCacheMiss()
	startTime := time.Now()
	byteValue, err = r.client.Get(fullKey).Bytes()
	elapsed := time.Since(startTime).Milliseconds()
	for _, p := range r.plugins {
		p.OnGetRequestEnd(ctx, cmdGet, elapsed, fullKey, err)
	}
	
	// 數(shù)據(jù)源拉取原始數(shù)據(jù)
    ........	
}

緩存擊穿

對(duì)于某些key設(shè)置了過期時(shí)間,但是其是熱點(diǎn)數(shù)據(jù),如果某個(gè)key失效,可能大量的請(qǐng)求打過來,緩存未命中,然后去數(shù)據(jù)庫訪問,此時(shí)數(shù)據(jù)庫訪問量會(huì)急劇增加。

解決方案

多級(jí)緩存+singleflight

我們可以設(shè)置多級(jí)緩存,每一級(jí)緩存失效時(shí)間不一樣,某個(gè)級(jí)別緩存過期,也有其他級(jí)別緩存兜底。而且再加上singleflight 限制,就可以做每一個(gè)服務(wù)實(shí)例只有一個(gè)請(qǐng)求最終到數(shù)據(jù)庫源上,大大減輕了數(shù)據(jù)源壓力

緩存穿透

緩存穿透是指查詢的數(shù)據(jù)在數(shù)據(jù)庫是沒有的,那么在緩存中自然也沒有,所以,在緩存中查不到就會(huì)去數(shù)據(jù)庫取查詢,這樣的請(qǐng)求一多,那么我們的數(shù)據(jù)庫的壓力自然會(huì)增大。

解決方案

設(shè)置Null值

  • 約定:對(duì)于返回為Null的依然緩存,對(duì)于拋出異常的返回不進(jìn)行緩存,注意不要把拋異常的也給緩存了。采用這種手段的會(huì)增加我們緩存的維護(hù)成本,需要在插入緩存的時(shí)候刪除這個(gè)空緩存,當(dāng)然我們可以通過設(shè)置較短的超時(shí)時(shí)間來解決這個(gè)問題。

數(shù)據(jù)過濾

  • 小數(shù)據(jù)用BitMap,大數(shù)據(jù)可以用布隆過濾器

數(shù)據(jù)一致性問題

我們通常說的數(shù)據(jù)一致性指的是在程序運(yùn)行過程中本地緩存、分布式緩存、mysql數(shù)據(jù)庫三者之間的數(shù)據(jù)一致性

本地緩存與DB保持一致

解決方案

MQ 方案

  • 應(yīng)用實(shí)例1收到請(qǐng)求,更新 db,同時(shí)更新應(yīng)用自己的本地緩存.
  • 應(yīng)用實(shí)例1 發(fā)送更新 mq 廣播消息.
  • 應(yīng)用 實(shí)例2 和應(yīng)用實(shí)例3 收到消息,查詢 db,更新本地緩存.
  • 這個(gè)時(shí)候應(yīng)用實(shí)例1,2,3與 DB 數(shù)據(jù)就保持一致

Redis與DB保持一致

基于 binlog 方案

  • 更新 db 數(shù)據(jù)
  • 監(jiān)聽 mysql binlog, 并寫入到MQ
  • 啟動(dòng)一個(gè)數(shù)據(jù)處理應(yīng)用,消費(fèi) MQ 數(shù)據(jù)并進(jìn)行數(shù)據(jù)加工
  • 將加工后的數(shù)據(jù)寫入 redis
  • 查詢 redis 數(shù)據(jù)返回

延遲雙刪方案

先進(jìn)行緩存清除,再執(zhí)行 update sql,最后(延遲 N 秒)再執(zhí)行緩存清除。
上述中(延遲 N 秒)的時(shí)間要大于一次寫操作的時(shí)間,一般為 3-5 秒。

基于定時(shí)任務(wù)方案

1.更新 db 數(shù)據(jù),同時(shí)寫入數(shù)據(jù)到 redis
2.啟動(dòng)一個(gè)定時(shí)任務(wù)定時(shí)將 db 數(shù)據(jù)同步到 redis

熱key和大key問題

熱key

熱key是服務(wù)端的常見問題,指一段時(shí)間內(nèi)某個(gè)key的訪問量遠(yuǎn)遠(yuǎn)超過其他的key,導(dǎo)致大量訪問流量落在某一個(gè)redis實(shí)例中;或者是帶寬使用率集中在特定的key

以被請(qǐng)求頻率來定義是否是熱key,沒有固定經(jīng)驗(yàn)值。某個(gè)key被高頻訪問導(dǎo)致系統(tǒng)穩(wěn)定性變差,都可以定義為熱key。

可能造成的問題

  • 占用大量的CPU資源,影響其他請(qǐng)求并導(dǎo)致整體性能降低。
  • 集群架構(gòu)下,產(chǎn)生訪問傾斜,即某個(gè)數(shù)據(jù)分片被大量訪問,而其他數(shù)據(jù)分片處于空閑狀態(tài),可能引起該數(shù)據(jù)分片的連接數(shù)被耗盡,新的連接建立請(qǐng)求被拒絕等問題。
  • 在搶購或秒殺場景下,可能因商品對(duì)應(yīng)庫存Key的請(qǐng)求量過大,超出Redis處理能力造成超賣。
  • 熱Key的請(qǐng)求壓力數(shù)量超出Redis的承受能力易造成緩存擊穿,即大量請(qǐng)求將被直接指向后端的存儲(chǔ)層,導(dǎo)致存儲(chǔ)訪問量激增甚至宕機(jī),從而影響其他業(yè)務(wù)。

發(fā)現(xiàn)方法

開發(fā)獨(dú)立的熱 key 檢測系統(tǒng)

提供單獨(dú)的熱 key 檢測的接入 sdk,應(yīng)用系統(tǒng)引入該 sdk 后,熱 key 檢測系統(tǒng)自動(dòng)計(jì)
算是否熱 key 并推送相關(guān)結(jié)果給應(yīng)用系統(tǒng),應(yīng)用系統(tǒng)根據(jù)業(yè)務(wù)實(shí)際情況進(jìn)行相應(yīng)處理。

改寫 redis 客戶端收集上報(bào)數(shù)據(jù)

改寫 Redis SDK,記錄每個(gè)請(qǐng)求,定時(shí)把收集到的數(shù)據(jù)上報(bào),然后由一個(gè)統(tǒng)一的服務(wù)進(jìn)行聚合計(jì)算。

解決方案

利用本地緩存

在你發(fā)現(xiàn)熱 key 以后,把熱 key 加載到系統(tǒng)的內(nèi)存中。針對(duì)這種熱 key 請(qǐng)求,會(huì)直接從內(nèi)存中取,而不會(huì)走到 redis 層。

  • 優(yōu)點(diǎn):內(nèi)存訪問和 redis 訪問的速度不在一個(gè)量級(jí),基于本地緩存,接口性能非常好, 可以
    大大增加單實(shí)例的 QPS。
  • 缺點(diǎn):受應(yīng)用內(nèi)存限制,容量有限,數(shù)據(jù)量非常大的時(shí)候,占用太多內(nèi)存,不太適合。部分熱點(diǎn)數(shù)據(jù),需要提前預(yù)知。熱點(diǎn)數(shù)據(jù)自動(dòng)檢測有一定的延遲,系統(tǒng)短時(shí)間內(nèi)承受的風(fēng)險(xiǎn)比較大。

大key

大key是指當(dāng)redis的字符串類型占用內(nèi)存過大或非字符串類型元素?cái)?shù)量過多

生產(chǎn)環(huán)境中,綜合衡量運(yùn)維和環(huán)境的情況,給大key定義參考值如下:

  • string類型的key超過10KB
  • hash/set/zset/list等數(shù)據(jù)結(jié)構(gòu)中元素個(gè)數(shù)大于5k/整體占用內(nèi)存大于10MB

可能造成的問題

  • 客戶端執(zhí)行命令的時(shí)長變慢。
  • Redis內(nèi)存達(dá)到maxmemory參數(shù)定義的上限引發(fā)操作阻塞或重要的Key被逐出,甚至引發(fā)內(nèi)存溢出(Out Of Memory)。
  • 集群架構(gòu)下,某個(gè)數(shù)據(jù)分片的內(nèi)存使用率遠(yuǎn)超其他數(shù)據(jù)分片,無法使數(shù)據(jù)分片的內(nèi)存資源達(dá)到均衡。
  • 對(duì)大Key執(zhí)行讀請(qǐng)求,會(huì)使Redis實(shí)例的帶寬使用率被占滿,導(dǎo)致自身服務(wù)變慢,同時(shí)易波及相關(guān)的服務(wù)。
  • 對(duì)大Key執(zhí)行刪除操作,易造成主庫較長時(shí)間的阻塞,進(jìn)而可能引發(fā)同步中斷或主從切換。

發(fā)現(xiàn)方法

實(shí)時(shí)統(tǒng)計(jì)

我們可以通過在Redis 客戶端上實(shí)時(shí)統(tǒng)計(jì)出大Key,直接計(jì)算出Key對(duì)應(yīng)的Value值大小就可以,例如

// b 為序列化之后的數(shù)據(jù)
b, err := utils.Serialize(value, c.getSerializer())
if err != nil {
   return err
}
// var b []byte
// 長度
reqSize =  len(b)

// 10KB
bigKey := 1024 * 10
if reqSize > bigKey {
    
}
  • 優(yōu)點(diǎn):對(duì)性能幾乎無影響。
  • 缺點(diǎn):返回的Key序列化長度并不等同于它在內(nèi)存空間中的真實(shí)長度,因此不夠準(zhǔn)確,僅可作為參考。

離線全量Key分析

  • 對(duì)Redis的RDB備份文件進(jìn)行定制化的分析,幫助您發(fā)現(xiàn)實(shí)例中的大Key,掌握Key在內(nèi)存中的占用和分布

  • Redis提供了bigkeys參數(shù)能夠使redis-cli以遍歷的方式分析Redis實(shí)例中的所有Key,并返回Key的整體統(tǒng)計(jì)信息與每個(gè)數(shù)據(jù)類型中Top1的大Key,bigkeys僅能分析并輸入六種數(shù)據(jù)類型(STRING、LIST、HASH、SET、ZSET、STREAM),命令示例為redis-cli -h 127.0.0.1 -p 6379 --bigkeys

  • 優(yōu)點(diǎn):可對(duì)歷史備份數(shù)據(jù)進(jìn)行分析,對(duì)線上服務(wù)無影響。

  • 缺點(diǎn):時(shí)效性差,RDB文件較大時(shí)耗時(shí)較長。

解決方案

  • 業(yè)務(wù)拆分,將key的含義更細(xì)粒度化,避免大key出現(xiàn)。
  • 數(shù)據(jù)結(jié)構(gòu)上拆分。如果大key是個(gè)大json,可以通過mset的方式,將這個(gè)key的內(nèi)容打散到各個(gè)實(shí)例中,減小大key對(duì)數(shù)據(jù)量傾斜的影響;如果是大list,可以拆成list_1,list_2,list_N;其他數(shù)據(jù)結(jié)構(gòu)同理。(可以考慮增加單獨(dú)key存儲(chǔ)大key被拆分的個(gè)數(shù)或元數(shù)據(jù)信息)
  • 對(duì)于長文本,更建議使用文檔型數(shù)據(jù)庫例如MongoDB等。
  • 對(duì)一致性要求不高的場景,嘗試使用客戶端緩存。(只解決了redis的阻塞問題,但機(jī)器或局域網(wǎng)的帶寬問題沒有改善)
  • 對(duì)大key的壓縮。相當(dāng)于用cpu資源來降低網(wǎng)絡(luò)io,其中g(shù)oogle提出的snappy算法較常用。
  • 對(duì)于hash等數(shù)據(jù)結(jié)構(gòu),需要注意業(yè)務(wù)是否可以引入定期清理無效field的機(jī)制。
    • Hash 結(jié)構(gòu)不建議使用,沒有辦法對(duì)具體的Key做過期時(shí)間設(shè)置,只能再額外開發(fā)功能去做,增加開發(fā)成本

到此這篇關(guān)于一文了解發(fā)現(xiàn)并解決Redis熱key與大key問題的文章就介紹到這了,更多相關(guān)Redis熱key與大key內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家! 

相關(guān)文章

  • React Antd Cascader組件地區(qū)選擇方式

    React Antd Cascader組件地區(qū)選擇方式

    文章介紹了在表單中實(shí)現(xiàn)地區(qū)選擇功能,使用Cascader組件動(dòng)態(tài)加載數(shù)據(jù),需通過loadData和遞歸處理實(shí)現(xiàn)增刪改查,存儲(chǔ)和回顯需完整id數(shù)組以支持多級(jí)地區(qū)展示,強(qiáng)調(diào)后端設(shè)計(jì)對(duì)數(shù)據(jù)關(guān)聯(lián)(id/pid)的重要性
    2025-08-08
  • Redis如何實(shí)現(xiàn)分布式鎖

    Redis如何實(shí)現(xiàn)分布式鎖

    這篇文章主要介紹了Redis如何實(shí)現(xiàn)分布式鎖問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-10-10
  • Redis哨兵模式在Spring Boot項(xiàng)目中的使用與實(shí)踐完全指南

    Redis哨兵模式在Spring Boot項(xiàng)目中的使用與實(shí)踐完全指南

    Redis哨兵模式為SpringBoot項(xiàng)目提供高可用Redis管理,實(shí)現(xiàn)自動(dòng)故障轉(zhuǎn)移與監(jiān)控,通過配置依賴、參數(shù)及最佳實(shí)踐(如哨兵節(jié)點(diǎn)數(shù)量、網(wǎng)絡(luò)規(guī)劃),可提升系統(tǒng)穩(wěn)定性與可靠性,本文給大家介紹Redis哨兵模式在Spring Boot項(xiàng)目中的使用與實(shí)踐,感興趣的朋友跟隨小編一起看看吧
    2025-09-09
  • Redis Cluster設(shè)置密碼修改密碼過程

    Redis Cluster設(shè)置密碼修改密碼過程

    這篇文章主要介紹了Redis Cluster設(shè)置密碼修改密碼過程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2026-06-06
  • Redis SETEX命令實(shí)現(xiàn)鍵值對(duì)管理

    Redis SETEX命令實(shí)現(xiàn)鍵值對(duì)管理

    本文主要介紹了Redis SETEX命令實(shí)現(xiàn)鍵值對(duì)管理,SETEX命令用于設(shè)置具有過期時(shí)間的鍵值對(duì),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-06-06
  • 淺談Redis中LFU算法源碼解析

    淺談Redis中LFU算法源碼解析

    Redis的LFU淘汰算法主要用于?maxmemory-policy?設(shè)置為allkeys-lfu或volatile-lfu時(shí),以最少使用頻率的鍵進(jìn)行淘汰,本文主要介紹了淺談Redis中LFU算法源碼解析,文中通過示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2025-04-04
  • Redis:Redisson分布式鎖的使用方式(推薦使用)

    Redis:Redisson分布式鎖的使用方式(推薦使用)

    這篇文章主要介紹了Redis:Redisson分布式鎖的使用方式(推薦使用),具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-04-04
  • 保證Redis中存儲(chǔ)的Token安全性的示例詳解

    保證Redis中存儲(chǔ)的Token安全性的示例詳解

    確保Redis中存儲(chǔ)的Token安全性是一個(gè)多層面的任務(wù),涉及到網(wǎng)絡(luò)、應(yīng)用、數(shù)據(jù)和操作等多個(gè)方面的安全措施,本文給大家介紹了一些詳細(xì)的實(shí)踐建議和示例,并有詳細(xì)的代碼供大家參考,需要的朋友可以參考下
    2024-03-03
  • Redis Stat的安裝指南

    Redis Stat的安裝指南

    這篇文章主要介紹了Redis Stat的安裝指南的相關(guān)資料,需要的朋友可以參考下
    2016-04-04
  • Redis @type坑的解決

    Redis @type坑的解決

    新建一個(gè)對(duì)象存入redis中,對(duì)象中會(huì)出現(xiàn)一個(gè)字段@type,本文主要介紹了Redis @type坑的解決,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-06-06

最新評(píng)論

那坡县| 新竹市| 剑河县| 龙川县| 滦南县| 彩票| 磴口县| 鄯善县| 密山市| 高安市| 揭西县| 留坝县| 岳池县| 福清市| 南昌市| 安远县| 五家渠市| 兴化市| 乐山市| 革吉县| 历史| 将乐县| 中江县| 安宁市| 安乡县| 清流县| 宿松县| 顺义区| 义乌市| 杨浦区| 化隆| 金川县| 黄梅县| 弥渡县| 焉耆| 汾阳市| 丽江市| 福州市| 密云县| 张家港市| 六枝特区|