為什麼緩存與資料庫要結合使用,使用緩存的目的是為了減少用戶請求穿透到服務端和資料庫,儘量將資源放置在離用戶更近的地方,讓用戶能夠更快得到應答。在一些活動大促、秒殺場景中,經常會面臨突然的流量爆發,造成系統的高併發訪問。例如秒殺商品的詳情頁內容提前預熱到緩存中,能緩解資料庫讀取壓力。但在高併發下,緩存 ...
為什麼緩存與資料庫要結合使用,使用緩存的目的是為了減少用戶請求穿透到服務端和資料庫,儘量將資源放置在離用戶更近的地方,讓用戶能夠更快得到應答。在一些活動大促、秒殺場景中,經常會面臨突然的流量爆發,造成系統的高併發訪問。例如秒殺商品的詳情頁內容提前預熱到緩存中,能緩解資料庫讀取壓力。但在高併發下,緩存與資料庫的使用存在兩個痛點 痛點一:在高併發訪問下,緩存的使用會引發穿透、雪崩、擊穿等問題,導致流量穿透緩存層直接壓到資料庫,如果超出了資料庫系統承載能力,會造成宕機。 痛點二:緩存與資料庫如何更新同步,才能保持兩邊數據是一致的。是先更新資料庫後更新緩存,還是先更新緩存再更新資料庫。更新完緩存後,更新資料庫失敗,怎麼辦?又或者更新資料庫後,在更新緩存時,有另一個業務線程去更新資料庫,此時更新緩存里的數據是臟數據,和資料庫不一致。 緩存穿透是用戶大量訪問一個不存在的key建引起,請求穿透到資料庫。 緩存擊穿是一個熱點key突然緩存時間到期失效,大量請求落到資料庫。 緩存雪崩是指大範圍key在同一時間失效,請求同一時間落到資料庫。 以上緩存問題,假設緩存不設置過期失效時間,請求不會回溯到資料庫,也就不會發生擊穿、雪崩等問題。緩存穿透如果訪問不存在key,直接返回空值,請求也不會回溯到資料庫。但如果不回溯到資料庫,緩存如何更新,例如在更新資料庫時,主動更新緩存。這個方案看似合理,但在更新緩存時,存在併發更新的問題,後一個更新緩存的值可能被前一個值覆蓋,這是因為緩存更新沒類似資料庫的事務隔離機制,更新操作是一個非冪等操作。 通過消息隊列將更新緩存操作串列處理,可以解決併發更新的問題,比如線程A、線程B在併發更新資料庫時,利用資料庫事務隔離機制避免臟讀、不可重覆讀。然後把數據標識寫入消息隊列,接下來消費消息隊列,再通過數據標識去讀取資料庫相應數據並刷新緩存。雖然非同步操作無法保證順序,但最終是通過數據標識獲取新的數據刷新緩存,所以不會出現前後步驟值被相互覆蓋的問題。