高併發場景下數據庫和緩存一致性問題

一般而言,我們在更新數據的時候會先刪除緩存中對應的數據,再去更新數據庫的數據。這就是所謂的Cache Aside Pattern。
但是這種模式在高併發場景下還是會出現數據不一致的問題: 一個線程A在修改數據,另外一個線程B讀取數據,當A在刪除緩存的數據還沒來得及修改數據庫的時候,B發現緩存沒有數據,去數據庫讀取數據後將數據又存入緩存,這時候A完成了數據庫的修改,最後數據庫和緩存的數據就不一致了。
那麼如何解決?
將讀寫數據請求做成異步串行化的。
在內存中搞若干個隊列,將讀寫請求進行hash後進行取模分佈到各個隊列中,然後另起一些工作線程去對應的隊列進行消費,這樣讀寫請求就變成了串行化的了。當然還可以進行優化,比如隊列中有多個讀寫請求並且中間沒有寫操作,可以進行一些“去重”的操作,當然不是直接刪掉~
不過這樣做後又會帶來新的問題:
1.讀請求阻塞的時間過長。
比如讀請求前面阻塞了100個寫操作,每個寫操作要耗費10ms,那麼這個讀請求就要hang住1s,造成很大的延遲,那麼這時候可以加機器,減少每個隊列中寫操作的數量。
2.多實例部署的請求路由問題
同一個數據的讀寫操作要路由到同一臺機器上
解決:

  • 服務間按照某個請求hash路由
  • nginx進hash路由

3.熱點數據的路由問題,導致請求的傾斜
很多請求都積壓到同一臺機器的同一個隊列中。如果更新操作不多的話那也問題不大

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章