1. 程式人生 > 其它 >記一次生產優化-優化定時提前載入使用者資訊

記一次生產優化-優化定時提前載入使用者資訊

背景

最近,有不少使用者反映登入我們的APP後,進入首頁展示使用者資料時要很久很久才能展示出來。剛開始還沒在意,以為是使用者自己的網路慢導致的,後來有好幾個使用者都反映了此問題,這不得不引起我們的重視了。

後來經過我們排查日誌發現一個現象,提出該問題的使用者都是基礎資料比較多的,因為我們是金融軟體,所以當用戶的基礎資料比較多的時候,在首頁展示時會先去查詢基礎資料,然後在輪詢這些基礎資料查詢介面得到結果之後再進行一些邏輯運算。有不少使用者多達幾十甚至上百條基礎資料,所以導致查詢時非常慢。

問題分析

這個問題的關鍵是使用者基礎資料的查詢,以及對基礎資料輪詢查詢介面次數較多導致的。所以當了解了問題的根源所在,我們就從根源出發解決這個問題。

我們想到的是,既然是因為查詢基礎資料和輪詢基礎資料次數較多導致的,那麼我們就減少次數。

怎麼減少呢?我們的方案是提前查詢使用者基礎資料到Redis進行快取,而不是在客戶登入時再去載入,這樣使用者登入時的基礎資料查詢次數就減少到了0。因為我們的使用者基礎資料變化的不是那麼頻繁,所以我們可以這樣提前快取

那麼什麼時候去載入使用者的資料到Redis裡呢?顯然是在使用者使用APP之前且較少人使用的時間段,我們暫且定在凌晨3、4點吧。我們可以在這個時間把這些特殊使用者的資料通過定時跑批的方式提前載入至Redis。

那什麼樣的使用者才去提前載入呢?肯定不是所有使用者,我們只針對基礎資料條數達到某一閾值時的使用者

(稱為特殊使用者,將使用者新增至白名單使用者表white_user表)。比如基礎資料達到5條時,該閾值可引數化配置,並根據條數和頁面響應時間測試得出該值。比如當有5條基礎資料時,達到頁面響應時間使用者可忍受程度的極限。

我們必須要自動發現特殊使用者,將其新增至white_user表。我們選擇在使用者登入時開啟執行緒判斷使用者是否滿足白名單使用者的條件,滿足則新增至white_user表,不滿足的先判斷是否在表裡,在則刪除掉。(使用者可自己操作減少基礎資料)

實施方案

分析完問題,也大致確定瞭解決方案。我們來總結下解決方案:

1、自動發現特殊使用者,新增至white_user表。-根據基礎資料閾值,判定是否為特殊使用者。

2、凌晨定時載入白名單使用者基礎資料至Redis。-定時跑批,執行任務。

具體實現

1、在跑批系統,建立SpringQuartz定時任務。設定每天凌晨3點執行定時任務,具體執行的任務就是通過Redis釋出訂閱功能通知APP服務系統,APP服務系統收到訊息後查詢白名單使用者,然後查詢使用者基礎資料到Redis。

2、客戶登入時,執行非同步操作。根據基礎資料個數與閾值比較,判定是否可以列為特殊使用者,並新增至白名單使用者表;不滿足特殊條件時若使用者在白名單使用者表,則刪除。

3、非同步重新整理使用者基礎資料,當用戶修改基礎資料時,非同步更新基礎資料。

4、因為載入到Redis的資料設定的都有過期時間,所以。。。。

需要注意

1、跑批系統和APP服務系統都是叢集部署的,所以如何實現只有一臺跑批伺服器去執行跑批任務利用Redis釋出訊息通知APP服務系統?

2、如何實現APP叢集服務不重複載入使用者資訊?(因為叢集下都會收到跑批系統的訊息,又不能控制只有一臺收到訊息,所以就控制只有一臺執行)

第一個問題解決方案,redis分散式鎖

定時任務執行時,利用Redis實現分散式鎖,使得只有一臺跑批系統執行任務。

第二個問題解決方案,可以和第一種一樣也使用分散式鎖,但還可以用另一種

由於APP服務系統執行載入客戶資料的操作是基於使用者ID的,所以查詢白名使用者ID的操作可以交給跑批系統來做

跑批系統將客戶號放入Redis(list型別實現佇列),APP服務系統就算是多臺都執行,但是他們都是要去Redis中取使用者ID的,對Redis的list型別實現的佇列執行getAndDel操作。

所以即使是叢集環境下多臺機器都執行,也不會重複操作同一使用者資料,不會做重複操作。