天天看點

大廠面試官:Redis中緩存資料更新政策有哪些?

作者:尚矽谷教育

緩存是一把雙刃劍,在帶來性能提升的同時,也會帶來一些問題。首先就是緩存一緻性的問題,因為我們把資料同時儲存在緩存和資料庫當中,當我們修改了資料庫之後,緩存是無法感覺到資料變化的,這個時候緩存中保留的就是舊資料,那麼使用者來查詢的時候查到的就是舊資料。這在很多業務場景下是不被允許的。是以今天咱們就一起讨論一下企業中常用的幾種緩存更新政策。

一、記憶體淘汰(無需編碼)

這個機制實際上是Redis用來解決記憶體不足的問題的,因為Redis是基于記憶體的,記憶體是比較珍貴的資源,在使用Redis的時候往往會設定一個記憶體上限,當Redis中的資料達到這個上限時,會觸發Redis的記憶體淘汰政策。

使用這種方式的好處就是不用自己維護緩存資料,當Redis中緩存資料大小達到我們設定的最大值時,自動淘汰部分資料,下次查詢的時候再次更新,這種政策的資料一緻性是最差的,因為觸發淘汰機制的時機是不可控的,而且就算觸發了,也不能保證會淘汰掉要更新的緩存資料。是以用這種方式解決一緻性問題完全就是看緣分了。但好處就是代碼的維護成本為0,我們隻需要修改一下配置檔案即可。

二、逾時剔除(無需編碼)

給緩存資料加上TTL過期時間,到期後自動删除緩存。下次查詢更新緩存。

手動給緩存資料加上過期時間,到期後自動删除緩存,下次查詢時更新,這種方式也有很大的機率産生資料一緻性問題,過期時間是固定的,如果一條緩存資料剛剛存入Redis,這個時候剛好更新了資料庫,那麼在這個緩存資料過期之前,資料庫和緩存中的資料都是不一緻的。這種方式比記憶體淘汰政策好那麼一點點,資料一緻性問題出現的最大時間就是我們設定的過期時間。如果業務對資料的一緻性要求不是很高,那麼我們可以設定一個在業務允許範圍内的過期時間,用這種方式實作資料最終一緻性。

三、主動更新(需要編碼)

需要我們手動編寫業務邏輯,在修改資料庫的同時,更新緩存。主動更新政策有三種

1. Cache Aside Pattern:由緩存的調用者,在更新資料庫的同時更新緩存。

2. Read/Write Through Pattern:緩存和資料庫整合為一個服務,由服務來維護一緻性。調用者調用服務,不用關心一緻性問題。

3. Write Behind Caching Pattern:調用者隻操作緩存,由其他線程異步的将緩存資料持久化到資料庫,最終保持一緻。

在企業中使用最多的主動更新政策是 Cache Aside Pattern。也就是我們自己編碼來保證資料的一緻性。

操作緩存和資料庫時有三個問題需要我們考慮:

1. 删除緩存還是更新緩存

1)更新緩存:每次更新資料庫都更新緩存,無效寫操作比較多。

這種方式的缺點很明顯,舉個例子:假如我更新了100次資料庫,然後又同時更新了100次緩存,但是在更新的時候并沒有人來查這個資料,那麼我更新這100次緩存好像也沒啥用吧,相當于前99次都是無用功,隻有最後一次才是有用的。這就是無效寫操作過多的原因。

2)删除緩存:更新資料庫時讓緩存失效,查詢時再更新緩存。(延遲加載)一般選擇這個方案

這個方案比較合理一點,可以避免過多的無效寫操作,緩存删除後,隻要沒人來查詢這條資料,資料就不會被寫入緩存,這樣就可以避免大量無效的寫操作。

2. 如何保證緩存與資料庫的操作同時成功或失敗

1)單體系統,将緩存與資料庫操作放在一個事務中。

2)分布式系統,利用TCC等分布式事務方案。

3. 先操作緩存還是資料庫

1. 先删除緩存,再操作資料庫

這種方式存在很明顯的問題,假設有兩個并發操作,線程A更新,線程B查詢。線程A先删除緩存,然後還沒來得及更新資料庫,CPU資源被線程B搶走,線程B查詢緩存發現沒有命中(因為已經被線程A删除了),查詢資料庫,然後把結果寫入到緩存中。這個時候線程A終于搶到CPU資源了,然後更新資料庫,此時就會造成資料不一緻問題。

大廠面試官:Redis中緩存資料更新政策有哪些?

2. 先操作資料庫,再删除緩存(使用最多的方式)

這種處理方式使用的頻率是最高的,因為出錯的機率非常小,隻有一種比較極端的情況才會出現資料一緻性問題。

同樣有兩個并發請求,線程A查詢、線程B更新,當線程A查詢的時候,緩存剛好失效,然後就去查詢資料庫拿到資料,在準備寫入緩存的時候,CPU資源被線程B搶走,線程B開始更新資料庫,然後删除緩存(這一步其實等于無用,因為緩存已經過期)。此時線程A再次擷取到CPU資源,然後寫入緩存,此時寫入的是更新前的舊資料,會産生資料一緻性問題。

看起來這确實也是一個問題,但是我們仔細分析一下這種情況都需要滿足哪些條件:

1. 并發讀寫操作

2. 讀緩存時,緩存剛好失效

3. 寫資料庫操作要比寫緩存快

寫資料庫是操作磁盤,寫緩存是操作記憶體的,是以不太可能會出現寫磁盤的速度快于寫記憶體的。是以使用這種方式出現資料一緻性的機率是很小的。

大廠面試官:Redis中緩存資料更新政策有哪些?

3.延時雙删政策

延遲雙删政策是分布式系統中資料庫存儲和緩存資料保持一緻性的常用政策,但它不是強一緻。其實不管哪種方案,都避免不了Redis存在髒資料的問題,隻能減輕這個問題,要想徹底解決,得要用到同步鎖和對應的業務邏輯層面解決。

前面兩種方案的不足點我們進行了分析,第二種方式的使用頻率比較高,但是也有一些小缺陷,雖然說發生的機率很低,但是這個機率到了線上會不會發生也不好說,是以就有了延時雙删政策對第二種方式做補充。

所謂延時雙删就是先進行緩存清除,再執行資料庫操作,最後(延遲N秒)再執行緩存清除。延遲N秒的時間要大于一次寫操作的時間,這個延時N秒就是了完善保證第二種政策中不足,可以保證線程A的寫緩存和線程B的修改資料庫、删除緩存都執行完畢,然後再删除緩存一次,就可以保證後面再來的查詢請求可以查詢到最新資料。

ps: 一般的延時時間設定為3S左右,具體情況要根據業務場景取最佳值。

總結

1. 記憶體淘汰:不用自己維護,利用Redis記憶體淘汰機制,自動删除部分緩存資料,這些被删除的資料在下一次被查詢時更新。這種方式一緻性最差。

2.逾時剔除:給緩存資料加上過期時間 ,到期後自動删除,下次查詢時更新,資料一緻性問題大機率會出現。維護成本比較低。

3.主動更新:編寫業務邏輯,在修改資料庫的同時更新緩存,一緻性比較好,維護成本比較高。一般采用先操作資料庫再更新緩存的方式。

一般在資料一緻性要求比較低的場景下可以使用記憶體淘汰機制,比如商城首頁的分類資訊,這些東西基本上是不會變化的。如果一緻性要求比較高,我們可以采用主動更新+逾時剔除兜底的方式來處理。

繼續閱讀