數據庫讀寫分離主要解決高並發時,提高系統的吞吐量。因為大部分場景下都是讀多寫少。下圖是數據庫讀寫分離模型。
每次請求打到這個系統后:
- 讀請求,直接讀從庫
- 寫請求,先寫入主庫,然后主庫將數據同步到其他從庫
在高並發或者網絡狀況不理想時,寫完數據后,主庫還沒來得及將數據同步到從庫,其他讀請求去讀從庫,發現從庫中的數據仍然是舊數據。這就是讀寫分離數據庫數據不一致的根本原因。
下面給出兩種方案去解決這個問題:
緩存標記法
上圖流程:
1)A發起寫請求,更新了主庫,再在緩存中設置一個標記,代表此數據已經更新,標記格式( 用戶ID+業務ID+其他業務維度)
2)設置此標記,要加上過期時間,可以為預估的主庫和從庫同步延遲的時間
3)B發起讀請求的時候,先判斷此請求的業務在緩存中有沒有更新標記
4)如果存在標記,走主庫;如果沒有走從庫。
這個方案就有效了解決了數據不一致的問題。
但這個方案會有個嚴重的問題,也就是每次的讀請求都要到緩存中去判斷是否存在緩存標記,如果是單機部署用的是jvm緩存,對性能還好;但如果是集群部署緩存肯定用redis,每次讀都要和redis進行交互,這樣肯定會影響系統吞吐量。
那么解決這個問題可以用下面這個方案
本地緩存標記
上圖流程:
1)用戶A發起寫請求,更新了主庫,並在客戶端設置標記,過期時間(預估的主庫和從庫同步延遲的時間),可以使用cookie實現
2)用戶A再發起讀請求時,帶上這個cookie
3)服務器處理請求時,獲取請求傳過來的數據,看有沒有這個標記
4)有這個業務標記,走主庫;沒有走從庫。
這個方案就保證了用戶A的讀請求肯定是數據一致的,而且沒有性能問題,因為標記是本地客戶端傳過去的。
但是無法保證其他用戶讀數據是一致的,但是實際場景很少需要保持其他用戶也保持強一致。延遲個幾秒也沒問題。
引用 https://www.pianshen.com/article/99311675430/