案例分析|執行緒池相關故障梳理&總結
來源:阿里雲開發者
阿里妹導讀
背景
故障視角
資料庫相關
熱更新
故障案例1:某次壓測對 DB 產生瞬時 60w+ QPS 的壓力,期間同一條資料(更新 count 欄位)在事務裡大量熱點更新導致了行鎖爭搶產生慢 SQL。
故障案例2:幾個大使用者高併發操作,其中涉及單條熱點資料在事務裡的更新,排查發現單次更新耗時高達5-6秒,積壓的執行緒引起 Dubbo 對外服務執行緒池堆積,最終執行緒池滿導致無法對外服務。
線下模擬測試發現 1200 併發進行熱點資料的更新(在特定的資料庫版本和配置下),開啟事務需要1分鐘,不開啟事務需要3秒。
大表加欄位
故障案例:大表新增欄位未採用 Online DDL,在最後階段會對錶加 Metadata Lock 原子鎖,使得大量相關 SQL 鎖等待產生慢 SQL,進而快速打滿應用執行緒池。
索引沒走對(走了主鍵全表掃描)
故障案例:凌晨 3 點多突然收到報警資料庫 CPU 100%,排查發現某查詢 SQL 走了主鍵索引觸發了全表掃描(SQL 樣例為:where a= and b= and c= and d= order by id desc limit 20,當時只有 idx_a_b_e 的聯合索引),期間在資料庫運維平臺手工無差別限流 SQL 有所緩解但很快 CPU 又會飈上來,也嘗試了物理刪除一些無效資料減少資料量,多管齊下,最後透過臨時增加一個 idx_a_b_c_d 新的全欄位覆蓋的索引止血。
深分頁
故障案例:某賬號(資料量巨大)呼叫某查詢介面分頁查詢引發慢 SQL 導致資料庫連線池滿進而導致 Dubbo 執行緒池滿無法對外服務,緊急限流該賬號對該介面的呼叫後恢復。
呼叫量大
解法:系統層面需要做一定的限流策略,單機任務瓶頸時應切換到網格型任務。
故障案例2:壓測未預熱,直接一次性併發到壓測值導致執行緒池滿,導致資料庫有很多事務等待的慢 SQL。
解法:壓測應按照一定節奏逐步上量,觀察系統負載並及時暫定,而不是開局就決戰。
其他
該 Case 不涉及執行緒池滿問題,但筆者覺得有一定的代表性因此也分享下。不管是查詢還是刪除還是更新資料,不管是程式碼還是日常的 SQL 訂正,建議都增加 Limit 來兜底保護自己,縮小影響面。
技術視角
1、儘量減少遠端呼叫本身的 超時時間 以實現 fast-fail 快速失敗。一般是設定 ConnectionTimeout 即握手時間 和 SocketTimeout 即業務執行超時時間。
2、在連線池滿了以後,獲取新的連線的 超時時間 也需要設定的小一些以實現 fast-fail 快速失敗,這個是很容易忽略的一個點。如 Druid 裡設定 MaxWait,Http 連線池裡設定 ConnectionRequestTimeout。
Dubbo 執行緒池
如內部運維介面和對外服務的介面做隔離。
對外服務裡核心介面和非核心介面做隔離。
Http 連線池
故障案例:某次釋出的程式碼引入了一個 SDK,該 SDK 整合了 HttpClient,但並沒有設定 ConnectionTimeout,在某次網路抖動發生時,Http 連線池被迅速打滿,進而導致業務執行緒池滿導致服務受損。
故障案例:某 SDK 預設設定的 128,在某次壓測中發現客戶端耗時較高,但服務端耗時並無波動,排查後懷疑是 DefaultMaxPerRoute 太小導致的阻塞,調大後問題解決。
資料庫連線池 Druid
故障案例:凌晨 1 點多收到 API 成功率降低報警,排查發現部分 SQL 執行超時,原因是資料庫發生了主備切換,進一步排查發現應用側對資料庫連線池沒有設定 SocketTimeout 導致切換前的老的連線不會被超時 Kill 導致相關 SQL 執行超時,直到 900秒系統預設超時後才會斷開連線再次重連。
故障案例:在某次變更時由於程式碼有 bug 導致事務未提交,同時由於事務沒設定超時時間,導致大量相關 SQL 超時服務受損。
小插曲:之前 Druid 預設設定的 60 秒,後來筆者與作者有過溝通反饋這個預設值太長容易坑大家,後來發現已經改為了 6 秒[1]
自定義執行緒池
故障案例:Dubbo 執行緒池滿報警,排查後發現是業務程式碼裡使用了 future.get 沒有設定超時時間,同時執行緒池的拒絕策略設定的是 DiscardPolicy,會導致線上程池滿後新的任務被丟棄時 future.get 阻塞,進而導致 Dubbo 執行緒池滿服務受損。
Redis連線池
總結
fast-fail 理念
保護好自己:流控/背壓
謹慎重試
不在最上層自動重試,在單個節點裡重試
令牌桶控制重試的速率
定時、週期性的作業需要打散,分散高峰。這塊我們也遇到過類似的故障案例:
故障案例1:某客戶端曾經出過一個類似故障:客戶端的定時心跳同一秒傳送到服務端,導致服務端扛不住,此類情況需適當打散。
故障案例2:某系統大量定時任務都是整點執行,一瞬間對系統壓力過大引發線上問題,定時任務的週期需適當打散。
來自 “ ITPUB部落格 ” ,連結:https://blog.itpub.net/70024922/viewspace-3002745/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 執行緒池相關執行緒
- 執行緒池相關複習執行緒
- MYSQL執行緒池總結(一)MySql執行緒
- MySQL執行緒池總結(二)MySql執行緒
- 多執行緒:執行緒池理解和使用總結執行緒
- openGauss執行緒池相關引數執行緒
- 關於iOS多執行緒通訊的相關總結iOS執行緒
- 執行緒池關閉的小結執行緒
- Java執行緒類相關面試題與答案總結Java執行緒面試題
- Java-ThreadPool執行緒池總結Javathread執行緒
- 多執行緒(三)、執行緒池 ThreadPoolExecutor 知識點總結執行緒thread
- Java 執行緒池執行原理分析Java執行緒
- 執行緒池原始碼分析執行緒原始碼
- 執行緒池之ThreadPoolExecutor執行緒池原始碼分析筆記執行緒thread原始碼筆記
- 執行緒池之ScheduledThreadPoolExecutor執行緒池原始碼分析筆記執行緒thread原始碼筆記
- Java執行緒池二:執行緒池原理Java執行緒
- Java執行緒池原理及分析Java執行緒
- dubbo原始碼-執行緒池分析原始碼執行緒
- 淺談執行緒池(上):執行緒池的作用及CLR執行緒池執行緒
- 執行緒和執行緒池執行緒
- 多執行緒【執行緒池】執行緒
- 執行緒 執行緒池 Task執行緒
- 多執行緒相關整理執行緒
- 程式和執行緒相關執行緒
- 淺談執行緒池(下):相關試驗及注意事項執行緒
- 詳解Java執行緒池的ctl(執行緒池控制狀態)【原始碼分析】Java執行緒原始碼
- 多執行緒知識梳理(5) 執行緒池四部曲之 Executor 框架執行緒框架
- 多執行緒知識梳理(6) 執行緒池四部曲之 ThreadPoolExecutor執行緒thread
- 執行緒池執行緒
- 淺談執行緒池(中):獨立執行緒池的作用及IO執行緒池執行緒
- Java多執行緒——執行緒池Java執行緒
- netty原始碼分析-執行緒池Netty原始碼執行緒
- Java執行緒總結Java執行緒
- 【多執行緒總結(二)-執行緒安全與執行緒同步】執行緒
- java執行緒池趣味事:這不是執行緒池Java執行緒
- 執行緒池以及四種常見執行緒池執行緒
- 關於執行緒池的面試題執行緒面試題
- Java優雅關閉執行緒池Java執行緒