日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

背景

概述

最近團(tuán)隊(duì)里我們?cè)诿芗挠懻?redis 緩存一致性相關(guān)的問題,電商核心的域如商品、營(yíng)銷、庫(kù)存、訂單等實(shí)際上在緩存的選擇上各有特色,那么在這些差異的業(yè)務(wù)背后,我們有沒有一些最佳實(shí)踐可供參考呢?本文嘗試著來討論這個(gè)問題,并給出一些建議。

在討論之前,有兩個(gè)重點(diǎn)我們需要達(dá)成一致:

  1. 分布式場(chǎng)景下無法做到強(qiáng)一致:不同于 CPU 硬件緩存體系采用的 MESI 協(xié)議(參考資料)以及硬件的強(qiáng)時(shí)鐘控制,分布式場(chǎng)景下我們無法做到緩存與底層數(shù)據(jù)庫(kù)的強(qiáng)一致,即把緩存和數(shù)據(jù)庫(kù)的數(shù)據(jù)變更做成一個(gè)原子操作。硬件工程師設(shè)計(jì)了內(nèi)存屏障(Memory Barrier)的概念,提供給軟件開發(fā)者不同的一致性選項(xiàng)在性能與一致性上進(jìn)行權(quán)衡。
  2. 就算是達(dá)到最終一致性也很難:分布式場(chǎng)景下,要做到最終一致性,就要求緩存中存儲(chǔ)的是最新版本的數(shù)據(jù)(或者緩存為空),而且是在數(shù)據(jù)庫(kù)更新后很迅速的就要達(dá)到這個(gè)一致性的狀態(tài),要做到是極其困難的。我們會(huì)面臨硬件、軟件、通信等等組件非常多的異常情況。
一文弄懂Redis緩存一致性最佳實(shí)踐參考案例

 

緩存的一致性問題

一般化來說,我們面臨的是這樣的一個(gè)問題,如下圖所示,數(shù)據(jù)庫(kù)的數(shù)據(jù)會(huì)有 5 次更新,產(chǎn)生 6 個(gè)版本,V1~V6,圖中每個(gè)方框的長(zhǎng)度代表這個(gè)版本持續(xù)的時(shí)間。我們期望,在數(shù)據(jù)庫(kù)中的數(shù)據(jù)變化后,緩存層需要盡快的感知到并作出反應(yīng),如下圖所示,緩存層方框中的間隔代表這個(gè)時(shí)間段緩存數(shù)據(jù)不存在,V2、V3 以及 V5 版本在緩存中不存在并不會(huì)破壞我們的最終一致性要求,只要數(shù)據(jù)庫(kù)的最終版本和緩存的最終版本是相同的就可以了。

一文弄懂Redis緩存一致性最佳實(shí)踐參考案例

 

緩存是如何寫入的

緩存寫入的代碼通常情況下都是和緩存使用的代碼放在一起的,包含 4 個(gè)步驟,如下圖所示:W1 讀取緩存,W2 判斷緩存是否存在,W3 組裝緩存數(shù)據(jù)(這通常需要向數(shù)據(jù)庫(kù)進(jìn)行查詢),W4 寫入緩存。每一個(gè)步驟間可能會(huì)停頓多久是沒有辦法控制的,尤其是 W3、W4 之間的停頓最為要命,它很可能讓我們將舊版本的數(shù)據(jù)寫入到緩存中。

我們可能會(huì)想,W4 步的寫入,帶上 W2 的假設(shè),即使用 WriteIfNotExists 語(yǔ)義,會(huì)不會(huì)有所改善?

一文弄懂Redis緩存一致性最佳實(shí)踐參考案例

 

考慮如下的情形,假設(shè)有 3 個(gè)緩存寫入的并發(fā)執(zhí)行,由于短時(shí)間數(shù)據(jù)庫(kù)大量的更新,它們分別組裝的是 V1、V2、V3 版本的數(shù)據(jù)。使用 WriteIfNotExists 語(yǔ)義,其中必然有 2 個(gè)執(zhí)行會(huì)失敗,哪一個(gè)會(huì)成功根本無法保證。我們無法簡(jiǎn)單的做決策,需要再次將緩存讀取出來,然后判斷是否我們即將寫入的一樣,如果一樣那就很簡(jiǎn)單;如果不一樣的話,我們有兩種選擇:

1)將緩存刪除,讓后續(xù)別的請(qǐng)求來處理寫入。

2)使用緩存提供的原子操作,僅在我們的數(shù)據(jù)是較新版本時(shí)寫入。

一文弄懂Redis緩存一致性最佳實(shí)踐參考案例

 

如何感知數(shù)據(jù)庫(kù)的變化

數(shù)據(jù)庫(kù)的數(shù)據(jù)發(fā)生變化后,我們?nèi)绾胃兄讲⑦M(jìn)行有效的緩存管理呢?通常情況下有如下的 3 種做法:

使用代碼執(zhí)行流

通常我們會(huì)在數(shù)據(jù)庫(kù)操作完成后,執(zhí)行一些緩存操作的代碼。這種方式最大的問題是可靠性不高,應(yīng)用重啟、機(jī)器意外當(dāng)機(jī)等情況都會(huì)導(dǎo)致后續(xù)的代碼無法執(zhí)行。

使用事務(wù)消息

作為如何感知數(shù)據(jù)庫(kù)的變化的改進(jìn),在數(shù)據(jù)庫(kù)操作完成后發(fā)出事務(wù)消息,然后在消息的消費(fèi)邏輯里執(zhí)行緩存的管理操作。可靠性的問題就解決了,只是業(yè)務(wù)側(cè)要為此增加事務(wù)消息的邏輯,以及運(yùn)行成本。

使用數(shù)據(jù)變更日志

數(shù)據(jù)庫(kù)產(chǎn)品通常都支持在數(shù)據(jù)變更后產(chǎn)生變更日志,比如 MySQL 的 binlog。可以讓中間件團(tuán)隊(duì)寫一款產(chǎn)品,在接收到變更后執(zhí)行緩存的管理操作,比如阿里的精衛(wèi)。可靠性有保證,同時(shí)還可以進(jìn)行某個(gè)時(shí)間段變更日志的回放,功能就比較強(qiáng)大了。

最佳實(shí)踐一:數(shù)據(jù)庫(kù)變更后失效緩存

這是最常用和簡(jiǎn)單的方式,應(yīng)該被作為首選的方案,整體的執(zhí)行邏輯如下圖所示:

一文弄懂Redis緩存一致性最佳實(shí)踐參考案例

 

W4 步使用最基本的 put 語(yǔ)義,這里的假設(shè)是寫入較晚的請(qǐng)求往往也是攜帶的最新的數(shù)據(jù),這在大多的情形下都是成立的。D1 步使用監(jiān)聽 DB binlog 的方式來刪除緩存,即前述使用事務(wù)消息中介紹的方法。

這個(gè)方案的缺點(diǎn)是:在數(shù)據(jù)庫(kù)數(shù)據(jù)存在高并發(fā)更新且緩存讀取流量較大的情況下,會(huì)有小概率存在緩存中存儲(chǔ)的是舊版本數(shù)據(jù)的情況。

通常的解法有四種:

1)限制緩存有效時(shí)間:設(shè)定緩存的過期時(shí)間,比如 15 分鐘。即表示我們最多接受緩存在 15 分鐘的時(shí)間范圍內(nèi)是舊的。

2)小概率緩存重加載:根據(jù)流量比設(shè)定一定比例的緩存重加載,以保證大流量情況下的緩存數(shù)據(jù)的一致性。比如 1%的比例,這同時(shí)還可以幫助數(shù)據(jù)庫(kù)得到充分的預(yù)熱。

3)結(jié)合業(yè)務(wù)特點(diǎn):根據(jù)業(yè)務(wù)的特點(diǎn)做一些設(shè)計(jì),比如:

針對(duì)營(yíng)銷的場(chǎng)景:在商品詳情頁(yè)/確認(rèn)訂單頁(yè)的優(yōu)惠計(jì)算時(shí)使用緩存,而在下單時(shí)不使用緩存。這可以讓極端情況發(fā)生時(shí),不產(chǎn)生過大的業(yè)務(wù)損失。

針對(duì)庫(kù)存的場(chǎng)景:讀取到舊版本的數(shù)據(jù)只是會(huì)在商品已售罄的情況下讓多余的流量進(jìn)入到下單而已,下單時(shí)的庫(kù)存扣減是操作數(shù)據(jù)庫(kù)的,所以不會(huì)有業(yè)務(wù)上的損失。

4)兩次刪除:D1 步刪除緩存的操作執(zhí)行兩次,且中間有一定的間隔,比如 30 秒。這兩次動(dòng)作的觸發(fā)都是由“緩存管理組件”發(fā)起的,所以可以由它支持。

最佳實(shí)踐二:帶版本寫入

針對(duì)象商品信息緩存這種更新頻率低、數(shù)據(jù)一致性要求較高且緩存讀取流量很高的場(chǎng)景,通常會(huì)采用帶版本更新的方式,整體的執(zhí)行邏輯如下圖如示:

一文弄懂Redis緩存一致性最佳實(shí)踐參考案例

 

和“數(shù)據(jù)庫(kù)變更后失效緩存”方案最大的差異在 W4 步和 D1 步,需要緩存層提供帶版本寫入的 API,即僅當(dāng)寫入數(shù)據(jù)版本較新時(shí)可以寫入成功,否則寫入失敗。這同時(shí)也要求我們?cè)跀?shù)據(jù)庫(kù)增加數(shù)據(jù)版本的信息。

這個(gè)方案的最終一致性效果比較好,僅在極端情況下(新版本寫入后數(shù)據(jù)丟失了,后續(xù)舊版本的寫入就會(huì)成功)存在緩存中存儲(chǔ)的是舊版本數(shù)據(jù)的可能。在 D1 步使用寫入而不是使用刪除可以極大程度的避免這個(gè)極端情況的出現(xiàn),同時(shí)由于該方案適用于緩存讀取流量很高的場(chǎng)景,還可以避免緩存被刪除后 W3 步短時(shí)間大量請(qǐng)求穿透到 DB。

總結(jié)與展望

對(duì)于緩存與數(shù)據(jù)庫(kù)分離的場(chǎng)景,在結(jié)合了業(yè)界多家公司的實(shí)踐經(jīng)驗(yàn)以及 ROI 權(quán)衡之后,前述的兩個(gè)最佳實(shí)踐是被應(yīng)用的最為廣泛的,尤其是最佳實(shí)踐一,應(yīng)該作為我們?nèi)粘?yīng)用的首選。同時(shí),為了最大限度的避免每個(gè)最佳實(shí)踐背后可能發(fā)生的不一致性問題,我們還需要切合業(yè)務(wù)的特點(diǎn),在關(guān)鍵的場(chǎng)景上做一些保障一致性的設(shè)計(jì)(比如前述的營(yíng)銷在下單時(shí)使用數(shù)據(jù)庫(kù)讀而不是緩存讀),這也顯得尤為重要(畢竟如“背景”中所述,并不存在完美的技術(shù)方案)。

除了緩存與數(shù)據(jù)庫(kù)分離的方案,還有兩個(gè)業(yè)界已經(jīng)應(yīng)用的方案也值得我們借鑒:

阿里 XKV

簡(jiǎn)單來講就是在數(shù)據(jù)庫(kù)上部署一個(gè) Memcache 的 Server,它直接繞過數(shù)據(jù)庫(kù)層直接訪問存儲(chǔ)引擎層(如:InnoDB),同時(shí)使用 KV client 來進(jìn)行數(shù)據(jù)的訪問。它的特點(diǎn)是數(shù)據(jù)實(shí)際上與數(shù)據(jù)庫(kù)是強(qiáng)一致的,性能可以比使用 SQL 訪問數(shù)據(jù)庫(kù)提升 5~10 倍。缺點(diǎn)也很明顯,只能通過主鍵或者唯一鍵來訪問數(shù)據(jù)(這只是相對(duì) SQL 來說的,大多數(shù)緩存本來也就是 KV 訪問協(xié)議)。

騰訊 DCache

介紹資料。不用自行維護(hù)緩存與數(shù)據(jù)庫(kù)兩套存儲(chǔ),給開發(fā)人員統(tǒng)一的一套數(shù)據(jù)視圖,由 DCache 在緩存更新后自行持久化數(shù)據(jù)。缺點(diǎn)是支持的數(shù)據(jù)結(jié)構(gòu)有限( key-value,k-k-row,list,set,zset ),未來也很難支持形如數(shù)據(jù)庫(kù)表一樣復(fù)雜的數(shù)據(jù)結(jié)構(gòu)。


作者:得物技術(shù)
鏈接:
https://juejin.cn/post/7051772135584301092

分享到:
標(biāo)簽:緩存 Redis
用戶無頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫(kù),初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定