溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

怎么使用數(shù)據(jù)庫緩存技術(shù)

發(fā)布時(shí)間:2021-11-16 16:18:52 來源:億速云 閱讀:146 作者:iii 欄目:大數(shù)據(jù)

這篇文章主要講解了“怎么使用數(shù)據(jù)庫緩存技術(shù)”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“怎么使用數(shù)據(jù)庫緩存技術(shù)”吧!

緣起:為何使用緩存

在應(yīng)用對(duì)外提供服務(wù)時(shí),其穩(wěn)定性受到諸多因素影響,其中比較重要的有CPU、內(nèi)存、IO(磁盤IO、網(wǎng)絡(luò)IO)等,這些硬件資源十分寶貴,因此對(duì)于那些需要經(jīng)過復(fù)雜計(jì)算才能得到結(jié)果的,或者需要頻繁讀取磁盤數(shù)據(jù)的,最好將結(jié)果緩存起來,避免資源的重復(fù)消耗。

CPU瓶頸

如果項(xiàng)目中有很多正則表達(dá)式計(jì)算,或者某個(gè)計(jì)算結(jié)果是多次中間結(jié)果合并后才得出的,且CPU的使用率一直居高不下,那么就可以考慮是否應(yīng)該將這些結(jié)果緩存起來,根據(jù)特定Key直接獲取Value結(jié)果,減少中間鏈路的傳遞過程,減少CPU的使用率。

IO瓶頸

眾所周知,從磁盤獲取數(shù)據(jù)受到磁盤轉(zhuǎn)速、尋道速度、磁盤緩沖區(qū)大小等諸多因素影響,這些因素決定了磁盤的IOPS,同時(shí)我們也知道對(duì)于數(shù)據(jù)的讀寫來說,CPU的緩存讀寫速度> 內(nèi)存的讀寫速度>磁盤的讀寫速度。雖然磁盤內(nèi)部也配備了緩存以匹配內(nèi)存的讀寫速度,但其容量畢竟是有限的,那么當(dāng)磁盤的IOPS無法進(jìn)一步提升的時(shí)候,便會(huì)想到將數(shù)據(jù)緩存到內(nèi)存中,從而降低磁盤的訪問壓力。這一策略常被應(yīng)用于緩解DB數(shù)據(jù)庫的數(shù)據(jù)訪問壓力。

選擇本地緩存和分布式緩存的考量點(diǎn)

既然可以使用緩存來提升系統(tǒng)吞吐能力,那么緊接著遇到的問題就是選擇本地緩存,還是分布式緩存?什么時(shí)候需要使用多級(jí)緩存呢?接下來,讓我們聊一聊在使用緩存優(yōu)化項(xiàng)目的過程中,本地緩存和分布式緩存的應(yīng)用場(chǎng)景和優(yōu)缺點(diǎn)。

本地緩存的優(yōu)缺點(diǎn)和應(yīng)用場(chǎng)景

統(tǒng)一進(jìn)程帶來了以下優(yōu)勢(shì):

  • 由于本地緩存和應(yīng)用在同一個(gè)進(jìn)程中,因而其穩(wěn)定性很高,達(dá)到了和應(yīng)用同生共死的境界;

  • 由于在同一進(jìn)程中,避免了網(wǎng)絡(luò)數(shù)據(jù)傳輸帶來的消耗,所有緩存數(shù)據(jù)直接從進(jìn)程所在的內(nèi)存區(qū)域獲取即可。

強(qiáng)耦合性也會(huì)導(dǎo)致以下這些劣勢(shì):

  • 本地緩存和應(yīng)用共享一片JVM內(nèi)存,爭搶內(nèi)存資源,無法水平擴(kuò)展,且可能造成頻繁的GC,影響線上應(yīng)用的穩(wěn)定性。

  • 由于沒有持久化機(jī)制,在項(xiàng)目重啟后緩存內(nèi)數(shù)據(jù)就會(huì)丟失,對(duì)于高頻訪問數(shù)據(jù),需要對(duì)數(shù)據(jù)進(jìn)行預(yù)熱操作。

  • 多份進(jìn)程內(nèi)緩存存儲(chǔ)著同樣的數(shù)據(jù)內(nèi)容,造成內(nèi)存使用浪費(fèi)。

  • 同樣的數(shù)據(jù)存儲(chǔ)在不同的本地機(jī)器,數(shù)據(jù)變化后,很難保證數(shù)據(jù)的一致性。

結(jié)合以上優(yōu)缺點(diǎn),我們就會(huì)想到,如果有一種數(shù)據(jù)需要頻繁訪問,但一旦創(chuàng)建后就輕易不會(huì)改變,而且初始創(chuàng)建時(shí)就能預(yù)估占用的內(nèi)存空間,那么這種類型的數(shù)據(jù)無疑是最適合用本地緩存存儲(chǔ)了。

既然有了上述的應(yīng)用場(chǎng)景,我們反觀技術(shù)開發(fā)中的訴求,發(fā)現(xiàn)其實(shí)很多優(yōu)秀的框架已經(jīng)在這樣使用了,比如緩存類class的反射信息,包括field、method等。因?yàn)閏lass的數(shù)量是有限的,且內(nèi)容不會(huì)輕易改變,在使用時(shí)無需再使用反射機(jī)制,而只需要從本地緩存讀取數(shù)據(jù)即可。

分布式緩存的優(yōu)缺點(diǎn)和應(yīng)用場(chǎng)景

優(yōu)勢(shì):

  • 數(shù)據(jù)集中存儲(chǔ),消除冗余數(shù)據(jù),解決整體內(nèi)存的占用率,易于維護(hù)集群建緩存數(shù)據(jù)的一致性。

  • 緩存中間件可以對(duì)緩存進(jìn)行統(tǒng)一管理,便于水平擴(kuò)容。

劣勢(shì):

  • 依賴分布式緩存中間件穩(wěn)定性,一旦掛了,容易造成緩存雪崩;

  • 由于是跨機(jī)器獲取緩存數(shù)據(jù),因此會(huì)造成數(shù)據(jù)傳輸?shù)木W(wǎng)絡(luò)消耗,以及一些序列化/反序列化的時(shí)間開銷。

對(duì)于上述缺點(diǎn)中,網(wǎng)絡(luò)耗時(shí)等開銷是難免的,而且這些操作耗費(fèi)的時(shí)間在可接受范圍內(nèi),而對(duì)于中間件的穩(wěn)定性則可以通過服務(wù)降級(jí)、限流或者多級(jí)緩存思路來保證。我們主要看中的是它的優(yōu)點(diǎn),既然分布式緩存天然能保證緩存一致性,那么我們傾向于將需要頻繁訪問卻又經(jīng)常變化的數(shù)據(jù)存放于此。

選擇緩存框架的衡量標(biāo)準(zhǔn)

在了解了何時(shí)使用緩存以及緩存的優(yōu)缺點(diǎn)后,我們就準(zhǔn)備大刀闊斧開始升級(jí)系統(tǒng)了,可緊接著的問題也隨之出現(xiàn),對(duì)于本地緩存和分布式緩存,到底應(yīng)該使用什么框架才是最適用的呢?

現(xiàn)在的技術(shù)百花齊放,不同的技術(shù)解決的問題側(cè)重點(diǎn)也不同,對(duì)于本地緩存來說,如果無資源競(jìng)爭的代碼邏輯,可以使用HashMap,而對(duì)于有資源競(jìng)爭的多線程程序來說,則可以使用ConcurrentHashMap。但以上二者有個(gè)通病就是緩存占用只增不減,沒有緩存過期機(jī)制、也沒有緩存淘汰機(jī)制。

那么本地緩存是否有更高性能的框架呢?而對(duì)于分布式緩存,領(lǐng)域內(nèi)常用的Redis和Memcache又應(yīng)該怎樣取舍呢?本小節(jié)期望通過橫向?qū)Ρ鹊姆绞剑謩e給出一個(gè)比較通用的緩存框架方案,當(dāng)然如果有個(gè)性化需求的,也可以根據(jù)不同緩存框架的特性來取舍。

不同本地緩存框架的橫向?qū)Ρ龋缦卤硭荆?/p>

 怎么使用數(shù)據(jù)庫緩存技術(shù)

總結(jié):如果不需要淘汰算法則選擇ConcurrentHashMap,如果需要淘汰算法和一些豐富的API,推薦選擇Caffeine。

不同分布式緩存框架的橫向?qū)Ρ?,如下表所示?/p>

怎么使用數(shù)據(jù)庫緩存技術(shù)

被動(dòng)請(qǐng)求DB數(shù)據(jù),更新緩存

當(dāng)有請(qǐng)求到達(dá)且發(fā)現(xiàn)緩存沒數(shù)據(jù)時(shí),就向DB請(qǐng)求最新數(shù)據(jù)并更新緩存。這種方案完全可以看做是方案一的互斥方案,它解決的是機(jī)器CPU和內(nèi)存浪費(fèi)的問題,內(nèi)存中存儲(chǔ)的數(shù)據(jù)始終是有用的,但卻無法避免緩存失效的瞬間又突然流量峰值帶來的緩存擊穿問題,在業(yè)務(wù)上會(huì)有一定的風(fēng)險(xiǎn)。

詳情見下圖,緩存不會(huì)主動(dòng)加載數(shù)據(jù),而是根據(jù)Web請(qǐng)求懶加載數(shù)據(jù)。對(duì)于請(qǐng)求k1數(shù)據(jù)來說,發(fā)現(xiàn)緩存沒有對(duì)應(yīng)數(shù)據(jù),到DB查詢,然后放入Cache,這是常規(guī)流程;但如果有突發(fā)流量,大量請(qǐng)求同時(shí)訪問k2數(shù)據(jù),但Cache中沒有數(shù)據(jù)時(shí),請(qǐng)求就會(huì)同時(shí)落到DB上,可能壓垮數(shù)據(jù)庫。

怎么使用數(shù)據(jù)庫緩存技術(shù)

緩存過期策略

依賴時(shí)間的過期策略

  • 定時(shí)刪除

對(duì)于需要?jiǎng)h除的每個(gè)Key都配備一個(gè)定時(shí)器,元素超時(shí)時(shí)間一到就刪除元素,釋放元素占用的內(nèi)存,同時(shí)釋放定時(shí)器自身資源。其優(yōu)點(diǎn)是元素的刪除很及時(shí),但缺點(diǎn)也很明顯,比如為每個(gè)Key配備定時(shí)器肯定會(huì)消耗CPU和內(nèi)存資源,嚴(yán)重影響性能。這種策略只適合在小數(shù)據(jù)量且對(duì)過期時(shí)間又嚴(yán)格要求的場(chǎng)景能使用,一般生產(chǎn)環(huán)境都不會(huì)使用。

  • 惰性刪除

元素過期后并不會(huì)立馬刪除,而是等到該元素的下一次操作(如:訪問、更新等)才會(huì)判斷是否過期,執(zhí)行過期刪除操作。這樣的好處是節(jié)約CPU資源,因?yàn)橹挥挟?dāng)元素真的過期了,才會(huì)將其刪除,而不用單獨(dú)管理元素的生命周期。但其對(duì)內(nèi)存不友好,因?yàn)槿绻舾梢呀?jīng)過期的元素一直不被訪問的話,那就會(huì)一直占用內(nèi)存,造成內(nèi)存泄漏。

  • 定期刪除

以上兩種元素刪除策略各有優(yōu)缺點(diǎn),無非是對(duì)CPU友好,還是對(duì)內(nèi)存友好。為了結(jié)合兩者的優(yōu)點(diǎn),一方面減少了元素定時(shí)器的配備,只使用一個(gè)定時(shí)器來統(tǒng)一掃描過期元素;另一方面加速了判斷元素過期的時(shí)間間隔,不是被動(dòng)等待檢測(cè)過期,而是間隔一段時(shí)間就主動(dòng)執(zhí)行元素過期檢測(cè)任務(wù)。正是由于以上的改進(jìn)點(diǎn),此方案是元素過期檢測(cè)的慣常手段。

我們假設(shè)一個(gè)場(chǎng)景,為了保護(hù)用戶隱私,通常在用戶電話和商家電話之間,會(huì)使用一個(gè)虛擬電話作為溝通的橋梁。業(yè)務(wù)使用中,往往同一個(gè)虛擬號(hào)碼在一定時(shí)間內(nèi)是可以對(duì)相同的用戶和商家建立連接的,而當(dāng)超出這個(gè)時(shí)間后,這個(gè)虛擬號(hào)碼就不再維護(hù)映射關(guān)系了。

虛擬電話號(hào)碼的資源是有限的,自然會(huì)想到創(chuàng)建一個(gè)虛擬號(hào)碼資源池,管理虛擬號(hào)碼的創(chuàng)建和釋放。比如規(guī)定一個(gè)虛擬號(hào)碼維持的關(guān)系每次能使用15分鐘,那么過期后要釋放虛擬號(hào)碼,我們有什么方案呢?

A. 方案一:全量數(shù)據(jù)掃描,依次遍歷判斷過期時(shí)間

怎么使用數(shù)據(jù)庫緩存技術(shù)

對(duì)于DB中存儲(chǔ)的以上內(nèi)容,每天記錄都存儲(chǔ)著虛擬號(hào)碼的創(chuàng)建時(shí)間,以及經(jīng)過expire_seconds就會(huì)刪除此記錄。那么需要配備一個(gè)定時(shí)任務(wù)掃描表中的所有記錄,再判斷current_time - create_time >expire_seconds,才會(huì)刪除記錄。

如果數(shù)據(jù)量很大的情況,就會(huì)導(dǎo)致數(shù)據(jù)刪除延遲時(shí)間很長,這并不是可取的方案。那是否有方案能直接獲取到需要過期的vr_phone,然后批量過期來解決上述痛點(diǎn)呢?來看看方案二吧。

B. 方案二:存儲(chǔ)絕對(duì)過期時(shí)間+BTree索引,批量獲取過期的vr_phone列表

 怎么使用數(shù)據(jù)庫緩存技術(shù)

此時(shí)DB中不再存儲(chǔ)和過期時(shí)間相關(guān)的數(shù)據(jù),而專注于業(yè)務(wù)數(shù)據(jù)本身。對(duì)于過期的功能我們交給單層定時(shí)輪來解決。其本質(zhì)是一個(gè)環(huán)形數(shù)組,數(shù)組每一格代表1秒,每次新加入的元素放在游標(biāo)的上一格,而游標(biāo)所指向的位置就是需要過期的vr_phone列表。

執(zhí)行過程:

1、初始化:啟動(dòng)一個(gè)timer,每隔1s,在上述環(huán)形隊(duì)列中移動(dòng)一格,1->2->3...->29->750->1...有一個(gè)指針來標(biāo)識(shí)有待過期的slot數(shù)據(jù)

2、新增數(shù)據(jù):當(dāng)有一個(gè)新的vr_phone創(chuàng)建時(shí),存儲(chǔ)到指針的上一個(gè)slot中。對(duì)于有slot沖突的場(chǎng)景,可以利用鏈表解決沖突,也可以利用數(shù)組解決沖突。鏈表和數(shù)組的考量標(biāo)準(zhǔn)還是依賴于單個(gè)slot的數(shù)據(jù)長度,如果數(shù)據(jù)過長,那么存儲(chǔ)的數(shù)組會(huì)很長,則需要很大的內(nèi)存空間才能滿足,無法利用內(nèi)存碎片的空間。

3、過期數(shù)據(jù):指針每隔1秒移動(dòng)一個(gè)slot,那么指針指向的slot就是需要過期的數(shù)據(jù),因?yàn)樾略龅臄?shù)據(jù)在環(huán)形slot轉(zhuǎn)完一圈后,才會(huì)被指向到。

這樣一種算法結(jié)構(gòu),將時(shí)間和空間巧妙地結(jié)合在了一起。新增元素的時(shí)間復(fù)雜度為O(1),直接插入待批量過期的slot的上一個(gè)位置即可;獲取待刪除元素列表時(shí)間復(fù)雜度也是O(1),就是待批量過期的slot位置。流行框架Netty、Kafka都有定時(shí)輪的影子。

當(dāng)然,單層定時(shí)輪只適用于固定時(shí)間過期的場(chǎng)景,如果需要管理不同過期時(shí)間的元素,那么可以參考"多層定時(shí)輪算法",其實(shí)就是模擬現(xiàn)實(shí)世界的時(shí)針、分針、秒針的概念,建立多個(gè)單層定時(shí)輪,采用進(jìn)位和退位的思想來管理元素的過期時(shí)間。

以上各種元素過期策略各有優(yōu)缺點(diǎn),可以根據(jù)業(yè)務(wù)的訴求來取舍。比如Memcache只是用了惰性刪除,而Redis則同時(shí)使用了惰性刪除和定期刪除以結(jié)合二者的優(yōu)點(diǎn)。

依賴空間的過期策略

此處只探討最經(jīng)典的三種策略FIFO、LRU、LFU的原理及實(shí)現(xiàn)方案,對(duì)于其它改進(jìn)算法,感興趣的同學(xué)可以自行查找。

a) FIFO:先進(jìn)先出,當(dāng)空間不足時(shí),先進(jìn)入的元素將會(huì)被移除。此方案并沒有考慮元素的使用特性,可能最近頻繁訪問的一個(gè)元素會(huì)被移除,從而降低了緩存命中率。實(shí)現(xiàn):基于LinkedHashMap的鉤子函數(shù)實(shí)現(xiàn)FIFOMap。

// 鏈表頭部是最近最少被訪問的元素,需要被刪除
public class FIFOMap<K, V> extends LinkedHashMap<K, V> {
    private int maxSize;

    //LinkedHashMap每次插入數(shù)據(jù),默認(rèn)都是鏈表tail;當(dāng)accessOrder=false,元素被訪問不會(huì)移動(dòng)位置
    public FIFOMap(int maxSize) {
        super(maxSize, 0.75f, false);
        this.maxSize = maxSize;
    }

    //每次put和putAll新增元素的時(shí)候都會(huì)觸發(fā)判斷;當(dāng)下面函數(shù)=true時(shí),就刪除鏈表head元素
    @Override
    protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
        return size() > maxSize;
    }
}

b) LRU:最近最少使用算法,當(dāng)下多次被訪問的數(shù)據(jù)在以后被訪問的概率會(huì)很大,因此保留最近訪問的元素,提高命中率??梢詰?yīng)對(duì)流量突發(fā)峰值,因?yàn)榇鎯?chǔ)的池子大小是固定的,因此內(nèi)存占用不可能過多。但也有缺點(diǎn):如果一個(gè)元素訪問存在間歇規(guī)律,1分鐘前訪問1萬次,后面30秒無訪問,然后再訪問一萬次,這樣就會(huì)導(dǎo)致被刪除,降低了命中率。實(shí)現(xiàn):基于LinkedHashMap的鉤子函數(shù)實(shí)現(xiàn)LRUHashMap。

// 鏈表頭部是最近最少被訪問的元素,需要被刪除
public class LRUMap<K, V> extends LinkedHashMap<K, V> {
    private int maxSize;

    //LinkedHashMap每次插入數(shù)據(jù),默認(rèn)都是鏈表tail;當(dāng)accessOrder=true時(shí),被訪問的元素也會(huì)放到鏈表tail
    public LRUMap(int maxSize) {
        super(maxSize, 0.75f, true);
        this.maxSize = maxSize;
    }

    //每次put和putAll新增元素的時(shí)候都會(huì)觸發(fā)判斷;當(dāng)下面函數(shù)=true時(shí),就刪除鏈表head元素
    @Override
    protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
        return size() >= maxSize;
    }
}

c) LFU:最近最少頻率使用,根據(jù)數(shù)據(jù)的歷史訪問頻率來淘汰數(shù)據(jù),其核心思想是"如果數(shù)據(jù)過去被訪問多次,那么將來被訪問的頻率也更高"。這種算法針對(duì)LRU的缺點(diǎn)進(jìn)行了優(yōu)化,記錄了元素訪問的總次數(shù),選出訪問次數(shù)最小的元素進(jìn)行刪除。原本的LFU算法要求記錄所有元素的訪問次數(shù),但考慮到內(nèi)存成本,改進(jìn)后的LFU是在有限隊(duì)列中進(jìn)行淘汰。

實(shí)現(xiàn):Redis的優(yōu)先級(jí)隊(duì)列Zset實(shí)現(xiàn),Zset存儲(chǔ)元素的數(shù)量固定,Value是訪問次數(shù),超過size就刪除訪問次數(shù)最小的即可。但這種刪除策略對(duì)于有時(shí)效性的數(shù)據(jù)卻并不合適,對(duì)于排行榜類的數(shù)據(jù),如果某個(gè)歷史劇點(diǎn)擊量特別高,那么就始終不會(huì)被淘汰,新劇就沒有展示的機(jī)會(huì)。改進(jìn)方案,可以將Value存儲(chǔ)為入庫時(shí)間戳+訪問次數(shù)的值,這樣隨著時(shí)間流逝,歷史老劇就可能被淘汰。

其他影響命中率的因素

緩存穿透

對(duì)于數(shù)據(jù)庫中本就不存在的值,緩存中肯定也不會(huì)存在,此類數(shù)據(jù)的查詢一定會(huì)落到DB上。為了減少DB訪問壓力,我們期望將這些數(shù)據(jù)都可以在緩存中cover住,以下是兩種解法。

  • 解法一:緩存null值: 該方法對(duì)于元素是否存在于DB有精準(zhǔn)的判斷,可如果存在海量null值的數(shù)據(jù),則會(huì)對(duì)內(nèi)存過度占用。

  • 布隆過濾: 使用場(chǎng)景是海量數(shù)據(jù),且不要求精準(zhǔn)判斷和過濾數(shù)據(jù)。其思路是借助Hash和bit位思想,將Key值映射成若干Hash值存儲(chǔ)到bit數(shù)組中。

怎么使用數(shù)據(jù)庫緩存技術(shù)

B. 新增元素時(shí),將元素的Key根據(jù)預(yù)設(shè)的若干Hash函數(shù)解析成若干整數(shù),然后定位到bit位數(shù)組中,將對(duì)應(yīng)的bit位都改為1。

怎么使用數(shù)據(jù)庫緩存技術(shù)

C. 判斷元素是否存在,也是將元素的Key根據(jù)Hash函數(shù)解析成整數(shù),查詢?nèi)舾蒪it位的值。只要有一個(gè)bit位是0,那么這個(gè)Key肯定是新元素,不存在;如果所有bit位全都是1,那么這個(gè)Key很大概率是已經(jīng)存在的元素,但也有極小的概率是Key3經(jīng)過若干Hash函數(shù)定位到bit數(shù)組后都是Hash沖突的,可能造成誤判。

怎么使用數(shù)據(jù)庫緩存技術(shù)

緩存擊穿

緩存中原本一批數(shù)據(jù)有值,但恰好都同時(shí)過期了,此時(shí)有大量請(qǐng)求過來就都會(huì)落到DB上。避免這種風(fēng)險(xiǎn)也有兩種解法。

  • 解法一:隨機(jī)緩存失效時(shí)間: 對(duì)緩存中不同的Key設(shè)置不同的緩存失效時(shí)間,避免緩存同時(shí)失效帶來大量請(qǐng)求都落到DB上的情況。

  • 解法二:主動(dòng)加載更新緩存策略,替代緩存過期刪除策略: 在緩存失效之前就主動(dòng)到DB中加載最新的數(shù)據(jù)放到緩存中,從而避免大量請(qǐng)求落到DB的情況。

緩存雪崩

大量緩存同時(shí)過期,或者緩存中間件不可用,導(dǎo)致大量請(qǐng)求落到DB,系統(tǒng)停止響應(yīng)。解法是對(duì)緩存設(shè)置隨機(jī)失效時(shí)間,同時(shí)增加緩存中間件健康度監(jiān)測(cè)。

保證業(yè)務(wù)數(shù)據(jù)一致性的策略

在分析了影響緩存命中率的若干策略和方案后,我們結(jié)合實(shí)際開發(fā)訴求,來分析下緩存是如何降低DB的訪問壓力,以及DB和緩存中業(yè)務(wù)數(shù)據(jù)的一致性如何保證?

維護(hù)數(shù)據(jù)一致性常用的方案有兩種:先操作DB,再操作Cache;先操作Cache,再操作DB。而以上兩步操作都期望是全部成功,才能保證操作是原子性的。如果不依賴事務(wù),那么對(duì)數(shù)據(jù)怎樣操作才能保證即使流程異常中斷,對(duì)業(yè)務(wù)影響也是最小呢?

對(duì)于讀取操作

因?yàn)橹皇亲x取,不涉及數(shù)據(jù)修改,因此先讀緩存,Cache miss后,讀DB數(shù)據(jù),然后set cache就足夠通用。

對(duì)于寫入操作

先操作DB,再操作(delete/update)緩存

當(dāng)DB數(shù)據(jù)操作成功,但緩存數(shù)據(jù)(不論是delete還是update)操作失敗,就會(huì)導(dǎo)致在未來一段時(shí)間內(nèi),緩存中的數(shù)據(jù)都是歷史舊數(shù)據(jù),并沒有保證操作的原子性,無法接受。

先操作(delete/update)緩存,再操作DB

  • 第一種方案:當(dāng)update緩存成功,但操作DB失敗,雖然緩存中的數(shù)據(jù)是最新的了,但這個(gè)最新的數(shù)據(jù)最終并沒有更新到DB中,當(dāng)緩存失效后,還是會(huì)從DB中讀取到舊的數(shù)據(jù),這樣就會(huì)導(dǎo)致上下游依賴的數(shù)據(jù)出現(xiàn)錯(cuò)誤,無法接受。

  • 第二種方案:先delete緩存,再操作DB數(shù)據(jù),我們?cè)敿?xì)討論下這種方案:

  1. 如果delete就失敗了,整體操作失敗,相當(dāng)于事務(wù)回滾;

  2. 如果delete成功,但DB操作失敗,此時(shí)會(huì)引起一次cache miss,緊接著還是會(huì)從DB加載舊數(shù)據(jù),相當(dāng)于整體無操作,事務(wù)回滾,代價(jià)只是一次cache miss;

  3. 如果delete成功,且DB操作成功,那么整體成功。

感謝各位的閱讀,以上就是“怎么使用數(shù)據(jù)庫緩存技術(shù)”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對(duì)怎么使用數(shù)據(jù)庫緩存技術(shù)這一問題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI