通過緩存+SQL修改優(yōu)雅地優(yōu)化慢查詢
問題描述
單例數(shù)據(jù)庫模式中,后端高并發(fā)請求多(讀多寫少),導致數(shù)據(jù)庫壓力過大,關鍵接口響應變慢,嚴重影響體驗。
需求
減少接口的響應時間。
尋找解決方案
由于問題主要處在數(shù)據(jù)庫壓力過大的情況,采用兩種優(yōu)化思路優(yōu)化查詢過程:
- 使用緩存分擔數(shù)據(jù)庫壓力
- 對查詢數(shù)據(jù)庫過程做優(yōu)化
緩存方案
更新策略
使用Redis,雖然可以很好地減少數(shù)據(jù)庫的壓力,但是同時在高并發(fā)的情況下,容易出現(xiàn)數(shù)據(jù)不一致的情況,尤其是在更新數(shù)據(jù)的時候。
最常見的導致不一致的原因是雙寫操作,即高并發(fā)情況下短時間內(nèi)對數(shù)據(jù)庫進行兩次寫操作。為了最小程度地出現(xiàn)這種情況,緩存在更新策略上采用先更新數(shù)據(jù)庫后刪除緩存的方式。
對于雙寫問題,在最壞情況下,寫請求A在更新數(shù)據(jù)庫后,被寫請求B先一步更新數(shù)據(jù)庫+刪除緩存,然后A請求才刪除緩存,也不會導致后續(xù)請求讀取到錯誤的值。
對于先寫后讀,在最壞情況下,寫請求A在更新數(shù)據(jù)庫后,被讀請求C先一步在緩存讀取到舊值,然后A請求才刪除緩存,也只會影響這段時間的讀請求,刪除后的讀請求不影響。
對比其他方案(先更新緩存后更新數(shù)據(jù)庫、先刪除緩存后更新數(shù)據(jù)庫、先更新數(shù)據(jù)庫后更新緩存)在最壞情況下會導致的錯誤(更新數(shù)據(jù)庫失敗導致緩存是未知值、雙寫后數(shù)據(jù)庫變成舊值、更新緩存失敗導致緩存保存舊值)要好得多。
但是先更新數(shù)據(jù)庫后刪除緩存也不是完全安全的,除了上文提到的高并發(fā)下先寫后讀可能讀到舊值外,若刪除緩存失敗,也有可能導致讀到舊值。處理方法見下文。
緩存架構
添加緩存,勢必要修改業(yè)務代碼,如何配置架構才能把對代碼的入侵性講到最低,這里使用監(jiān)聽數(shù)據(jù)庫binlog的方法,使用中間件監(jiān)聽mysql的日志,當出現(xiàn)操作時,通知專門的模塊來修改緩存,做到修改緩存和業(yè)務邏輯解耦。
同時為了解決緩存刪除失敗的問題,當發(fā)生失敗時,發(fā)送消息至消息隊列傳遞給專門的模塊進行重試刪除。
中間件選擇:
- 緩存使用Redis
- 監(jiān)聽binlog使用canal
- 消息隊列使用RocketMQ
架構如下所示:
SQL優(yōu)化
查詢優(yōu)化可以從兩個方面進行:
- 根據(jù)高頻的查詢case,遵循最左匹配原則,設置對應的索引或聯(lián)合索引
- 通過了解業(yè)務場景,看看能否將一些小SQL合并成大SQL
通過本文的介紹,我們可以看到,優(yōu)化慢查詢并不一定需要對程序代碼進行復雜的修改。通過巧妙地運用緩存和SQL優(yōu)化手段,我們可以達到相同或者更好的效果。在實際的開發(fā)中,我們應該繼續(xù)探索和研究這些優(yōu)化方法,以提高程序的效率和穩(wěn)定性。
到此這篇關于通過緩存+SQL修改優(yōu)雅地優(yōu)化慢查詢的文章就介紹到這了,更多相關優(yōu)化慢查詢內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
5個MySQL GUI工具推薦,幫助你進行數(shù)據(jù)庫管理
這篇文章主要介紹了5個MySQL GUI工具推薦,幫助大家更好的進行MySQL數(shù)據(jù)庫管理,感興趣的朋友可以了解下2020-08-08