本文來自網易雲社區html
考拉湊單頁爲整單類活動湊單頁面,從大促的表現來看,承載在考拉全站差很少5%左右的請求量,尤爲在大促整單類活動比較多的狀況,對於湊單商品的實時性就有更高的要求,要否則用戶沒有入口作湊單,已考拉目前的湊單頁地址如https://www.kaola.com/activity/goods/1197184.html,效果以下ajax
考拉目前的搜索湊單頁基於杭研的ndir去構建doc,可是考拉在大促的時候零點那一個時刻,按照3月8大促的量,存在幾十萬商品更新索引信息,由於全部商品的促銷信息都須要更新到ndir裏面,隨着考拉業務的不斷髮展,商品的數量級仍然會不斷增長,可是對於ndir來講,更新索引是比較耗時,基於lucene全文檢索實現,更新通常分爲刪除和插入操做doc,以前考拉的方案因爲商品很少,因此在變動活動信息基於mq消息通知搜索,搜索觸發更新索引操做會調用促銷接口更新ndir,促銷會給出當前的實時促銷信息,活動結束的時候也會觸發mq消息通知,這樣保證活動開始和活動結束這個搜索能夠即便的構建活動。
數據庫
可是隨着考拉商品sku數量不斷擴大,ndir的更新瓶頸顯得尤其明顯,尤爲在大促時候,瞬間有幾十萬商品參加活動,這樣mq消息就顯得特別的龐大,按照以前數據量所有更新一次索引差很少兩個小時,可是大促開始那個時刻是下單量最大的,這段時間的湊單頁不實時直接影響轉化率和用戶體驗。
緩存
因此整個大促的活動總體優化方案 安全
1.搜索增長一個索引字段專門爲湊單頁去匹配,這個字段只給湊單頁使用數據庫設計
2.促銷對於整單類活動的時間,促銷提早返回所有未開始的整單類活動,整單類活動在發動發佈的時候就刷新進緩存ide
3.促銷的整單類活動的開始時間以會員時間爲準,若是處於提早購階段或者未開始的時間存在提早購增長返回提早購標示,整單類還須要把非會員開始時間,整單類結束時間落庫性能
4.對於中途整單類活動已經刷進ndir,運營變動活動,修改,刪除等活動都須要的實時刷新到ndir去
優化
新增一個索引字段,主要是爲了不正在進行的活動和未開始的活動的區分,在考拉的主搜那邊會根據goods_tag去獲取正在進行的活動,用戶前臺能夠根據是否有促銷搜索商品信息,這塊信息要保證明時的一致性,不然會引發很大的客訴,https://www.kaola.com/activity/goods/1197184.html湊單頁的url比較固定,這樣會被用戶窮舉,加入用戶訪問了一個未開始的活動,這樣也會有問題。對於這個窮舉問題,考拉目前的作法是頁面和數據分兩個請求,頁面請求爲同步請求,同步請求的時候會根據活動方案號去促銷系統查詢改方案是否有效,若是爲非法的方案號,直接渲染404錯誤頁面,不然跳轉正常的湊單頁,而後再根據ajax請求搜索數據
url
整個基於mq消息通知去更新索引信息,因爲活動的數據時間常常變動,所以須要在活動發佈,活動開始,價格審覈經過,活動暫停,活動恢復等活動變動的流程中去控制ndir裏面的索引數據,目前這塊業務整合在促銷的消息通知裏面,爲了不一次消息量過大,促銷發送消息時候作了一次分批處理
@Override public void sendActivityNotifyMessage(List<Long> goodsIdList) { if (CollectionUtils.isEmpty(goodsIdList)) { return; } List<Long> notifyGoodsIdList = new ArrayList<>(new HashSet<>(goodsIdList)); int batchSize = promotionConfig.getInteger(sendActivityNotifyBatchSize, 500); ListUtils.split(notifyGoodsIdList, batchSize, new PageProcess<Long>() { @Override public void process(List<Long> pageIdList) { logger.info("send activity notify Message to rabbitmq goodsId:{}",pageIdList); Map<String,List<Long>> param = Maps.newHashMap(); param.put("goodsIdList", pageIdList); rabbitTemplate.convertAndSend(param); } }); }
活動變動時候爲了減小發送量,只會把變動商品發送給ndir那邊,變動數據主要爲新增,修改和刪除的商品id,促銷這邊基於定時任務發送變動信息,定時任務每一分鐘發送一次,數據表一個商品在同一個時間點存在多個活動,這時候變動記錄只會有一條,因此數據庫設計以商品id和時間維度,具體表設計以下
CREATE TABLE TB_ACTIVITY_NOTIFY ( ID VARCHAR2(32) NOT NULL, GOODS_ID NUMBER(10) NOT NULL, UPDATE_TIME TIMESTAMP(6) DEFAULT SYSDATE NOT NULL, SEND_FLAG NUMBER(1) DEFAULT 0 NOT NULL, CONSTRAINT PK_TB_ACTIVITY_NOTIFY PRIMARY KEY (ID) );
該表爲了保證通知性能,須要定時清除,由於大促的商品數據量很大,若是不作定時清理或者分區,會致使通知表的性能降低,因此增長一個send_flag表示通知標示,若是已經發送的成功的話,則修改成Y,這樣定時清除就能夠經過標示清除已發送數據
本文來自網易雲社區,經做者李世堤受權發佈。
相關文章:
【推薦】 聊聊空狀態設計
【推薦】 如何作好iOS應用安全?這有一把行之有效的「三板斧」