1. 需求簡介算法
根據用戶的測試狀況,給他推薦相應的課程,而後根據學習時長能夠得到勳章數據庫
2. 效果圖緩存
3. 功能拆解異步
3.1. 測試題分佈式
【要點】學習
一、 須要一個題庫,配好題目和答案選項;測試
二、須要根據用戶的答題狀況(分數)抽取必定量的各類類型的題目大數據
三、本次抽取的題目與上一次的題目重複率不得超過50%spa
四、提交答案3d
【難點】
這個功能最複雜的地方在於重複率不得超過50%,能夠用兩次的題目去交集來判斷,也能夠排除上一次的題目後再隨機,沒有用什麼高深的算法(主要是不懂)這裏我用的後者,再也不贅述。
3.2. 生成計劃
【要點】
一、從大數據那裏獲取推薦內容
二、上一個計劃未完成不容許開啓下一個計劃
三、同種勳章只能得到一次
四、保存數據(計劃、計劃詳情、勳章、消息)
【難點】
一、調大數據的接口時要考慮到失敗的狀況,即便大數據的服務掛了,我們也不能掛,爲此加上try...catch,超時時間等等都是必要,這還不夠。萬一調大數據失敗了,返回保底數據。
二、考慮到重複提交的狀況,需加分佈式鎖
3.3. 計劃首頁
【要點】
一、內容展現,包括分已購未購、免費付費、會員非會員、標籤等等
二、學習時長展現,包括時長、天數、當前階段、勳章等等
【難點】
一、查數據庫想都不要想,首選直接查Redis,可是Redis查的次數多了綜合起來也有可能慢,必要時可考慮本地緩存(內存緩存)
二、時長、天數等均從在Redis總累計,可直接獲取
3.4. 學習時長
【要點】
一、實時記錄
【難點】
一、線上相似的接口高峯時段可達到1分鐘84萬次請求,所以想都不用想,必須異步,咱們採用MQ
二、儘管消費者是一條一條的消費,然而這並不意味着一秒鐘只消費一條,據觀察,線上其它相似MQ消費者平均一秒鐘消費300條
三、時長最終是要更新到MySQL數據庫中的,可是如此頻繁的寫數據,風險比較大,想來想去,最終選擇用定時任務在夜深人靜的時候從Redis同步到MySQL
四、學習時長是一個特別重要的參數,關係到挑戰任務,關係到勳章,所以以秒爲單位,累計至1分鐘再寫入
五、在壓測的時候,我發現基於Redis的分佈式鎖彷佛並不能保證徹底100%鎖住,雖然機率極低,但我好像碰到了
3.5. 樓層
【要點】
一、根據用戶計劃的狀態展現不一樣的按鈕及背景圖
二、連續關閉兩次樓層後再也不出現,新開啓計劃後再次出現
【難點】
一、用戶關閉樓層的行爲直接記到Redis中,沒必要存數據庫
3.6. 彈窗
【要點】
一、每一個挑戰任務對應一個勳章,再加上最後一個獎勵勳章。任務是有順序的,所以彈窗也是,爲此須要知道任務先後的關係
二、每一個彈窗只彈一次,所以須要記錄用戶是否查看過
【難點】
一、用雙向鏈表將挑戰任務串聯起來,這樣就能夠根據當前所處階段快速找到上一個或下一個任務
二、在Redis緩存結構上,我犯了一個錯誤。緣由我想的是既然是有順序的要不就用List類型,可是後來發現更新的時候極其不方便,要把全部的元素先刪除(LTRIM命令),而後修改後從新插入,在一次壓測過程當中發現裏面大量重複數據,還沒刪完就已經插入了,因而越插入越多,這就是偷懶的代價,最終緊急改爲Hash類型,這樣即便有重複也會被覆蓋。
3.7. 通知消息
【要點】
一、APP消息和站內信都要發
二、不用的階段的消息文案不同
【難點】
一、定時任務掃描
二、異步發送,保證互不影響
4. 壓測
全部的Redis查詢都是批量查詢,即便是這樣,響應時間依然很長,平均響應時間400ms左右。用PinPoint分析排查:
後來,加上了本地緩存Caffeine,感受快了不少
順便看下其它指標