分布式緩存

背景

在高并發(fā)的分布式的系統(tǒng)中其障,緩存是必不可少的一部分银室。沒有緩存對系統(tǒng)的加速和阻擋大量的請求直接落到系統(tǒng)的底層,系統(tǒng)是很難撐住高并發(fā)的沖擊静秆,所以分布式系統(tǒng)中緩存的設(shè)計是很重要的一環(huán)

作用

使用緩存我們得到以下收益:整體是利的

  • 加速讀寫粮揉。因為緩存通常是全內(nèi)存的巡李,比如Redis抚笔、Memcache。對內(nèi)存的直接讀寫會比傳統(tǒng)的存儲層如MySQL侨拦,性能好很多殊橙。舉個例子:同等配置單機Redis QPS可輕松上萬,MySQL則只有幾千狱从。加速讀寫之后膨蛮,響應(yīng)時間加快,相比之下系統(tǒng)的用戶體驗?zāi)艿玫礁玫奶嵘?/li>
  • 降低后端的負載季研。緩存一些復(fù)雜計算或者耗時得出的結(jié)果可以降低后端系統(tǒng)對CPU敞葛、IO、線程這些資源的需求与涡,讓系統(tǒng)運行在一個相對資源健康的環(huán)境惹谐。

但隨之以來也有一些成本:

  • 數(shù)據(jù)不一致性:緩存層與存儲層的數(shù)據(jù)存在著一定時間窗口一致,時間窗口與緩存的過期時間更新策略有關(guān)驼卖。
  • 代碼維護成本:加入緩存后氨肌,需要同時處理緩存層和存儲層的邏輯,增加了開發(fā)者維護代碼的成本酌畜。
  • 運維成本:引入緩存層怎囚,比如Redis。為保證高可用桥胞,需要做主從恳守,高并發(fā)需要做集群考婴。

產(chǎn)品

主要是redis,redis常見問題見redis文章分類

緩存讀寫策略

Cache Aside Pattern(旁路緩存模式)

Cache Aside Pattern 是我們平時使用比較多的一個緩存讀寫模式井誉,比較適合讀請求比較多的場景
寫:

  • 先更新 DB
  • 然后直接刪除 cache

讀 :

  • 從 cache 中讀取數(shù)據(jù)蕉扮,讀取到就直接返回
  • cache 中讀取不到的話,就從 DB 中讀取數(shù)據(jù)返回
  • 再把數(shù)據(jù)放到 cache 中

Read/Write Through Pattern(讀寫穿透)

寫(Write Through):

  • 先查 cache颗圣,cache 中不存在喳钟,直接更新 DB
  • cache 中存在,則先更新 cache在岂,然后 cache 服務(wù)自己更新 DB(同步更新 cache 和 DB)

讀(Read Through):

  • 從 cache 中讀取數(shù)據(jù)奔则,讀取到就直接返回
  • 讀取不到的話,先從 DB 加載蔽午,寫入到 cache 后返回響應(yīng)

Write Behind Pattern(異步緩存寫入)

Write Behind Pattern 和 Read/Write Through Pattern 很相似易茬,兩者都是由 cache 服務(wù)來負責(zé) cache 和 DB 的讀寫。
但是及老,兩個又有很大的不同:Read/Write Through 是同步更新 cache 和 DB抽莱,而 Write Behind Caching 則是只更新緩存,不直接更新 DB骄恶,而是改為異步批量的方式來更新 DB食铐。

數(shù)據(jù)庫緩存一致性

不一致場景

我們業(yè)務(wù)中采用的先更新數(shù)據(jù)庫,再刪緩存這種情況不存在并發(fā)問題么僧鲁?
不是的虐呻。假設(shè)這會有兩個請求,一個請求A做查詢操作寞秃,一個請求B做更新操作斟叼,那么會有如下情形產(chǎn)生
(1)緩存剛好失效
(2)請求A查詢數(shù)據(jù)庫,得一個舊值
(3)請求B將新值寫入數(shù)據(jù)庫
(4)請求B刪除緩存
(5)請求A將查到的舊值寫入緩存
但是這樣的情況很少春寿,但數(shù)據(jù)庫讀寫分離情況下出現(xiàn)不一致的情況會更高:
(1)請求B更新數(shù)據(jù)庫
(2)請求B刪除緩存
(3)請求A讀數(shù)據(jù)走從庫朗涩,此時主從還未同步,A查到舊值
(4)請求A將查到的舊值寫入緩存
以上情況都是并發(fā)情況下無法避免的绑改,除非讀寫加鎖谢床,如果無法忍受則不適合采用緩存

方案

方案并不是要完全避免數(shù)據(jù)庫緩存一致性的情況,但可以很大程度上降低數(shù)據(jù)庫緩存一致性帶來的影響

延遲雙刪

刪除緩存的同時绢淀,另起一個線程在一段時間(可以是數(shù)據(jù)庫主從延遲的時間多一些)后再次刪除緩存萤悴,可以采用的雙刪方案非常多:

  • JDK延遲線程池ScheduledThreadPoolExecutor
  • MQ消息隊列
  • Canal監(jiān)聽+MQ消息隊列

緩存問題

緩存穿透

一般的緩存系統(tǒng),都是按照key去緩存查詢皆的,如果不存在對應(yīng)的value覆履,就應(yīng)該去后端系統(tǒng)查找(比如DB)。如果key對應(yīng)的value是一定不存在的,并且對該key并發(fā)請求量很大硝全,就會對后端系統(tǒng)造成很大的壓力栖雾。這就叫做緩存穿透。

解決:
1伟众、對查詢結(jié)果為空的情況也進行緩存析藕,設(shè)置一個較短的過期時間
2、布隆過濾器:有誤判率凳厢,會將不存在的誤判為存在账胧,不建議使用

緩存擊穿

某些熱點緩存數(shù)據(jù)突然過期,同一時刻大量請求同時進入DB先紫,對數(shù)據(jù)庫造成極大壓力

解決:
1治泥、熱點數(shù)據(jù)不過期
2、后臺定時任務(wù)刷新
3遮精、分布式鎖只允許一個線程請求DB并刷新緩存

緩存雪崩

當(dāng)緩存服務(wù)器重啟或者大量緩存集中在某一個時間段失效居夹,這樣在失效的時候,也會給后端系統(tǒng)(比如DB)帶來很大壓力本冲。

解決:
1:在緩存失效后准脂,通過加鎖或者隊列來控制讀數(shù)據(jù)庫寫緩存的線程數(shù)量。比如對某個key只允許一個線程查詢數(shù)據(jù)和寫緩存檬洞,其他線程等待狸膏。
2:不同的key,設(shè)置不同的過期時間疮胖,讓緩存失效的時間點盡量均勻环戈。


image.png

布隆過濾器

如何判斷一個元素是不是在一個集合里

如果想判斷一個元素是不是在一個集合里闷板,一般想到的是將集合中所有元素保存起來澎灸,然后通過比較確定。鏈表遮晚、樹性昭、散列表(又叫哈希表,Hash table)等等數(shù)據(jù)結(jié)構(gòu)都是這種思路县遣。但是隨著集合中元素的增加糜颠,我們需要的存儲空間越來越大。同時檢索速度也越來越慢萧求。

原理

Bloom Filter 是一種空間效率很高的隨機數(shù)據(jù)結(jié)構(gòu)其兴,Bloom filter 可以看做是對 bit-map 的擴展, 它的原理是:
當(dāng)一個元素被加入集合時,通過 K 個 Hash 函數(shù)將這個元素映射成一個位陣列(Bit array)中的 K 個點夸政,把它們置為 1元旬。檢索時,我們只要看看這些點是不是都是 1 就(大約)知道集合中有沒有它了:

如果這些點有任何一個 0,則被檢索元素一定不在匀归;
如果都是 1坑资,則被檢索元素很可能在。

優(yōu)點

It tells us that the element either definitely is not in the set or may be in the set.

它的優(yōu)點是空間效率和查詢時間都遠遠超過一般的算法穆端,布隆過濾器存儲空間和插入 / 查詢時間都是常數(shù)O(k)袱贮。另外, 散列函數(shù)相互之間沒有關(guān)系,方便由硬件并行實現(xiàn)体啰。布隆過濾器不需要存儲元素本身攒巍,在某些對保密要求非常嚴(yán)格的場合有優(yōu)勢。

缺點

但是布隆過濾器的缺點和優(yōu)點一樣明顯荒勇。誤算率是其中之一窑业。隨著存入的元素數(shù)量增加,誤算率隨之增加枕屉。但是如果元素數(shù)量太少常柄,則使用散列表足矣。
(誤判補救方法是:再建立一個小的白名單搀擂,存儲那些可能被誤判的信息西潘。)

另外,一般情況下不能從布隆過濾器中刪除元素哨颂。

誤判率

增加位數(shù)組長度喷市、哈希函數(shù)數(shù)量可減少誤判率

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市威恼,隨后出現(xiàn)的幾起案子品姓,更是在濱河造成了極大的恐慌,老刑警劉巖箫措,帶你破解...
    沈念sama閱讀 218,122評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件腹备,死亡現(xiàn)場離奇詭異,居然都是意外死亡斤蔓,警方通過查閱死者的電腦和手機植酥,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來弦牡,“玉大人友驮,你說我怎么就攤上這事〖菝蹋” “怎么了卸留?”我有些...
    開封第一講書人閱讀 164,491評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長椭豫。 經(jīng)常有香客問我耻瑟,道長买喧,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,636評論 1 293
  • 正文 為了忘掉前任匆赃,我火速辦了婚禮淤毛,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘算柳。我一直安慰自己低淡,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,676評論 6 392
  • 文/花漫 我一把揭開白布瞬项。 她就那樣靜靜地躺著蔗蹋,像睡著了一般。 火紅的嫁衣襯著肌膚如雪囱淋。 梳的紋絲不亂的頭發(fā)上猪杭,一...
    開封第一講書人閱讀 51,541評論 1 305
  • 那天,我揣著相機與錄音妥衣,去河邊找鬼皂吮。 笑死,一個胖子當(dāng)著我的面吹牛税手,可吹牛的內(nèi)容都是我干的蜂筹。 我是一名探鬼主播,決...
    沈念sama閱讀 40,292評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼芦倒,長吁一口氣:“原來是場噩夢啊……” “哼艺挪!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起兵扬,我...
    開封第一講書人閱讀 39,211評論 0 276
  • 序言:老撾萬榮一對情侶失蹤麻裳,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后器钟,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體津坑,經(jīng)...
    沈念sama閱讀 45,655評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,846評論 3 336
  • 正文 我和宋清朗相戀三年俱箱,在試婚紗的時候發(fā)現(xiàn)自己被綠了国瓮。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片灭必。...
    茶點故事閱讀 39,965評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡狞谱,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出禁漓,到底是詐尸還是另有隱情跟衅,我是刑警寧澤,帶...
    沈念sama閱讀 35,684評論 5 347
  • 正文 年R本政府宣布播歼,位于F島的核電站伶跷,受9級特大地震影響掰读,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜叭莫,卻給世界環(huán)境...
    茶點故事閱讀 41,295評論 3 329
  • 文/蒙蒙 一蹈集、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧雇初,春花似錦拢肆、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至刊橘,卻和暖如春鄙才,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背促绵。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評論 1 269
  • 我被黑心中介騙來泰國打工攒庵, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人败晴。 一個月前我還...
    沈念sama閱讀 48,126評論 3 370
  • 正文 我出身青樓叙甸,卻偏偏與公主長得像,于是被迫代替她去往敵國和親位衩。 傳聞我的和親對象是個殘疾皇子裆蒸,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,914評論 2 355

推薦閱讀更多精彩內(nèi)容