在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

聊聊緩存擊穿的解決方法

馬哥Linux運維 ? 來源:博客園snail_lie ? 2024-10-23 13:54 ? 次閱讀

緩存擊穿,Redis中的某個熱點key不存在或者過期,但是此時有大量的用戶訪問該key。比如xxx直播間優惠券搶購、xxx商品活動,這時候大量用戶會在某個時間點一同訪問該熱點事件。但是可能由于某種原因,redis的這個熱點key沒有設置,或者過期了,那么這時候大量高并發對于該key的請求就得不到redis的響應,那么就會將請求直接打在DB服務器上,造成DB突刺,CPU和內存瞬間被打滿,最終導致服務崩潰。

本人所負責的業務就存在這樣的場景,以直播間邀請榜單為例,顧名思義就是會查詢該直播間實時的邀請人數,統計前30名邀請人數最多的用戶展示在直播間里面,通過榜單去刺激C端用戶的分享參與熱情。下面一起分析下這個場景遇到的問題和解決方案。

問題1:
統計邀請榜單需要加載實時的,即我邀請一個人進來,假設在前30名,那我不得上榜嗎?那問題來了,這種數據我是不是得實時去查數據庫呢?

解決方案:這種業務,我們一般會設置一個短時間的緩存,比如30秒左右。也就是在緩存失效后,即30秒去查一次數據庫,不然數據庫肯定是頂不住的。

問題2:
我們常規的設置緩存的代碼邏輯可能是下面這種。(代碼片段錯誤處理等細節請自行處理,這是一段精簡版的代碼,主要介紹Redis的處理邏輯)

//step1:讀緩存,存在則返回結果
ctx := context.Background()

rdb := redis.NewClient(&redis.Options{
Addr:     "localhost:6379",
Password: "123456",
DB:       0,
})

redisKey := "xxx_xxx_xxx" //邀請榜單數據的key

res, err := rdb.Get(ctx, redisKey).Result()
if err == nil {
return res
}

//step2:不存在緩存,讀DB
//此處省略,查DB的數據,結果為res

//step3:設置緩存,并返回結果
args := redis.SetArgs{
TTL:  time.Second * 30,
Mode: "EX",
}
_, _ = rdb.SetArgs(ctx, redisKey, res, args).Result()

return res

這種代碼邏輯在并發量小的情況下是沒有任何問題的,事實上我平時寫一些業務,基本上就把它當成一個“公式”來用,用的非常多。然而,在一些高并發的場景下,這種邏輯就會出現問題。試想一下這個場景:假如某個大直播(用戶量巨大)是在晚上8點開播,那么8點一到,那個瞬間就會有大量的C端用戶進入直播間,去調用后端的接口,假如此時接口的Redis緩存已經過期或者不存在,那么這一刻就會有大量的請求落到DB上,可想而知這一刻DB的壓力是多么巨大(這誰頂得住啊)。這就是一個典型的緩存擊穿的業務場景。
那么我們需要怎么做,才能讓我們的服務抵抗住瞬時的請求洪峰呢?

解決方案:
解決緩存擊穿的常見方法有幾種:
1、設置該key永不過期,那么就不會存在緩存失效、過期等問題。但這種方法很明顯不適合我這種場景,因為我上面提到過,我這個key值存的是邀請榜單的數據,是動態更新的,在直播中,這個榜單的數據是會變化的,所以只能設30秒的緩存時間。該方案行不通。

2、人工干預該key,比如寫一個腳本去定時讀DB數據,然后更新這個key,然后業務側(對接前端的接口)只能通過讀該key的緩存去獲取結果數據,而不能直接讀DB。這樣也能解決問題,但是貌似維護成本有點高,而且業務側不能讀DB也很不靈活,你想下如果每個熱點key都這樣去設置維護,那估計會很煩吧。該方案也行不通。

3、使用互斥鎖,即在緩存失效的時候,只有一個請求可以獲取到互斥鎖,然后去查DB,最后重建緩存。這種方案就能很好地解決緩存擊穿這個問題,也是我在工作中用來應對緩存擊穿問題的最常用的方案。下面是精簡版代碼:

//step1:讀緩存,存在則返回結果
ctx := context.Background()

rdb := redis.NewClient(&redis.Options{
Addr:     "localhost:6379",
Password: "123456",
DB:       0,
})

redisKey := "xxx_xxx_xxx" //邀請榜單數據的key

res, err := rdb.Get(ctx, redisKey).Result()
if err == nil {
return res
}

//step2:不存在緩存,加互斥鎖,讀緩存
lockKey := "yyy_yyy_yyy" //互斥鎖的key

argsLock := redis.SetArgs{
TTL:  time.Second * 3,
Mode: "NX", //不存在時才執行
}

_, err = rdb.SetArgs(ctx, lockKey, "1", argsLock).Result()
if err != nil { //獲取互斥鎖失敗
for i := 0; i < 3; i++ { //重復三次去讀緩存值
res, errRetry := rdb.Get(ctx, redisKey).Result()
if errRetry == nil { //重試讀緩存成功,則返回結果
return res 
}
time.Sleep(10 * time.Millisecond) //這里睡眠時間根據業務來定,取的是另一個線程從讀數據庫到設置緩存成功的大概時間區間
}
return nil //如果循環三次,都讀不到緩存,則返回空結果
}

//step3:獲取互斥鎖成功,則表明當前的線程/協程擁有查DB的權力
//此處省略,查DB的數據,結果為res

//step4:設置緩存,刪除互斥鎖,并返回結果
args := redis.SetArgs{
TTL:  time.Second * 30,
Mode: "EX",
}
_, _ = rdb.SetArgs(ctx, redisKey, res, args).Result()

rdb.Del(ctx, lockKey) //刪除互斥鎖

return res

以上就是個人在線上的一些項目面對緩存擊穿問題,所做的一些處理方案了。當然這個方案也不是完美的,例如當獲取到互斥鎖的當前線程/協程,出現異常,導致設置緩存失敗,那么其他線程/協程就重試3次可能都獲取不到正常結果,最后返回了一個空結果給前端。感興趣的朋友可以想想這個方案還有什么問題,然后能怎么優化,歡迎指出

一個人可以被毀滅,但不可以被打敗。

鏈接:https://www.cnblogs.com/lmz-blogs/p/18173813

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 服務器
    +關注

    關注

    12

    文章

    9277

    瀏覽量

    85826
  • 緩存
    +關注

    關注

    1

    文章

    240

    瀏覽量

    26724
  • Redis
    +關注

    關注

    0

    文章

    377

    瀏覽量

    10905

原文標題:go高并發之路——緩存擊穿

文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運維】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    鴻蒙OpenHarmony:【常見編譯問題和解決方法

    常見編譯問題和解決方法
    的頭像 發表于 05-11 16:09 ?2400次閱讀

    阻容降壓 剛一上電 穩壓管就擊穿了,然后限流的線繞電阻也燒了,請問大佬這是怎么回事,有什么解決方法嗎。

    `阻容降壓 剛一上電 穩壓管ZD1和2就擊穿了,然后限流的線繞電阻R20也燒了,請問大佬這是怎么回事,有什么解決方法嗎。`
    發表于 04-26 16:38

    聊聊環形緩存在單片機程序中的使用

    片頭因為環形緩存在單片機程序中的使用是非常有效的,非常有用的,關于這個話題在此專門開一文章來聊聊這個話題。環形緩存的用途主要是來緩存數據,而需要緩存
    發表于 12-06 08:29

    短波通信盲區現象解決方法介紹

    短波通信盲區現象解決方法介紹短波通信盲區現象解決方法介紹短波通信盲區現象解決方法介紹
    發表于 11-10 17:13 ?5次下載

    sdwebimage清除緩存方法

    清除通過SDWebImage進行的緩存;Sdwebimage手動清除緩存方法;iOS SDWebImage清空緩存方法.
    發表于 11-09 14:38 ?3630次閱讀
    sdwebimage清除<b class='flag-5'>緩存</b><b class='flag-5'>方法</b>

    電容擊穿是開路還是短路_電容擊穿原因是什么

    本文開始闡述了電容擊穿的概念和電容器被擊穿的條件,其次分析了電容擊穿后是開路還是短路,最后介紹了電容擊穿的原因以及避免介質擊穿
    發表于 03-27 18:21 ?6w次閱讀

    內存安裝和使用常見問題的解決方法資料分析

    自銳龍平臺發布以來,AMD CPU憑借超高的性價比迅速崛起,如今整個市場已成為AMD和Intel平分秋色“五五開”的局面。但是盡管AMD銳龍平臺來勢洶洶,其內存控制器一直處于有待完善的水平。所以今天小編就藉此機會簡單聊聊關于內存常見問題的解決方法
    的頭像 發表于 12-15 11:11 ?4417次閱讀

    如何設計一個緩存系統?

    設計一個緩存系統,不得不要考慮的問題就是:緩存穿透、緩存擊穿與失效時的雪崩效應。 緩存穿透 緩存
    的頭像 發表于 02-08 11:40 ?2961次閱讀

    聊聊緩存數據庫一致性

    在云服務中,緩存是極其重要的一點。所謂緩存,其實是一個高速數據存儲層。當緩存存在后,日后再次請求該數據就會直接訪問緩存,提升數據訪問的速度。
    的頭像 發表于 01-30 17:41 ?815次閱讀

    如何在SpringBoot中解決Redis的緩存穿透等問題

    今天給大家介紹一下如何在SpringBoot中解決Redis的緩存穿透、緩存擊穿緩存雪崩的問題。
    的頭像 發表于 04-28 11:35 ?753次閱讀

    聊聊分頁列表緩存設計

    這是最簡單易懂的方案,我們按照不同的分頁條件查詢出結果后,直接緩存分頁結果 。
    的頭像 發表于 06-06 18:25 ?753次閱讀
    <b class='flag-5'>聊聊</b>分頁列表<b class='flag-5'>緩存</b>設計

    聊聊本地緩存和分布式緩存

    本地緩存 :應用中的緩存組件,緩存組件和應用在同一進程中,緩存的讀寫非常快,沒有網絡開銷。但各應用或集群的各節點都需要維護自己的單獨緩存,無
    發表于 06-11 15:12 ?847次閱讀
    <b class='flag-5'>聊聊</b>本地<b class='flag-5'>緩存</b>和分布式<b class='flag-5'>緩存</b>

    Redis緩存預熱+緩存雪崩+緩存擊穿+緩存穿透要點簡析

    緩存預熱就是系統上線后,提前將相關的緩存數據直接加載到緩存系統。
    的頭像 發表于 12-25 09:41 ?928次閱讀
    Redis<b class='flag-5'>緩存</b>預熱+<b class='flag-5'>緩存</b>雪崩+<b class='flag-5'>緩存</b><b class='flag-5'>擊穿</b>+<b class='flag-5'>緩存</b>穿透要點簡析

    MOS管擊穿原理分析、原因及解決方法

    MOS管(金屬-氧化物-半導體場效應管)是一種常用的電子元件,在電路中起著開關、放大等重要作用。然而,在某些情況下,MOS管可能會發生擊穿現象,導致其失效。擊穿原理主要涉及電場強度、電荷積累、熱量等因素。
    的頭像 發表于 10-09 11:54 ?5847次閱讀

    mac的常見問題解決方法

    Mac常見問題解決方法 1. 系統啟動緩慢 問題描述: 啟動Mac時,系統啟動緩慢,甚至出現卡頓現象。 解決方法: 檢查啟動項目: 打開系統偏好設置中的“用戶與群組”,點擊“登錄項”,移除不必要
    的頭像 發表于 12-19 15:02 ?285次閱讀
    主站蜘蛛池模板: 亚洲狠狠综合久久| 四虎一影院区永久精品| 68日本xxxxxxx18| eeuss影院www影院夜场| 91美女啪啪| 一区二区三区在线看| 欧美视频不卡一区二区三区 | 国产女人在线视频| 波多野结衣在线观看一区二区| 在线播放国产不卡免费视频| 午夜剧j| 加勒比在线视频| 国产yw855.c免费观看网站| 日本在线亚洲| 新版bt天堂资源在线| 日韩精品一区二区三区毛片 | 色视频在线看| 久久精品亚瑟全部免费观看| 成年片色大黄全免费网址| 午夜视频在线观看国产www| 免费视频网站在线观看| 黄色的网站在线观看| 国产亚洲欧美一区| 色偷偷91久久综合噜噜噜| 快播久久| 午夜免费毛片| baoyu168成人免费视频| 青青热久免费精品视频在线观看 | 天堂网在线播放| 免费国产zzzwww色| 99免费视频观看| 国产精品午夜寂寞视频| 三级黄a| 色香蕉在线观看| 国产亚洲精品成人a在线| 亚洲综合五月天| 亚洲乱码尤物193yw在线播放| 国产性大片黄在线观看在线放| 天堂网在线播放| 国产裸体美女视频全黄| 天堂在线网站|