背景
前段時間收到運維反饋,線上Mysql數據庫凌晨時候出現慢查詢的報警,並把原始sql發了過來:
--去除了業務含義的sql
update test_user set a=1 where id=1;
表數據量200W左右,不是很大,而且是根據主鍵更新。
問題排查
- 排查Mysql數據庫
我看到sql后第一反應就是是不是數據庫出問題了,每個小時都有業務,偏偏白天業務高峰時間段正常,凌晨業務量很少時候出問題,讓運維先檢查了數據庫的狀態,反饋是數據庫正常。
- 排查業務代碼(第一次)
這塊業務代碼比較復雜,而且是別人寫的,第一次看都沒看完,直接在代碼里打印了各個模塊執行的時間,然后上線。
- 排查業務代碼(第二次)
第二天又出現慢查詢了,我趕緊下載了線上日志,發現整個方法執行時間很長,然后發現執行時間長的代碼有幾行調用其他服務的代碼,使用的是HttpClient,猜到了原因,應該是調用其他超時導致的。
說下系統整體流程,微信(A)回調我們的收銀台服務(B),收銀台更新訂單信息並調用業務服務(C)。
出問題原因是:
第一次A調用B,B鎖住記錄行並調用C,這個時候C沒有響應,導致A又發送了第二次請求。
第二次A調用B,B更新記錄時候發生死鎖,出現慢查詢。
解決方案
-
收銀台系統B接收回調的方法添加分布式鎖,保證同一時刻同一訂單只能更新一次。
-
收銀台調用業務服務使用的是HttpClient4.4,默認超時時間60秒,這么長時間如果對方沒有響應就完了,改成了5秒,超時立馬返回,不影響其他業務。
HttpClient4.4版本設置超時時間代碼如下:
HttpPost httpPost = new HttpPost(url);
RequestConfig.custom().setSocketTimeout(5000).setConnectTimeout(5000).setConnectionRequestTimeout(5000).build();
httpPost.setConfig(requestConfig);
上面設置了3個超時時間,含義如下:
setConnectTimeout:設置連接超時時間,單位毫秒。
setConnectionRequestTimeout:設置從connect Manager獲取Connection 超時時間,單位毫秒。這個屬性是新加的屬性,因為目前版本是可以共享連接池的。
setSocketTimeout:請求獲取數據的超時時間,單位毫秒。 如果訪問一個接口,多少時間內無法返回數據,就直接放棄此次調用。
最后,按照這兩個方案改造上線后,系統運行正常,問題解決。
推薦閱讀
1.用戶密碼到底要怎么加密存儲?
2.徹底理解cookie、session、token
3.阿里面試官:分別說說微信和淘寶掃碼登錄背后的實現原理?
4.一分鍾帶你了解下MyBatis的動態SQL!
5.原創 | 我是如何解決POI解析Excel出現的OOM問題的?
如果覺得文章不錯,希望可以隨手轉發或者”在看“哦,非常感謝哈!
關注下方公眾號后回復「1024」,有驚喜哦!