1. 程式人生 > >Mongo 後臺加索引踩坑

Mongo 後臺加索引踩坑

開始 但是 一分鐘 聯合 管理 阻塞 主從同步 鍵值 增長

背景,隨著mongo數據量變大,查詢效率變低,要對索引進行優化,所在公司對mongo依賴比較嚴重,而DBA並不對mongo的權限做控制,所以每個後端開發都有mongo的讀寫權限,通常每個人各自管理自己的模塊的數據。

由於筆者所負責的模塊數據增長較快,用戶的關鍵業務數據都存在mongo裏面,很快mongo裏面的數據就積累到幾百萬,之前只有一個五個字段的聯合索引,所以是時候作死了。。。

本著作死要有條不紊有依有據的原則,在測試數據庫接近百萬數據量的相同Collection裏面進行了實操,阻塞方式加索引簡直快的飛起,shell裏面結果秒回,實際執行沒有監控,但也很快,因為幾秒內去測試接口,速度明顯提高,這樣折騰了幾回之後公司qa反映接口響應速度很快,頓時信心爆棚,要上線上大展拳腳。

一個月後,要優化接口的任務下來了,頓時心花怒放,多日的準備終於要看到成果了:

一開始還是很謹慎的,試著加上一個索引,當然時間選擇是下班前,這時候客戶大多下班,出了事情也能得到本公司運維的及時支持,照著測試環境的步驟,一個一個加,結果沒有任何用戶感知的情況下索引加成功!本著謹慎的原則,唯一一個與測試環境操作不同的就是後臺參數為true,天真的以為這樣就可以不影響服務了,正是這個不同導致了災難,事實上前幾個索引的添加確實沒什麽問題,十幾秒就添加成功,精神也逐漸松懈下來,這時,套用凱文哈特的一句話,It‘s about to go down!

加完了該加的索引後,去線上看看效果,結果並不理想,猜想原因是之前的5個鍵的聯合索引影響了查詢效率,於是想將其拆開,這樣雖然特定的一個接口效率會有所降低,但是卻照顧了大多數的接口,於是刪除了這個索引,然後開始新建索引,過了一分鐘,還沒有返回結果,線上各種服務開始各種pending。。。事故發生,並持續了3個小時。

看到這裏大家就都明白了,就是刪除這個聯合索引的時間過早了,因為之前添加的索引沒有一個是覆蓋了這個聯合索引中的某個鍵值的,更要命的是區區幾百萬數據,主從同步的話應該會很快,偏偏被我自作聰明的選擇了後臺建索引。這樣就導致刪除索引後查詢開始變慢,這時在線用戶還不少,一定量針對mongo的請求開始積壓,在短時間內沾滿的主服務的連接池,然後不用mongo的的接口也開始變慢,mongo一看進來了查詢,就優先處理查詢,索引就遲遲建不完,那麽索引就不能被使用,查詢就會慢,進入了惡性循環。

最終運維和dba查了各種資料在進行了一次mongo重啟後,在兩個多小時後,決定停服把原來的索引加回去,這時仍然是後臺方式,不到5分鐘索引就增長了60%完成了創建,服務恢復。

總結:第一點,數據庫的索引操作一定在深夜進行,防止影響服務。第二點,看起來謹慎的後臺建索引方式並不是最好的,數據量不大的情況下,阻塞可能更幹脆影響更小,在本案中,不到幾十秒肯定就能完成前臺建立單鍵索引。最後,手裏有權限不代表能操作,以後這種事一定要給DBA做。

Mongo 後臺加索引踩坑