大型高併發與高可用緩存架構總結

數據庫和redis緩存雙寫不一致的問題

    最初級的緩存不一致問題以及解決方案
    Q:若是先修改數據庫再刪除緩存,那麼當緩存刪除失敗來,那麼會致使數據庫中是最新數據,緩存中依舊是舊數據,形成數據不一致。

     A:能夠先刪除緩存,再修改數據庫,若是刪除緩存成功可是數據庫修改失敗,那麼數據庫中是舊數據,緩存是空不會出現不一致

    比較複雜的數據不一致問題分析
    問題:對於數據發生來變動,先刪除緩存,而後去修改數據庫,此時數據庫中的數據尚未修改爲功,併發的讀請求到來去讀緩存發現是空,進而去數據庫查詢到此時的舊數據放到緩存中,而後以前對數據庫數據的修改爲功來,就會形成數據不一致

    解決方案:將數據庫與緩存更新與讀取操做進行異步串行化。當更新數據的時候,根據數據的惟一標識,將更新數據操做路由到一個jvm內部的隊列中,一個隊列對應一個工做線程,線程串行拿到隊列中的操做一條一條地執行。當執行隊列中的更新數據操做,刪除緩存,而後去更新數據庫,此時尚未完成更新的時候過來一個讀請求,讀到了空的緩存那麼能夠先將緩存更新的請求發送至路由以後的隊列中,此時會在隊列積壓,而後同步等待緩存更新完成,一個隊列中多個相同數據緩存更新請求串在一塊兒是沒有意義的,所以能夠作過濾處理。等待前面的更新數據操做完成數據庫操做以後,纔會去執行下一個緩存更新的操做,此時會從數據庫中讀取最新的數據,而後寫入緩存中,若是請求還在等待時間範圍內,不斷輪詢發現能夠取到緩存中值就能夠直接返回(此時可能會有對這個緩存數據的多個請求正在這樣處理);若是請求等待事件超過必定時長,那麼這一次的請求直接讀取數據庫中的舊值

    對於這種處理方式須要注意一些問題:
        讀請求長時阻塞:因爲讀請求進行來很是輕度的異步化,因此對超時的問題須要格外注意,超過超時時間會直接查詢DB,處理很差會對DB形成壓力,所以須要測試系統高峯期QPS來調整機器數以及對應機器上的隊列數最終決定合理的請求等待超時時間
        多實例部署的請求路由:可能這個服務會部署多個實例,那麼必須保證對應的請求都經過nginx服務器路由到相同的服務實例上
        熱點數據的路由導師請求的傾斜:由於只有在商品數據更新的時候纔會清空緩存,而後纔會致使讀寫併發,因此更新頻率不是過高的話,這個問題的影響並非特別大,可是的確可能某些機器的負載會高一些 。nginx

相關文章
相關標籤/搜索