<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          如何通過緩存來提升系統(tǒng)性能

          共 2798字,需瀏覽 6分鐘

           ·

          2021-08-10 01:22

          點(diǎn)擊上方“碼農(nóng)突圍”,馬上關(guān)注

          這里是碼農(nóng)充電第一站,回復(fù)“666”,獲取一份專屬大禮包

          真愛,請?jiān)O(shè)置“星標(biāo)”或點(diǎn)個(gè)“在看

          來源:blog.csdn.net/qq_36011946/article/details/104164031

          緩存

          在系統(tǒng)中最消耗性能的地方就是對數(shù)據(jù)庫的訪問了,一般來說,增、刪、改操作不會(huì)出現(xiàn)什么性能問題,除非索引太多,并且數(shù)據(jù)量有十分龐大的情況下,這三個(gè)操作才會(huì)導(dǎo)致性能問題。一般可以限制單表索引的數(shù)量來提升性能,比如單表的索引數(shù)量不能超過5個(gè)。

          絕大多數(shù)情況下,性能問題都出在查詢上,select操作提供了非常豐富的語法,這些語法包括函數(shù),子查詢,like子句,where子句等,這些查詢都是非常消耗性能的。大部分應(yīng)用都是讀多寫少的應(yīng)用,所以查詢慢的問題會(huì)被放大了,導(dǎo)致慢查詢成為了系統(tǒng)性能的瓶頸,這是就需要用到緩存來提高系統(tǒng)的性能。

          緩存為什么能提供系統(tǒng)性能?

          緩存通過減少系統(tǒng)對數(shù)據(jù)庫的訪問量來提高系統(tǒng)性能。試想一下,如果有100個(gè)請求同時(shí)請求同一個(gè)數(shù)據(jù),沒有加緩存之前,需要訪問100次數(shù)據(jù)庫,而加了緩存之后,可能只需訪問1次數(shù)據(jù)庫,剩下的99個(gè)請求的數(shù)據(jù)從緩存中取,大大的較少了數(shù)據(jù)庫的訪問量,雖然同樣需要訪問100次,但數(shù)據(jù)庫的讀取性能和緩存的讀取性能不在一個(gè)級(jí)別上,所以對系統(tǒng)性能提升顯著。為什么說可能需要訪問1次數(shù)據(jù)庫呢,這個(gè)和過期有關(guān),后面會(huì)講。

          更新模式

          既然知道了緩存對系統(tǒng)性能提升顯著,那下面先來了解一下緩存如何更新吧。

          Cache Aside(推薦)

          這應(yīng)該是最常用的更新模式了,這種模式大致流程如下:

          讀取

          • 如果緩存中沒有,則再從數(shù)據(jù)庫中讀取數(shù)據(jù),得到數(shù)據(jù)之后,放入緩存。
          • 如果緩存中有,取到后直接返回。

          更新

          • 先更新數(shù)據(jù)庫里的數(shù)據(jù),成功后,讓緩存失效。
          為什么是讓緩存失效而不是更新緩存呢?

          主要是因?yàn)閮蓚€(gè)并發(fā)寫操作導(dǎo)致臟數(shù)據(jù)。試想一下,有兩個(gè)線程A和B,分別要將資源A的值修改為1和2,線程A先到達(dá)數(shù)據(jù)庫把數(shù)據(jù)更新為1,但還沒更新緩存,由于時(shí)間片用完了,此時(shí)線程B獲得了CPU,并在這期間把數(shù)據(jù)庫資源A的值和緩存的值都更新為2,線程B結(jié)束后,線程A重新獲得CPU,執(zhí)行更新緩存,把資源A的值改為1,線程A結(jié)束。此時(shí),數(shù)據(jù)庫中A的值為2,而緩存中A的值為1,數(shù)據(jù)不一致。所以讓緩存失效就不會(huì)有這個(gè)問題,保證緩存中的數(shù)據(jù)和數(shù)據(jù)庫的保持一致。

          那是不是Cache Aside模式就不會(huì)有并發(fā)問題了呢?

          不是的。比如,一個(gè)讀操作,沒有命中緩存,就去數(shù)據(jù)的讀取數(shù)據(jù)(A=1),此時(shí)一個(gè)寫操作,更新數(shù)據(jù)庫數(shù)據(jù)(A=2)并讓緩存失效,此時(shí)讀操作把讀取到的數(shù)據(jù)(A=1)寫到緩存中,導(dǎo)致臟數(shù)據(jù)。

          這種情況理論上會(huì)出現(xiàn),但現(xiàn)實(shí)情況中出現(xiàn)的幾率極低。要這種情況出現(xiàn)必須在一個(gè)讀操作發(fā)生時(shí),有一個(gè)并發(fā)寫操作,并且既要讀操作要于寫操作寫入前讀取,又要后于寫操作寫入緩存。滿足這種條件的概率并不大。

          基于出現(xiàn)上面所描述的問題,目前有兩種比較合理的解決方案:

          • 通過2PC這種保證數(shù)據(jù)的一致性(復(fù)雜);
          • 通過降低并發(fā)時(shí)臟數(shù)據(jù)的概率,并設(shè)置合理的過期時(shí)間(簡單,但存在一定時(shí)間內(nèi)的錯(cuò)誤率,一般可以接受)。

          Read/Write Through

          在這種模式下,對于應(yīng)用程序來說,所有的讀寫請求都是直接和緩存打交道,關(guān)于數(shù)據(jù)庫的數(shù)據(jù)完全由緩存服務(wù)來更新(更新同步為同步操作)。

          這種模式下流程就相當(dāng)簡單了,完全就是對緩存的讀寫。

          缺點(diǎn):這種模式對緩存服務(wù)有強(qiáng)依賴性,要求緩存具備高可用性。所以應(yīng)有沒有上一種普遍。

          Write Behind Caching

          其實(shí)這個(gè)模式就是Read/Write Through的一個(gè)變種,區(qū)別就在于前者是異步更新,后者是同步更新。

          既然是異步更新數(shù)據(jù)庫,他的相應(yīng)速度比Read/Write Through還要高,并且還能合并對同一個(gè)數(shù)據(jù)的多次操作。這個(gè)有點(diǎn)像MySQL的buffer pool的刷盤操作。

          缺點(diǎn):異步就代表數(shù)據(jù)不是強(qiáng)一致性的,還存在數(shù)據(jù)丟失的風(fēng)險(xiǎn),實(shí)現(xiàn)邏輯也較為復(fù)雜。

          設(shè)計(jì)思路

          無狀態(tài)的服務(wù)

          在分布式系統(tǒng)中,無狀態(tài)的服務(wù)有利于橫向擴(kuò)展,所以緩存也應(yīng)該獨(dú)立于業(yè)務(wù)服務(wù)在外,設(shè)計(jì)成一個(gè)獨(dú)立的服務(wù),使業(yè)務(wù)服務(wù)變成無狀態(tài)的。很多公司都選擇是用Redis來搭建他們的緩存系統(tǒng),取決于其高速的讀寫性能。

          命中率

          一個(gè)緩存服務(wù)的好壞主要看命中率,一般來說,命中率保存在80%以上已經(jīng)算很高了,但我們不能為了提高命中率而把數(shù)據(jù)庫的全部數(shù)據(jù)的寫到緩存了,這個(gè)是不符合緩存的設(shè)計(jì)理念,而且需要極大的內(nèi)存空間。通常來說,應(yīng)該只有小部分熱點(diǎn)數(shù)據(jù)寫到緩存。 緩存是通過犧牲強(qiáng)一致性來換取性能的,并不是所有的業(yè)務(wù)的適合使用緩存。

          有效時(shí)間

          緩存數(shù)據(jù)的有效時(shí)間不易過短,不易過長,不易過于集中。

          • 過短,會(huì)增加數(shù)據(jù)庫訪問的次數(shù)。
          • 過長容易不使用的數(shù)據(jù)一直停留在緩存中,浪費(fèi)空間,并且一旦產(chǎn)生臟數(shù)據(jù),過程的有效時(shí)間會(huì)導(dǎo)致臟數(shù)據(jù)遲遲無法失效,進(jìn)而導(dǎo)致影響更多的業(yè)務(wù)。
          • 過于集中,會(huì)導(dǎo)致緩存雪崩。

          淘汰策略

          當(dāng)內(nèi)存不足時(shí),緩存系統(tǒng)就要按照淘汰策略,把不適合留在緩存的數(shù)據(jù)淘汰掉,騰出位置給新數(shù)據(jù)。下面就以Redis為例,給出了淘汰策略:

          • noeviction: 不刪除策略, 達(dá)到最大內(nèi)存限制時(shí), 如果需要更多內(nèi)存, 直接返回錯(cuò)誤信息(有極少數(shù)會(huì)例外, 如 DEL )。
          • allkeys-lru: 所有key通用,優(yōu)先刪除最近最少使用(less recently used ,LRU) 的 key。(推薦)
          • volatile-lru: 只限于設(shè)置了 expire 的部分,優(yōu)先刪除最近最少使用(less recently used ,LRU) 的 key。
          • allkeys-random: 所有key通用,隨機(jī)刪除一部分 key。
          • volatile-random: 只限于設(shè)置了 expire 的部分,隨機(jī)刪除一部分 key。
          • volatile-ttl: 只限于設(shè)置了 expire 的部分,優(yōu)先刪除剩余時(shí)間(time to live,TTL) 短的key。

          可根據(jù)項(xiàng)目實(shí)際情況進(jìn)行選擇。

          小結(jié)

          緩存是為了加速數(shù)據(jù)的訪問,在數(shù)據(jù)庫之上的一直機(jī)制,并非所有業(yè)務(wù)都適合使用緩存,要根據(jù)具體情況選擇更新策略和淘汰策略。

          - END -

          最近熱文

          ?  美團(tuán)面試題:hashCode 和對象的內(nèi)存地址有什么關(guān)系?
          ?  人臉識(shí)別的時(shí)候,一定要穿上衣服??!
          ?  數(shù)學(xué)女博士奧運(yùn)會(huì)摘金!沒有教練,用數(shù)學(xué)知識(shí)和計(jì)算機(jī)軟件自己訓(xùn)練,網(wǎng)友:真·學(xué)好數(shù)理化,走遍天下都不怕
          ?  我差點(diǎn)信了......

          瀏覽 41
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  五月婷婷激情在线 | 日韩欧美精品熟 | 欧美成人在线视频免费 | 91电影在线 亚洲精品 | 国产蜜臀AV |