自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

幾種緩存更新的設(shè)計(jì)方法,值得一看

開發(fā) 前端
我們一起來看一看我們?cè)谙到y(tǒng)中緩存更新的設(shè)計(jì),因自己經(jīng)驗(yàn)有限,所以這些緩存設(shè)計(jì)來源于網(wǎng)上,我只是在這里總結(jié)一下

前言

Hello,everybody,我是asong,今天我依然聊一聊緩存,不過今天我們聊的不是面試了,我們一起來看一看我們?cè)谙到y(tǒng)中緩存更新的設(shè)計(jì),因自己經(jīng)驗(yàn)有限,所以這些緩存設(shè)計(jì)來源于網(wǎng)上,我只是在這里總結(jié)一下,有什么不對(duì)的歡迎指出。

緩存預(yù)熱 To solve 緩存冷啟動(dòng)

什么是緩存預(yù)熱呢?我們都知道平常在跑步前都要熱身,可以預(yù)防肌肉拉傷等一系例的好處。所以緩存預(yù)熱具有同樣的道理,我們的新系統(tǒng)上線后,我們可以將相關(guān)的緩存數(shù)據(jù)直接加載到緩存系統(tǒng)。這樣可以避免在用戶請(qǐng)求的時(shí)候,先去查詢數(shù)據(jù)庫,然后再將數(shù)據(jù)緩存的問題。用戶可以直接查詢事先已被預(yù)熱的緩存數(shù)據(jù)。其實(shí)緩存預(yù)熱是為了解決緩存冷啟動(dòng)問題,我們新系統(tǒng)上線后,redis集群啟動(dòng)后,沒有任何的緩存數(shù)據(jù),這就是redis的冷啟動(dòng)。

如上圖所示,如果不進(jìn)行預(yù)熱,那么Redis初識(shí)狀態(tài)數(shù)據(jù)為空,系統(tǒng)上線初期,對(duì)于高并發(fā)的流量,都會(huì)訪問到數(shù)據(jù)庫中,對(duì)數(shù)據(jù)庫造成流量的壓力。

如何解決

現(xiàn)在我們已經(jīng)知道會(huì)有緩存預(yù)熱這個(gè)問題,那么就要想一下對(duì)策咯。可以分析出以下兩點(diǎn):

  • 需要統(tǒng)計(jì)訪問頻度較高的熱點(diǎn)數(shù)據(jù)
  • 使用LRU數(shù)據(jù)刪除策略,構(gòu)建數(shù)據(jù)留存隊(duì)列

所以我們可以設(shè)計(jì)一個(gè)如下方案:

  • 首先,通過 nginx + lua 的方式,把訪問流量數(shù)據(jù)上報(bào)到 Kafka,也可以是其它的 mq 隊(duì)列。
  • 然后使用實(shí)時(shí)計(jì)算框架(如 storm 、spark streaming、flume)從 kafka 中消費(fèi)訪問流量數(shù)據(jù),實(shí)時(shí)計(jì)算出訪問頻率高的數(shù)據(jù),這里統(tǒng)計(jì)出來的可能只會(huì)有編號(hào)信息,如商品編號(hào)或博客編號(hào)等。
  • 最后,根據(jù)編號(hào)從 mysql 數(shù)據(jù)庫中查詢出具體的信息,寫入 redis,開始提供服務(wù)。

緩存更新的幾種設(shè)計(jì)

1. 先刪除緩存,在更新數(shù)據(jù)庫

雖然這是一種錯(cuò)誤方法,但是這種設(shè)計(jì)也是屬于緩存更新的一種方法,所以大家還是要知道為什么不可以這么做。還是那句話:知其所以然嘛。

這種方法就是在更新數(shù)據(jù)庫時(shí),先刪除緩存,然后在更新數(shù)據(jù)庫,而后續(xù)的操作會(huì)把數(shù)據(jù)在裝載到緩存中,這種邏輯在并發(fā)時(shí)就會(huì)先臟數(shù)據(jù),看如下圖:

我們解釋一下上圖的操作,兩個(gè)并發(fā)操作,一個(gè)是更新操作,另一個(gè)是查詢操作,更新操作刪除緩存后,查詢操作沒有命中緩存,先把老數(shù)據(jù)讀出來后放到緩存中,然后更新操作更新了數(shù)據(jù)庫。于是,在緩存中的數(shù)據(jù)還是老的數(shù)據(jù),導(dǎo)致緩存中的數(shù)據(jù)是臟的,而且還一直這樣臟下去了。所以這個(gè)設(shè)計(jì)是錯(cuò)誤的,不建議使用。

2. Cache aside

這是我們最常用的一種設(shè)計(jì)模式,其邏輯如下:

  • 查詢:程序先從cache中獲取數(shù)據(jù),有數(shù)據(jù)直接返回,沒有得到,則去數(shù)據(jù)庫中取數(shù)據(jù),成功后更新到緩存中。
  • 更新:先把數(shù)據(jù)存到數(shù)據(jù)庫中,成功后,再讓緩存失效。

這種設(shè)計(jì)正好能解決上文出現(xiàn)臟數(shù)據(jù)的問題。我們來理一下,一個(gè)是查詢操作,一個(gè)是更新操作的并發(fā),沒有了刪除cache數(shù)據(jù)的操作了,而是先更新了數(shù)據(jù)庫中的數(shù)據(jù),此時(shí),緩存依舊有效,所以,并發(fā)的查詢操作拿的是沒有更新的數(shù)據(jù),但是,更新操作馬上讓緩存的失效了,后續(xù)的查詢操作再把數(shù)據(jù)從數(shù)據(jù)庫中拉出來。而不會(huì)像文章開頭的那個(gè)邏輯產(chǎn)生的問題,后續(xù)的查詢操作一直都在取老的數(shù)據(jù)。

那么是不是這種設(shè)計(jì)就不會(huì)存在并發(fā)問題了呢?不是的,比如,一個(gè)是讀操作,但是沒有命中緩存,然后就到數(shù)據(jù)庫中取數(shù)據(jù),此時(shí)來了一個(gè)寫操作,寫完數(shù)據(jù)庫后,讓緩存失效,然后,之前的那個(gè)讀操作再把老的數(shù)據(jù)放進(jìn)去,所以,會(huì)造成臟數(shù)據(jù)。但,這個(gè)case理論上會(huì)出現(xiàn),不過,實(shí)際上出現(xiàn)的概率可能非常低,因?yàn)檫@個(gè)條件需要發(fā)生在讀緩存時(shí)緩存失效,而且并發(fā)著有一個(gè)寫操作。而實(shí)際上數(shù)據(jù)庫的寫操作會(huì)比讀操作慢得多,而且還要鎖表,而讀操作必需在寫操作前進(jìn)入數(shù)據(jù)庫操作,而又要晚于寫操作更新緩存,所有的這些條件都具備的概率基本并不大。

我們可以為緩存設(shè)置上過期時(shí)間,這樣可以有效解決這個(gè)問題。

3. Read/Write Through

這個(gè)模式其實(shí)就是將 緩存服務(wù) 作為主要的存儲(chǔ),應(yīng)用的所有讀寫請(qǐng)求都是直接與緩存服務(wù)打交道,而不管最后端的數(shù)據(jù)庫了,數(shù)據(jù)庫的數(shù)據(jù)由緩存服務(wù)來維護(hù)和更新。不過緩存中數(shù)據(jù)變更的時(shí)候是同步去更新數(shù)據(jù)庫的,在應(yīng)用的眼中只有緩存服務(wù)。

流程如下:

  • Read Through

Read Through 套路就是在查詢操作中更新緩存,也就是說,當(dāng)緩存失效的時(shí)候(過期或LRU換出),Cache Aside是由調(diào)用方負(fù)責(zé)把數(shù)據(jù)加載入緩存,而Read Through則用緩存服務(wù)自己來加載,從而對(duì)應(yīng)用方是透明的。

  • Write Through

Write Through 套路和Read Through相仿,不過是在更新數(shù)據(jù)時(shí)發(fā)生。當(dāng)有數(shù)據(jù)更新的時(shí)候,如果沒有命中緩存,直接更新數(shù)據(jù)庫,然后返回。如果命中了緩存,則更新緩存,然后再由Cache自己更新數(shù)據(jù)庫(這是一個(gè)同步操作)

這個(gè)模式的特點(diǎn)就是出現(xiàn)臟數(shù)據(jù)的概率就比較低,但是就強(qiáng)依賴緩存了,對(duì)緩存服務(wù)的穩(wěn)定性有較大要求,另外,增加新緩存節(jié)點(diǎn)時(shí)還會(huì)有初始狀態(tài)空數(shù)據(jù)問題。

4. Write Behind Caching

Write Behind Caching又叫做Write Back,就是在更新數(shù)據(jù)的時(shí)候,只更新緩存,不更新數(shù)據(jù)庫,而緩存會(huì)異步地批量更新數(shù)據(jù)庫。這個(gè)設(shè)計(jì)的好處是讓數(shù)據(jù)的I/O操作可以很快,異步的操作還可以合并對(duì)同一個(gè)數(shù)據(jù)的多次操作,性能上是非??捎^的。

但是,其帶來的問題是,數(shù)據(jù)不是強(qiáng)一致性的,而且可能會(huì)丟失。在軟件設(shè)計(jì)上,我們基本上不可能做出一個(gè)沒有缺陷的設(shè)計(jì),就像算法設(shè)計(jì)中的時(shí)間換空間,空間換時(shí)間一個(gè)道理,有時(shí)候,強(qiáng)一致性和高性能,高可用和高性性是有沖突的。軟件設(shè)計(jì)從來都是取舍Trade-Off。另外,Write Back實(shí)現(xiàn)邏輯比較復(fù)雜,因?yàn)樗枰猼rack有哪數(shù)據(jù)是被更新了的,需要刷到持久層上。操作系統(tǒng)的write back會(huì)在僅當(dāng)這個(gè)cache需要失效的時(shí)候,才會(huì)被真正持久起來,比如,內(nèi)存不夠了,或是進(jìn)程退出了等情況,這又叫l(wèi)azy write。

這個(gè)模式的特點(diǎn)就是速度很快,效率會(huì)非常高,但是數(shù)據(jù)的一致性比較差,還可能會(huì)有數(shù)據(jù)的丟失情況,實(shí)現(xiàn)邏輯也較為復(fù)雜。

總結(jié)

上面講的這幾種緩存更新設(shè)計(jì),都是一些前人使用的總結(jié),這些設(shè)計(jì)也不是完美的,這個(gè)世界上沒有完美的設(shè)計(jì),所以我們的設(shè)計(jì)多多少少會(huì)有問題,比如我們沒有考慮緩存(Cache)和持久層(Repository)的整體事務(wù)的問題。比如,更新Cache成功,更新數(shù)據(jù)庫失敗了怎么嗎?或是反過來。關(guān)于這個(gè)事,如果你需要強(qiáng)一致性,就要好好考慮怎么解決這個(gè)問題。在軟件開發(fā)或設(shè)計(jì)中,我非常建議在之前先去參考一下已有的設(shè)計(jì)和思路, 看看相應(yīng)的guideline,best practice或design pattern,吃透了已有的這些東西,再?zèng)Q定是否要重新發(fā)明輪子 。千萬不要似是而非地,想當(dāng)然的做軟件設(shè)計(jì)。

 

責(zé)任編輯:張燕妮 來源: Go語言中文網(wǎng)
相關(guān)推薦

2015-07-30 14:20:27

面試攻略

2013-05-10 16:57:26

Android開發(fā)定制皮膚

2019-05-24 10:29:29

華為咨詢

2015-03-17 10:41:36

2012-07-24 09:29:33

黑帽大會(huì)

2022-07-29 20:44:06

算力芯片數(shù)字化

2017-01-05 10:43:53

Liunx

2015-12-02 09:59:14

2019-10-17 17:45:02

判斷瀏覽器前端

2019-01-13 16:18:25

云計(jì)算多云部署Kubernetes

2011-04-20 14:48:56

掃描儀

2022-11-30 14:33:51

網(wǎng)絡(luò)安全安全技術(shù)

2019-03-26 09:20:12

蘋果 iOS系統(tǒng)

2013-07-18 13:18:12

2019-08-27 09:03:13

工具插件開發(fā)

2023-08-08 11:46:36

2019-05-23 10:46:53

深度學(xué)習(xí)代碼算法

2020-12-21 09:32:49

開發(fā)設(shè)計(jì)UI

2020-12-02 19:09:24

開源源代碼文件

2022-06-09 15:45:42

函數(shù)梯度下降
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)