溫馨提示×

溫馨提示×

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

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

漫談Web緩存架構(gòu)

發(fā)布時間:2020-07-02 19:03:50 來源:網(wǎng)絡(luò) 閱讀:522 作者:木可大大 欄目:開發(fā)技術(shù)

計算機領(lǐng)域多處地方用到緩存,比如說為了緩解CPU和內(nèi)存之間的速度不匹配問題,我們往往通過增加一級、二級、三級緩存,CPU先從緩存中取指令,如果取不到,再從內(nèi)存中取,并更新緩存,同時,根據(jù)程序的局部性原理,使得大部分情況下緩存都會命中。

目前,Web應(yīng)用的核心數(shù)據(jù)通常存放在數(shù)據(jù)庫中,比如說用戶信息、訂單信息、交易信息等,同時,數(shù)據(jù)庫和編程語言是無關(guān)的,通過SQL交互,Java、Php等語言寫的程序需要訪問數(shù)據(jù)庫,執(zhí)行業(yè)務(wù)邏輯,展示結(jié)果給用戶。但是數(shù)據(jù)庫有一定的局限性,譬如:1.數(shù)據(jù)庫連接是非常 "昂貴 "的資源,為了復(fù)用這些資源,目前采用連接池技術(shù),2. 連接池的連接數(shù)是有限的,如果用戶過多,勢必要等待,3. 讀寫數(shù)據(jù)時需要加鎖。

通過上述介紹,我們知道一個大型系統(tǒng)中數(shù)據(jù)庫往往會成為瓶頸,我們不能每次訪問都訪問數(shù)據(jù)庫,尤其是在多用戶,大并發(fā)的情況下。面對這種情況,我們通常采用何種方法呢?在計算機行業(yè)中的所有問題,都可以通過增加一個抽象層來解決。那么,針對數(shù)據(jù)庫這個瓶頸,我們可以在應(yīng)用層和數(shù)據(jù)庫層增加一層,即緩存層

如何實現(xiàn)緩存

如果你是某某大型公司的首席架構(gòu)師,現(xiàn)在公司需要自研一套緩存系統(tǒng),你應(yīng)該怎么設(shè)計呢?我想在設(shè)計之前應(yīng)該想好以下幾個問題:

  1. 緩存里放什么格式的數(shù)據(jù)?
  2. 應(yīng)用程序(客戶端)如何訪問緩存?
  3. 緩存空間被應(yīng)用程序用完了怎么辦?
  4. 要不要支持分布式存儲(數(shù)據(jù)的分片),怎么實現(xiàn)?
1. 緩存里放什么格式的數(shù)據(jù)?

目前常見的數(shù)據(jù)格式有序列化對象、XML、JSON、字符串(key,value)和基本的數(shù)據(jù)結(jié)構(gòu),其中針對Java語言的序列化對象有序列化和反序列化,而Google研發(fā)的protobuf是和語言無關(guān)的,比如說Python將某對象序列化,Java能將這個對象進行反序列化。

2. 應(yīng)用程序如何訪問緩存

考慮到公司有很多后端小組,并且使用不同的編程語言,這就要求我們自研的緩存系統(tǒng)應(yīng)該和編程語言無關(guān),基于此,我們需要制定一套協(xié)議來支持各種語言。客戶端如何使用這套協(xié)議?最常見的就是客戶端/服務(wù)器模型。首先,服務(wù)器監(jiān)聽請求;接著,客戶端發(fā)送請求,獲得響應(yīng),其中客戶端發(fā)送的請求就是協(xié)議;最后,基于Socket通信。比如說:set 'name' 'mukedada'、get name。

3. 緩存空間被用完了怎么辦?

緩存服務(wù)器端在啟動的時候,應(yīng)該設(shè)置緩存大小,當(dāng)緩存被沾滿時,采用LRU算法。

4. 實現(xiàn)分布式存儲

對于大型應(yīng)用服務(wù)器,單機的緩存服務(wù)器是支撐不了的。那么,就需要對緩存服務(wù)器進行水平擴展(即增刪服務(wù)器,當(dāng)活動結(jié)束后,就需要考慮刪減服務(wù)器),那么用什么算法讓數(shù)據(jù)相對平均的分配到每臺服務(wù)器?同時,這個算法應(yīng)該放在客戶端還是服務(wù)端呢?

  • 客戶端實現(xiàn)
    注意這里的客戶端指的是Web應(yīng)用服務(wù),服務(wù)器列表信息通過配置文件獲得。當(dāng)節(jié)點數(shù)發(fā)生變化時,需要讓客戶端知曉。
    漫談Web緩存架構(gòu)

它的典型應(yīng)用是Memcached,Memcached使用的是一致性Hash算法,在介紹它之前,我們先來看一下余數(shù)算法。對于用戶要存儲的(key,value),計算key的整數(shù)哈希值,然后對服務(wù)器的數(shù)目求余,這樣來確定存儲服務(wù)器。這個方法存在一個致命的問題:當(dāng)服務(wù)器個數(shù)發(fā)送變化時,余數(shù)會發(fā)生變化,這樣一來需要重新到數(shù)據(jù)庫獲取數(shù)據(jù)
為了加深大家的理解,舉個具體的實例:假設(shè)有3臺服務(wù)器0、1、2,key1、key2的hash值分別是100,99,對應(yīng)的余數(shù)分別是1和0,也就是說它們分別存放于編號為1和0的服務(wù)器中,現(xiàn)在如果增加一臺服務(wù)器3,那么它們的余數(shù)也會隨之發(fā)生變化,100%4 = 0,99%4 = 3,但是它們在0、3號服務(wù)器卻找不到對應(yīng)的數(shù)據(jù)。
漫談Web緩存架構(gòu)

為了解決余數(shù)算法存在的問題,我們的先輩們提出了分布式一致性hash算法。它思路就是當(dāng)服務(wù)器個數(shù)發(fā)生變化時,盡可能的減少影響。譬如:當(dāng)我們新增node5,只影響局部范圍內(nèi)的key,而余數(shù)算法則影響全局。
漫談Web緩存架構(gòu)

但是它也存在分布不均勻的問題,導(dǎo)致有的服務(wù)器上緩存的數(shù)據(jù)多,有的少。一種方法就是虛擬節(jié)點,也就是說讓一個服務(wù)器化身為多個虛擬節(jié)點,分布到環(huán)上。Memcache采用的就是這種方法。
漫談Web緩存架構(gòu)
另一種方法就是Hash槽。Redis采用的就是這種方法,在介紹路由實現(xiàn)時會詳細介紹該方法。

  • 代理實現(xiàn)
    代理程序放在服務(wù)器端,它的典型案例有Twemproxy和Codis。它的基本思想:應(yīng)用程序向Proxy發(fā)送請求,Proxy通過一定算法計算得到數(shù)據(jù)應(yīng)該從哪個節(jié)點獲取,并且返回響應(yīng)給客戶端。為了防止Proxy出現(xiàn)單點故障,可以通過集群等方式實現(xiàn)Proxy高可用。
    漫談Web緩存架構(gòu)

  • 路由實現(xiàn)
    它的典型案例就是Redis。它的基本思想是應(yīng)用程序可以將請求發(fā)送到任意一個節(jié)點,當(dāng)節(jié)點包含該請求數(shù)據(jù),則直接返回響應(yīng)給應(yīng)用程序,當(dāng)節(jié)點不包含該請求數(shù)據(jù)時,則告訴它跳轉(zhuǎn)到其他節(jié)點中取數(shù)據(jù),其中,客戶端程序庫需要解析相應(yīng)的指令。例如:當(dāng)node1中沒有數(shù)據(jù),會讓客戶端程序訪問node3,這類似于web中的重定向,缺點: node1需要知道其他節(jié)點的數(shù)據(jù),即node1和其他節(jié)點是相互通信的。
    漫談Web緩存架構(gòu)
    首先它有16284個槽,每個node節(jié)點管理一段Hash槽,每當(dāng)新來一個請求,都對它的key值進行CRC16(key)%16384求余,最終會落到0~16383這個區(qū)間的槽中。
    漫談Web緩存架構(gòu)

但是,每當(dāng)新增一個節(jié)點時,需要從原先的每個節(jié)點中獲取hash槽,這時需要涉及數(shù)據(jù)遷移的過程。如果在數(shù)據(jù)遷移的過程中有一個用戶請求,這個時候該怎么辦?目前一種解決方法是讓node1和node4的持有相同的槽,但是設(shè)置不同的狀態(tài),例如node1的槽的狀態(tài)設(shè)置為正在遷移,而node4的狀態(tài)是正在導(dǎo)入,首先將請求交給node1,如果node1中有數(shù)據(jù)則直接返回,如果沒有則交給ndoe4。如下圖所示。
漫談Web緩存架構(gòu)

同時,我們注意到node1、node2等存在單點故障,為增加可用性,我們對每個node使用主從模式。數(shù)據(jù)首先寫入到master節(jié)點,之后有兩種方式,方式一,直接將結(jié)果返回給客戶端,然后將master節(jié)點數(shù)據(jù)同步到slave從節(jié)點中,這樣做的好處就是響應(yīng)周期短,缺點是可能存在數(shù)據(jù)不一致的情況,即master節(jié)點將結(jié)果返回給客戶端之后,還沒來得及將數(shù)據(jù)同步到slave節(jié)點中就發(fā)生故障,那么這部分?jǐn)?shù)據(jù)就會丟失。方式二,數(shù)據(jù)寫入到master節(jié)點之后,需要將數(shù)據(jù)同步到slave節(jié)點成功之后,再將結(jié)果返回給客戶端,這種方式保證了數(shù)據(jù)強一致性,但是用戶需要更長的時間來等待。
漫談Web緩存架構(gòu)

緩存擊穿問題

用戶每次訪問緩存都沒有命中,導(dǎo)致每次請求都要訪問數(shù)據(jù)庫,這就是緩存擊穿問題,出現(xiàn)這種情況導(dǎo)致緩存沒起效果,反而增加了系統(tǒng)消耗。針對這個問題,一般諸如雙十一等活動都會在活動開始之前將用戶信息預(yù)先存放到緩存中。

向AI問一下細節(jié)

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

AI