快取穿透導致資料庫效能不穩定

流水無情88發表於2017-03-30

事件描述 && 解決過程

  1. DAY1 19:47 業務新增一個訪問介面來增加網站的訪問量 。業務訪問量比較少,當天沒有發現問題。

2.DAY2 下午業務開發聯絡我們,發現了一些下面的錯誤:

### Error querying database.  Cause: org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is org.apache.commons.dbcp.SQLNestedException: Cannot get a connection, pool error Timeout waiting for idle object

通過 google 可以發現是MySQL 的dbcp 連線池上的連線數使用完了,新的 client 請求沒法獲取可使用的連線池,等待超時。

3.當時首先想到的是增加連線池的最大連線數,諮詢了下開發,連線數從原來的50增加到 100.

4.隨後資料庫伺服器開始出現突然的 load 飆到40+,然後瞬間降到0.1 左右,業務資料量很少,請求頻率也不高,每次報警的時候上去看了下,發現連線都不多,只有10+個使用者連線。

5.第一步確認下是不是 Linux Server 本身問題呢?聯絡 SA ,SA 大大說可能是 xfs 檔案系統的一個bug。可是資料庫系統都是統一配置的,為什麼就這個機器有問題呢?當時後面 SA 的建議是遷移走資料,機器升級。

6.隨後資料庫穩定,就沒有繼續追究,先看看連線數增加到 100 是否有效果。如果不行,考慮準備遷移走業務、升級機器。 [雖然業務量不大,但是物理機器上好幾個 MySQL 小業務,遷移都需要聯絡對應的開發,也是個辛苦活。]

7.DAY3 8:30 資料庫 load 繼續忽高忽低,DBA 接收到斷線報警,檢視監控平臺資訊,只有 cpu 的使用率也隨著 load 呈現相似變化。登入到資料庫機器上看的時候,load 變得很低,top 檢視程式的資源消耗也很低。找了一個資深的 SA 大大幫忙看了下,麻煩他確認下是不是Linux 系統問題。

8.SA 大大開了多終端,看了下 Linux機器的資訊,發現沒有啥問題,但是他在top 監控機器的過程中突然發現 MySQL 的cpu 使用率瞬間達到2000%,然後幾秒後又很低甚至消失在top 的前幾個資源程式消耗上。

9.DAY3 9:10 左右DBA[調侃他下]開始 top 和 show processlist 來實施捕捉 MySQL 的程式狀況,發現每過4-5min 左右,就會大量的出現 select now() from dual 和 select user()的請求,那個時間的相關業務連線數的確也非常高,接近100.

10.最後讓業務開發檢查下原因。

10.1 診斷期間有修改 dbpc 的配置,比如 validationQuery 從 select now() 改為 select 1, timeBetweenEvictionRunsMillis 和 minEvictableIdleTimeMillis 從1000 改為 3min ,5min 。 [效果不大]

10.2 最後是開發那邊對快取上了 lock,避免快取穿透,效果明顯。

解釋:如果多個client發現快取資料失效,只允許一個執行緒從資料庫讀取資料,放置到快取供後續的請求讀取。這樣可以有效的避免當快取失效的時候[開發設定5min],所有的 client 請求都下發到 DB ,造成DB 瞬間的請求處理請求數量增加,從而 cpu 和load 自然暴漲起來了。

事後總結

雖然這個事情最後是解決了,但是我發現這次解決問題的思路還是有些問題的。我就馬後炮的總結下診斷事故的正確姿勢。

1.業務開發給出錯誤以後,DBA 首先看看出錯日誌的原因。比如這次是連線池等待資源超時。

2.DBA 要連線到資料庫機器上,檢視當前的資料庫資源使用情況,對應例項的連線情況,是否有阻塞的SQL等,確保其他業務還能正常使用。[一個 MySQL 例項可能有多個業務在上面]

3.諮詢開發人員,這個業務什麼時候開始出現這些錯誤的,錯誤頻率如何 .[這個當時沒有諮詢,只是考慮到可能是我們資料庫這邊出現了問題]

3.1 如果是最近出現問題 && 並且資料庫沒有做任何變更,就要諮詢是否最近業務是否變更、請求量是否最近有增加。[太重要了!!!業務更新不是每次都會通知DBA的]

3.2 如果業務讓然沒有變更,看看資料庫伺服器歷史資源使用情況 [比如最近幾天的load cpu io tcp 連線數變化等],一來是看看資料庫最近的變化,二來看看是否是其他業務導致了這個業務受到影響。

4.看看慢查詢日誌,檢視最近是否有高頻並且佔用資源較高的SQL。

5.如果的確沒有什麼請求量,資料庫這邊沒有啥動靜,並且業務出現錯誤了,可能需要其他專業人士 SA 也來幫忙看下,是否是 Linux 機器本身的問題,或者是網路問題。

容易陷入的陷阱:

1.沒有資料庫自我檢查結束,就潛意識以為是DB 問題,其他方面出現問題的可能性沒有考慮全[硬體、網路、業務本身問題]。

2.處理問題的全域性性不夠,沒有再次出現問題就以為事情解決了,也沒有後續跟進修改業務引數以後的效果。

相關文章