1. 程式人生 > >u011878487的專欄

u011878487的專欄

快取更新策略

被動更新: 設定key過期的時間,讓其自動失效。
主動更新: 更新DB的時候,同時更新快取
一般業務都是主動更新和被動更新結合使用。

快取更新實現

  1. 呼叫者呼叫。失敗重試3次,再失敗,扔給訊息佇列非同步處理。訊息佇列從資料庫取最新的更新,保證成功
  2. DB中介軟體監聽DB變化,更新快取
利用DB中介軟體監聽DB變化(比如阿里的Canal中介軟體,點評的Puma),從而對快取進行更新。
這種辦法的一個好處就是:把快取的更新邏輯,和業務邏輯解藕。業務只更新DB,快取的更新被放在另外一個專門的系統裡面
主動更新 問題
存在一個問題:你是先更新快取,後更新DB;還是反過來?
下面分別分析以下2個場景,假設有
2個執行緒,t1, t2 (1) 先更新快取,後更新DB。假設有如下的執行系列: t1更新快取; t2讀快取,因為t1把快取更新了,導致t2沒讀到。從db中讀,然後更新快取; t1更新DB 上述操作系列會導致快取髒資料。 但是這個不更新 快取再讀都是錯的。只有等到下次更新才行。 但是更新操作總是比讀操作少 (2)先更新DB,後更新快取。假設有如下操作序列: t1更新DB t2更新DB t2更新快取; t1更新快取。
  • 1 上述操作系列會導致快取髒資料。 但是這個不更新 快取再讀都是錯的。只有等到下次更新才行。 但是更新操作總是比讀操作少

  • 2 這個出現的情況概率小點。同時更新可以加樂觀鎖 再加上快取過期失效策略,只會有部分時間不一致

  • 一句話,無論誰先誰後,只要更新快取和更新DB不是原子的,就可能導致不一致。只是從實際業務來講,一般快取也都是保持“最終一致性“,而不是和DB的強一致性。

  • 並且一般建議先更新DB,再更新快取,優先保證DB資料正確。

強一致

/分散式鎖

快取穿透

某個key,先查cache沒查到,再查db也沒有查到。 這種key的存在,會導致cache一直沒辦法命中,壓力一直打在db上面。如果訪問很高頻,可能會壓垮DB。

解決

- 當查詢DB沒查到時,往快取中寫入一個空值(預設值),這樣第2次再查,就不會打到DB上了。

快取雪崩

快取機器掛了,保證快取的可用性 解決

  • 應用內也保持應用內快取
  • 提高快取的HA。比如快取的主從複製。
  • 對DB的訪問實行限流、降級

快取併發

快取過期後將嘗試從後端資料庫獲取資料,這是一個看似合理的流程。但是,在高併發場景下,有可能多個請求併發的去從資料庫獲取資料, 對後端資料庫造成極大的衝擊,甚至導致 “雪崩”現象。此外,當某個快取key在被更新時,同時也可能被大量請求在獲取,

  • 解決 :鎖/分散式鎖 重試解決
類似“鎖”的機制,在快取更新或者過期的情況下,
先嚐試獲取到鎖,當更新或者從資料庫獲取完成後再釋放鎖,其他的請求只需要犧牲一定的等待時間,即可直接從快取中繼續獲取資料。

其他方法 不建議

由於資料庫層面的讀寫併發,引發的資料庫與快取資料不一致的問題(本質是後發生的讀請求先返回了),可能通過兩個小的改動解決:
1)修改服務Service連線池,id取模選取服務連線,能夠保證同一個資料的讀寫都落在同一個後端服務上
2)修改資料庫DB連線池,id取模選取DB連線,能夠保證同一個資料的讀寫在資料庫層面是序列的