百萬會員推薦關係優化實戰

        最近,一朋友整天因爲CPU 99%搞得茶飯不思,夜不能寐,找到我”訴苦“。聽完成,心中一陣竊喜:是時候展現真正的實力了(其實是練手的機會來了)。半推半就應承了下來。

 

 

01 分析問題

        幾分鐘瞭解下來,大概情況如下:會員可以推薦其他用戶註冊,會員有一個屬性--活躍度,用戶觀看視頻,簽到等等行爲時,這個屬性會動態變化,其中有個需求是統計所有下級活躍度。會員模型如下,模型比較簡單,使用使用sqlserver 2016。

 

 

  瞭解需求後,再來看看佔cpu高的查詢。其中佔cpu 時間最多的就是下面這條sql,查詢某個用戶所有下級的活躍度之和。這條語句使用遞歸查詢,那是比較耗時的,另外如果層級太多還有如下錯誤:語句被終止。完成執行語句前已用完最大遞歸 100。

  

1 WITH T
2 AS( 
3     SELECt DataID, avtivenewss FROM User WHERE DataID = 4167
4     UNION ALL 
5     SELECT u.DataID, u.avtivenewss   
6     FROM User U INNER JOIN T ON U.parentUserid=T.DataID
7 ) 
8 SELECT sum(avtivenewss) FROM T

  

  當前用戶1W+。

 

02 失敗的嘗試:前綴法

 

      幾乎沒思考,就想到了一個方法:前綴法。一個用戶的所有後代使用同一個前綴。增加一個字段 paths,以用戶編號爲基礎,格式爲:/1/2/3/,用戶註冊時使用記錄上級的paths + 上級id 生成自己的paths,  增加paths的索引,這樣更具此字段就可以查詢我的所有下級了,再寫個腳步初始化。非常簡單,三下五除二就解決了。上線效果非常明顯。

 

 

  但是好景真短,沒兩天cpu 又高了。一查,好多查詢都沒有走索引,明明字段已經加了索引。一看數據,原來是索引長度限制問題。用戶居然有好幾十個層級,且還在不斷增加,長度超過索引最大長度後,索引失效。

  當前用戶10W+。

 

04 大膽猜測,小心嘗試

 

     會員關係是一棵樹,不管怎麼遍歷,效率都有限。如果把樹拉平,用戶與所有後代都建立一個關係,性能會怎麼樣呢。爲了避免再次打臉,悄悄的開始了嘗試。增加模型tree。

    

  這需要在用戶註冊時,添加與所有祖祖輩輩的關係。比如 4167用戶註冊,需要一次添加14條關係記錄。而查詢用戶的所有子子孫孫時,也會非常方便。

 

  編寫腳本初始化數據,增加切換開關,戰戰兢兢的上線了。經過一個高峯,cpu居然都在10%以下,完全沒有壓力嘛,終於可以亮出臉來了。這是典型的空間換時間。但是高興之餘,心中閃過一個念頭--這個表的膨脹速度有點快,它會有極限麼。不過,馬上被另一個念頭壓制了:小網站能有多大量!

 

  有個什麼定律來着:凡事只要有可能出錯,那就一定會出錯。果不其然,10天后同樣的問題再次發生。cpu幾乎爆滿。只能不停重啓,最後乾脆下掉了這個統計功能,爲此還被懟了一頓。此時關係表總數爲10億。

   當前用戶100W+。

  

05 終級方案:分表

 

     其實對於分表這樣的事兒,一直都有想過,就是沒幹過,另外也一直以爲是sum()引起的cpu問題。後來諮詢了公司做交易的同學,傳說他們每天處理2kw的訂單,基本思路也是根據用戶id分了2048張表。反正也沒轍了,擼起袖子搞起來吧。分析了tree 表只有兩個查詢場景,查用戶所有後代及查用戶所有祖先。分別以ancestor ,descendant 分256 張表。用戶註冊時,把關係分別寫到個分表中。

 

  編寫腳本初始化兩個緯度的分表數據,再次戰戰兢兢的上線了。經過數個高峯,效果比預期好太多了。徹底告別了cpu告警。
經歷了幾次失敗,早以沒了高興勁兒,心中有個疑問,如果是sum引起的cpu跑滿的話,現在sum並沒有減少,但是cpu爲啥清閒了呢?這背後一定有原因的。

 

  

06 刨根問底

 

      帶着上面的疑問,對比了一些監控數據,發現了一個可疑的地方,磁盤請求減少了數百次。那麼磁盤與cpu有什麼樣的關係呢?

 

 

  查詢相關資料後,得出一個猜測:

  未分表前,每次查詢所有後代(祖先時)時,因爲數據在磁盤上非常分散,page cache 命中率低,磁盤預讀失效,所以一次查詢要進行很多次磁盤隨機讀,大量的io操作,cpu就要進行大量的上下文切換,從而導致cpu跑滿。

  分表後,每次查詢所有後代(祖先時)時,每次都在特定的分表中查詢,數據在磁盤上非常緊湊,磁盤預讀發揮最大性能,page cache 命中率高,io次數據大量減少,cpu上下文切換次數減少,沒了壓力,cpu自然清閒了。

 

        最後打個廣告:哈囉出行,base 杭州, java 我們的部門有大量HC, 歡迎私聊哈。微信:jijunjian

         I have a dream to be a good programmer。

         

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章