在做系統優化時,想到了將資料進行分級存盤的思路,因為在系統中會存在一些資料,有些資料的實時性要求不高,比如一些配置資訊,基本上配置了很久才會變一次,而有一些資料實時性要求非常高,比如訂單和流水的資料,所以這里根據資料要求實時性不同將資料分為三級,
-
第1級:訂單資料和支付流水資料;這兩塊資料對實時性和精確性要求很高,所以不添加任何快取,讀寫操作將直接操作資料庫,
-
第2級:用戶相關資料;這些資料和用戶相關,具有讀多寫少的特征,所以我們使用redis進行快取,
-
第3級:支付配置資訊;這些資料和用戶無關,具有資料量小,頻繁讀,幾乎不修改的特征,所以我們使用本地記憶體進行快取,
但是只要使用到快取,無論是本地記憶體做快取還是使用 redis 做快取,那么就會存在資料同步的問題,因為配置資訊快取在記憶體中,而記憶體時無法感知到資料在資料庫的修改,這樣就會造成資料庫中的資料與快取中資料不一致的問題,接下來就討論一下關于保證快取和資料庫雙寫時的資料一致性,整理了一份Java面試寶典完整版PDF已整理成檔案
解決方案
那么我們這里列出來所有策略,并且討論他們優劣性,
-
先更新資料庫,后更新快取
-
先更新資料庫,后洗掉快取
-
先更新快取,后更新資料庫
-
先洗掉快取,后更新資料庫
先更新資料庫,后更新快取
這種場景一般是沒有人使用的,主要原因是在更新快取那一步,為什么呢?因為有的業務需求快取中存在的值并不是直接從資料庫中查出來的,有的是需要經過一系列計算來的快取值,那么這時候后你要更新快取的話其實代價是很高的,如果此時有大量的對資料庫進行寫資料的請求,但是讀請求并不多,那么此時如果每次寫請求都更新一下快取,那么性能損耗是非常大的,
舉個例子比如在資料庫中有一個值為 1 的值,此時我們有 10 個請求對其每次加一的操作,但是這期間并沒有讀操作進來,如果用了先更新資料庫的辦法,那么此時就會有十個請求對快取進行更新,會有大量的冷資料產生,如果我們不更新快取而是洗掉快取,那么在有讀請求來的時候那么就會只更新快取一次,
先更新快取,后更新資料庫
這一種情況應該不需要我們考慮了吧,和第一種情況是一樣的,
先洗掉快取,后更新資料庫
該方案也會出問題,具體出現的原因如下,
先洗掉快取,后更新資料庫
此時來了兩個請求,請求 A(更新操作) 和請求 B(查詢操作)
-
請求 A 會先洗掉 Redis 中的資料,然后去資料庫進行更新操作
-
此時請求 B 看到 Redis 中的資料時空的,會去資料庫中查詢該值,補錄到 Redis 中
-
但是此時請求 A 并沒有更新成功,或者事務還未提交
那么這時候就會產生資料庫和 Redis 資料不一致的問題,如何解決呢?其實最簡單的解決辦法就是延時雙刪的策略,
延時雙刪
但是上述的保證事務提交完以后再進行洗掉快取還有一個問題,就是如果你使用的是 Mysql 的讀寫分離的架構的話,那么其實主從同步之間也會有時間差,
主從同步時間差
此時來了兩個請求,請求 A(更新操作) 和請求 B(查詢操作)
-
請求 A 更新操作,洗掉了 Redis
-
請求主庫進行更新操作,主庫與從庫進行同步資料的操作
-
請 B 查詢操作,發現 Redis 中沒有資料
-
去從庫中拿去資料
-
此時同步資料還未完成,拿到的資料是舊資料
此時的解決辦法就是如果是對 Redis 進行填充資料的查詢資料庫操作,那么就強制將其指向主庫進行查詢,
從主庫中拿資料
先更新資料庫,后洗掉快取
問題:這一種情況也會出現問題,比如更新資料庫成功了,但是在洗掉快取的階段出錯了沒有洗掉成功,那么此時再讀取快取的時候每次都是錯誤的資料了,
先更新資料庫,后洗掉快取
此時解決方案就是利用訊息佇列進行洗掉的補償,具體的業務邏輯用語言描述如下:
-
請求 A 先對資料庫進行更新操作
-
在對 Redis 進行洗掉操作的時候發現報錯,洗掉失敗
-
此時將Redis 的 key 作為訊息體發送到訊息佇列中
-
系統接收到訊息佇列發送的訊息后再次對 Redis 進行洗掉操作
但是這個方案會有一個缺點就是會對業務代碼造成大量的侵入,深深的耦合在一起,所以這時會有一個優化的方案,我們知道對 Mysql 資料庫更新操作后再 binlog 日志中我們都能夠找到相應的操作,那么我們可以訂閱 Mysql 資料庫的 binlog 日志對快取進行操作,
利用訂閱 binlog 洗掉快取
總結
每種方案各有利弊,比如在第二種先洗掉快取,后更新資料庫這個方案我們最后討論了要更新 Redis 的時候強制走主庫查詢就能解決問題,那么這樣的操作會對業務代碼進行大量的侵入,但是不需要增加的系統,不需要增加整體的服務的復雜度,最后一種方案我們最后討論了利用訂閱 binlog 日志進行搭建獨立系統操作 Redis,這樣的缺點其實就是增加了系統復雜度,其實每一次的選擇都需要我們對于我們的業務進行評估來選擇,沒有一種技術是對于所有業務都通用的,整理了一份Java面試寶典完整版PDF已整理成檔案,沒有最好的,只有最適合我們的,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/247933.html
標籤:Java
上一篇:EasyExcel之不使用物件靈活生成Excel,并且調整行高、自動列寬與自由合并
下一篇:maven打包時排除組態檔
