日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
不同業(yè)務(wù)場(chǎng)景該如何選擇緩存的讀寫(xiě)策略?

你可能覺(jué)得緩存的讀寫(xiě)很簡(jiǎn)單,只需要優(yōu)先讀緩存,緩存不命中就從數(shù)據(jù)庫(kù)查詢,查詢到了就回種緩存。實(shí)際上,針對(duì)不同的業(yè)務(wù)場(chǎng)景,緩存的讀寫(xiě)策略也是不同的。

專(zhuān)注于為中小企業(yè)提供成都做網(wǎng)站、網(wǎng)站制作、成都外貿(mào)網(wǎng)站建設(shè)服務(wù),電腦端+手機(jī)端+微信端的三站合一,更高效的管理,為中小企業(yè)崆峒免費(fèi)做網(wǎng)站提供優(yōu)質(zhì)的服務(wù)。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動(dòng)了超過(guò)千家企業(yè)的穩(wěn)健成長(zhǎng),幫助中小企業(yè)通過(guò)網(wǎng)站建設(shè)實(shí)現(xiàn)規(guī)模擴(kuò)充和轉(zhuǎn)變。

而我們?cè)谶x擇策略時(shí)也需要考慮諸多的因素,比如說(shuō),緩存中是否有可能被寫(xiě)入臟數(shù)據(jù),策略的讀寫(xiě)性能如何,是否存在緩存命中率下降的情況等等。

接下來(lái),我就以標(biāo)準(zhǔn)的“緩存 + 數(shù)據(jù)庫(kù)”的場(chǎng)景為例,帶你剖析經(jīng)典的緩存讀寫(xiě)策略以及它們適用的場(chǎng)景。這樣一來(lái),你就可以在日常的工作中根據(jù)不同的場(chǎng)景選擇不同的讀寫(xiě)策略。

Cache Aside(旁路緩存)策略

我們來(lái)考慮一種最簡(jiǎn)單的業(yè)務(wù)場(chǎng)景,比方說(shuō)在你的電商系統(tǒng)中有一個(gè)用戶表,表中只有 ID 和年齡兩個(gè)字段,緩存中我們以 ID 為 Key 存儲(chǔ)用戶的年齡信息。那么當(dāng)我們要把 ID 為 1 的用戶的年齡從 19 變更為 20,要如何做呢?

你可能會(huì)產(chǎn)生這樣的思路:先更新數(shù)據(jù)庫(kù)中 ID 為 1 的記錄,再更新緩存中 Key 為 1 的數(shù)據(jù)。

這個(gè)思路會(huì)造成緩存和數(shù)據(jù)庫(kù)中的數(shù)據(jù)不一致。比如,A 請(qǐng)求將數(shù)據(jù)庫(kù)中 ID 為 1 的用戶年齡從 19 變更為 20,與此同時(shí),請(qǐng)求 B 也開(kāi)始更新 ID 為 1 的用戶數(shù)據(jù),它把數(shù)據(jù)庫(kù)中記錄的年齡變更為 21,然后變更緩存中的用戶年齡為 21。緊接著,A 請(qǐng)求開(kāi)始更新緩存數(shù)據(jù),它會(huì)把緩存中的年齡變更為 20。此時(shí),數(shù)據(jù)庫(kù)中用戶年齡是 21,而緩存中的用戶年齡卻是 20。

為什么產(chǎn)生這個(gè)問(wèn)題呢?因?yàn)樽兏鼣?shù)據(jù)庫(kù)和變更緩存是兩個(gè)獨(dú)立的操作,而我們并沒(méi)有對(duì)操作做任何的并發(fā)控制。那么當(dāng)兩個(gè)線程并發(fā)更新它們的時(shí)候,就會(huì)因?yàn)閷?xiě)入順序的不同造成數(shù)據(jù)的不一致。

另外,直接更新緩存還存在另外一個(gè)問(wèn)題就是丟失更新。還是以我們的電商系統(tǒng)為例,假如電商系統(tǒng)中的賬戶表有三個(gè)字段:ID、戶名和金額,這個(gè)時(shí)候緩存中存儲(chǔ)的就不只是金額信息,而是完整的賬戶信息了。當(dāng)更新緩存中賬戶金額時(shí),你需要從緩存中查詢完整的賬戶數(shù)據(jù),把金額變更后再寫(xiě)入到緩存中。

這個(gè)過(guò)程中也會(huì)有并發(fā)的問(wèn)題,比如說(shuō)原有金額是 20,A 請(qǐng)求從緩存中讀到數(shù)據(jù),并且把金額加 1,變更成 21,在未寫(xiě)入緩存之前又有請(qǐng)求 B 也讀到緩存的數(shù)據(jù)后把金額也加 1,也變更成 21,兩個(gè)請(qǐng)求同時(shí)把金額寫(xiě)回緩存,這時(shí)緩存里面的金額是 21,但是我們實(shí)際上預(yù)期是金額數(shù)加 2,這也是一個(gè)比較大的問(wèn)題。

那我們要如何解決這個(gè)問(wèn)題呢?其實(shí),我們可以在更新數(shù)據(jù)時(shí)不更新緩存,而是刪除緩存中的數(shù)據(jù),在讀取數(shù)據(jù)時(shí),發(fā)現(xiàn)緩存中沒(méi)了數(shù)據(jù)之后,再?gòu)臄?shù)據(jù)庫(kù)中讀取數(shù)據(jù),更新到緩存中。

這個(gè)策略就是我們使用緩存最常見(jiàn)的策略,Cache Aside 策略(也叫旁路緩存策略),這個(gè)策略數(shù)據(jù)以數(shù)據(jù)庫(kù)中的數(shù)據(jù)為準(zhǔn),緩存中的數(shù)據(jù)是按需加載的。它可以分為讀策略和寫(xiě)策略,其中讀策略的步驟是:

  • 從緩存中讀取數(shù)據(jù);
  • 如果緩存命中,則直接返回?cái)?shù)據(jù);
  • 如果緩存不命中,則從數(shù)據(jù)庫(kù)中查詢數(shù)據(jù);
  • 查詢到數(shù)據(jù)后,將數(shù)據(jù)寫(xiě)入到緩存中,并且返回給用戶。

寫(xiě)策略的步驟是:

  • 更新數(shù)據(jù)庫(kù)中的記錄;
  • 刪除緩存記錄。

你也許會(huì)問(wèn)了,在寫(xiě)策略中,能否先刪除緩存,后更新數(shù)據(jù)庫(kù)呢?答案是不行的,因?yàn)檫@樣也有可能出現(xiàn)緩存數(shù)據(jù)不一致的問(wèn)題,我以用戶表的場(chǎng)景為例解釋一下。

假設(shè)某個(gè)用戶的年齡是 20,請(qǐng)求 A 要更新用戶年齡為 21,所以它會(huì)刪除緩存中的內(nèi)容。這時(shí),另一個(gè)請(qǐng)求 B 要讀取這個(gè)用戶的年齡,它查詢緩存發(fā)現(xiàn)未命中后,會(huì)從數(shù)據(jù)庫(kù)中讀取到年齡為 20,并且寫(xiě)入到緩存中,然后請(qǐng)求 A 繼續(xù)更改數(shù)據(jù)庫(kù),將用戶的年齡更新為 21,這就造成了緩存和數(shù)據(jù)庫(kù)的不一致。

那么像 Cache Aside 策略這樣先更新數(shù)據(jù)庫(kù),后刪除緩存就沒(méi)有問(wèn)題了嗎?其實(shí)在理論上還是有缺陷的。

假如某個(gè)用戶數(shù)據(jù)在緩存中不存在,請(qǐng)求 A 讀取數(shù)據(jù)時(shí)從數(shù)據(jù)庫(kù)中查詢到年齡為 20,在未寫(xiě)入緩存中時(shí)另一個(gè)請(qǐng)求 B 更新數(shù)據(jù)。它更新數(shù)據(jù)庫(kù)中的年齡為 21,并且清空緩存。這時(shí)請(qǐng)求 A 把從數(shù)據(jù)庫(kù)中讀到的年齡為 20 的數(shù)據(jù)寫(xiě)入到緩存中,造成緩存和數(shù)據(jù)庫(kù)數(shù)據(jù)不一致。

不過(guò)這種問(wèn)題出現(xiàn)的幾率并不高,原因是緩存的寫(xiě)入通常遠(yuǎn)遠(yuǎn)快于數(shù)據(jù)庫(kù)的寫(xiě)入,所以在實(shí)際中很難出現(xiàn)請(qǐng)求 B 已經(jīng)更新了數(shù)據(jù)庫(kù)并且清空了緩存,請(qǐng)求 A 才更新完緩存的情況。而一旦請(qǐng)求 A 早于請(qǐng)求 B 清空緩存之前更新了緩存,那么接下來(lái)的請(qǐng)求就會(huì)因?yàn)榫彺鏋榭斩鴱臄?shù)據(jù)庫(kù)中重新加載數(shù)據(jù),所以不會(huì)出現(xiàn)這種不一致的情況。

Cache Aside 策略是我們?nèi)粘i_(kāi)發(fā)中最經(jīng)常使用的緩存策略,不過(guò)我們?cè)谑褂脮r(shí)也要學(xué)會(huì)依情況而變。比如說(shuō)當(dāng)新注冊(cè)一個(gè)用戶,按照這個(gè)更新策略,你要寫(xiě)數(shù)據(jù)庫(kù),然后清理緩存(當(dāng)然緩存中沒(méi)有數(shù)據(jù)給你清理)??僧?dāng)我注冊(cè)用戶后立即讀取用戶信息,并且數(shù)據(jù)庫(kù)主從分離時(shí),會(huì)出現(xiàn)因?yàn)橹鲝难舆t所以讀不到用戶信息的情況。

而解決這個(gè)問(wèn)題的辦法恰恰是在插入新數(shù)據(jù)到數(shù)據(jù)庫(kù)之后寫(xiě)入緩存,這樣后續(xù)的讀請(qǐng)求就會(huì)從緩存中讀到數(shù)據(jù)了。并且因?yàn)槭切伦?cè)的用戶,所以不會(huì)出現(xiàn)并發(fā)更新用戶信息的情況。

Cache Aside 存在的最大的問(wèn)題是當(dāng)寫(xiě)入比較頻繁時(shí),緩存中的數(shù)據(jù)會(huì)被頻繁地清理,這樣會(huì)對(duì)緩存的命中率有一些影響。如果你的業(yè)務(wù)對(duì)緩存命中率有嚴(yán)格的要求,那么可以考慮兩種解決方案:

  • 一種做法是在更新數(shù)據(jù)時(shí)也更新緩存,只是在更新緩存前先加一個(gè)分布式鎖,因?yàn)檫@樣在同一時(shí)間只允許一個(gè)線程更新緩存,就不會(huì)產(chǎn)生并發(fā)問(wèn)題了。當(dāng)然這么做對(duì)于寫(xiě)入的性能會(huì)有一些影響;
  • 另一種做法同樣也是在更新數(shù)據(jù)時(shí)更新緩存,只是給緩存加一個(gè)較短的過(guò)期時(shí)間,這樣即使出現(xiàn)緩存不一致的情況,緩存的數(shù)據(jù)也會(huì)很快過(guò)期,對(duì)業(yè)務(wù)的影響也是可以接受。

當(dāng)然了,除了這個(gè)策略,在計(jì)算機(jī)領(lǐng)域還有其他幾種經(jīng)典的緩存策略,它們也有各自適用的使用場(chǎng)景。

Read/Write Through(讀穿 / 寫(xiě)穿)策略

這個(gè)策略的核心原則是用戶只與緩存打交道,由緩存和數(shù)據(jù)庫(kù)通信,寫(xiě)入或者讀取數(shù)據(jù)。這就好比你在匯報(bào)工作的時(shí)候只對(duì)你的直接上級(jí)匯報(bào),再由你的直接上級(jí)匯報(bào)給他的上級(jí),你是不能越級(jí)匯報(bào)的。

Write Through 的策略是這樣的:先查詢要寫(xiě)入的數(shù)據(jù)在緩存中是否已經(jīng)存在,如果已經(jīng)存在,則更新緩存中的數(shù)據(jù),并且由緩存組件同步更新到數(shù)據(jù)庫(kù)中,如果緩存中數(shù)據(jù)不存在,我們把這種情況叫做“Write Miss(寫(xiě)失效)”。

一般來(lái)說(shuō),我們可以選擇兩種“Write Miss”方式:

  • 一個(gè)是“Write Allocate(按寫(xiě)分配)”,做法是寫(xiě)入緩存相應(yīng)位置,再由緩存組件同步更新到數(shù)據(jù)庫(kù)中;
  • 另一個(gè)是“No-write allocate(不按寫(xiě)分配)”,做法是不寫(xiě)入緩存中,而是直接更新到數(shù)據(jù)庫(kù)中。

在 Write Through 策略中,我們一般選擇“No-write allocate”方式,原因是無(wú)論采用哪種“Write Miss”方式,我們都需要同步將數(shù)據(jù)更新到數(shù)據(jù)庫(kù)中,而“No-write allocate”方式相比“Write Allocate”還減少了一次緩存的寫(xiě)入,能夠提升寫(xiě)入的性能。

Read Through 策略就簡(jiǎn)單一些,它的步驟是這樣的:先查詢緩存中數(shù)據(jù)是否存在,如果存在則直接返回,如果不存在,則由緩存組件負(fù)責(zé)從數(shù)據(jù)庫(kù)中同步加載數(shù)據(jù)。

下面是 Read Through/Write Through 策略的示意圖:

Read Through/Write Through 策略的特點(diǎn)是由緩存節(jié)點(diǎn)而非用戶來(lái)和數(shù)據(jù)庫(kù)打交道,在我們開(kāi)發(fā)過(guò)程中相比 Cache Aside 策略要少見(jiàn)一些,原因是我們經(jīng)常使用的分布式緩存組件,無(wú)論是 Memcached 還是 Redis 都不提供寫(xiě)入數(shù)據(jù)庫(kù),或者自動(dòng)加載數(shù)據(jù)庫(kù)中的數(shù)據(jù)的功能。而我們?cè)谑褂帽镜鼐彺娴臅r(shí)候可以考慮使用這種策略,比如說(shuō)在上一節(jié)中提到的本地緩存 Guava Cache 中的 Loading Cache 就有 Read Through 策略的影子。

我們看到 Write Through 策略中寫(xiě)數(shù)據(jù)庫(kù)是同步的,這對(duì)于性能來(lái)說(shuō)會(huì)有比較大的影響,因?yàn)橄啾扔趯?xiě)緩存,同步寫(xiě)數(shù)據(jù)庫(kù)的延遲就要高很多了。那么我們可否異步地更新數(shù)據(jù)庫(kù)?這就是我們接下來(lái)要提到的“Write Back”策略。

Write Back(寫(xiě)回)策略

這個(gè)策略的核心思想是在寫(xiě)入數(shù)據(jù)時(shí)只寫(xiě)入緩存,并且把緩存塊兒標(biāo)記為“臟”的。而臟塊兒只有被再次使用時(shí)才會(huì)將其中的數(shù)據(jù)寫(xiě)入到后端存儲(chǔ)中。

需要注意的是,在“Write Miss”的情況下,我們采用的是“Write Allocate”的方式,也就是在寫(xiě)入后端存儲(chǔ)的同時(shí)要寫(xiě)入緩存,這樣我們?cè)谥蟮膶?xiě)請(qǐng)求中都只需要更新緩存即可,而無(wú)需更新后端存儲(chǔ)了,我將 Write back 策略的示意圖放在了下面:

如果使用 Write Back 策略的話,讀的策略也有一些變化了。我們?cè)谧x取緩存時(shí)如果發(fā)現(xiàn)緩存命中則直接返回緩存數(shù)據(jù)。如果緩存不命中則尋找一個(gè)可用的緩存塊兒,如果這個(gè)緩存塊兒是“臟”的,就把緩存塊兒中之前的數(shù)據(jù)寫(xiě)入到后端存儲(chǔ)中,并且從后端存儲(chǔ)加載數(shù)據(jù)到緩存塊兒,如果不是臟的,則由緩存組件將后端存儲(chǔ)中的數(shù)據(jù)加載到緩存中,最后我們將緩存設(shè)置為不是臟的,返回?cái)?shù)據(jù)就好了。

發(fā)現(xiàn)了嗎?其實(shí)這種策略不能被應(yīng)用到我們常用的數(shù)據(jù)庫(kù)和緩存的場(chǎng)景中,它是計(jì)算機(jī)體系結(jié)構(gòu)中的設(shè)計(jì),比如我們?cè)谙虼疟P(pán)中寫(xiě)數(shù)據(jù)時(shí)采用的就是這種策略。無(wú)論是操作系統(tǒng)層面的 Page Cache,還是日志的異步刷盤(pán),亦或是消息隊(duì)列中消息的異步寫(xiě)入磁盤(pán),大多采用了這種策略。因?yàn)檫@個(gè)策略在性能上的優(yōu)勢(shì)毋庸置疑,它避免了直接寫(xiě)磁盤(pán)造成的隨機(jī)寫(xiě)問(wèn)題,畢竟寫(xiě)內(nèi)存和寫(xiě)磁盤(pán)的隨機(jī) I/O 的延遲相差了幾個(gè)數(shù)量級(jí)呢。

但因?yàn)榫彺嬉话闶褂脙?nèi)存,而內(nèi)存是非持久化的,所以一旦緩存機(jī)器掉電,就會(huì)造成原本緩存中的臟塊兒數(shù)據(jù)丟失。所以你會(huì)發(fā)現(xiàn)系統(tǒng)在掉電之后,之前寫(xiě)入的文件會(huì)有部分丟失,就是因?yàn)?Page Cache 還沒(méi)有來(lái)得及刷盤(pán)造成的。

當(dāng)然,你依然可以在一些場(chǎng)景下使用這個(gè)策略,在使用時(shí),我想給你的落地建議是:你在向低速設(shè)備寫(xiě)入數(shù)據(jù)的時(shí)候,可以在內(nèi)存里先暫存一段時(shí)間的數(shù)據(jù),甚至做一些統(tǒng)計(jì)匯總,然后定時(shí)地刷新到低速設(shè)備上。比如說(shuō),你在統(tǒng)計(jì)你的接口響應(yīng)時(shí)間的時(shí)候,需要將每次請(qǐng)求的響應(yīng)時(shí)間打印到日志中,然后監(jiān)控系統(tǒng)收集日志后再做統(tǒng)計(jì)。但是如果每次請(qǐng)求都打印日志無(wú)疑會(huì)增加磁盤(pán) I/O,那么不如把一段時(shí)間的響應(yīng)時(shí)間暫存起來(lái),經(jīng)過(guò)簡(jiǎn)單的統(tǒng)計(jì)平均耗時(shí),每個(gè)耗時(shí)區(qū)間的請(qǐng)求數(shù)量等等,然后定時(shí)地,批量地打印到日志中。

總結(jié)

本篇文章主要帶你了解了緩存使用的幾種策略,以及每種策略適用的使用場(chǎng)景是怎樣的。我想讓你掌握的重點(diǎn)是:

  • Cache Aside 是我們?cè)谑褂梅植际骄彺鏁r(shí)最常用的策略,你可以在實(shí)際工作中直接拿來(lái)使用。
  • Read/Write Through 和 Write Back 策略需要緩存組件的支持,所以比較適合你在實(shí)現(xiàn)本地緩存組件的時(shí)候使用;
  • Write Back 策略是計(jì)算機(jī)體系結(jié)構(gòu)中的策略,不過(guò)寫(xiě)入策略中的只寫(xiě)緩存,異步寫(xiě)入后端存儲(chǔ)的策略倒是有很多的應(yīng)用場(chǎng)景。

新聞標(biāo)題:不同業(yè)務(wù)場(chǎng)景該如何選擇緩存的讀寫(xiě)策略?
網(wǎng)站URL:http://www.dlmjj.cn/article/dpsdhjs.html