高并發(fā)業(yè)務除了需要有支撐高并發(fā)的服務器架構,還需要根據(jù)業(yè)務需求和架構體系,設計出合理的開發(fā)方案,
這里根據(jù)一個實踐過業(yè)務場景分析開發(fā)思路抒倚,羅列出高并發(fā)接口需要注意的點,以及設計上的巧思坷澡,共勉之托呕,望共鳴
業(yè)務場景
- 業(yè)務:
- 今日好貨
- 交互端:
- IOS/Andorid
- 需求點:(實際業(yè)務會復雜些,為了容易理解频敛,這里簡化需求點)
- 提供最新的好貨商品信息列表项郊,支持分頁
- 需要時時獲取最新的商品數(shù)據(jù)列表,以下情況商品信息會發(fā)生變化
- 商品數(shù)據(jù)字段更新(人為編輯斟赚,熱度字段更新着降,等)
- 商品不定時上新,在固定時段會有大量商品更新(目前 10點/20點上新量大)
- 商品在會在規(guī)律時間里重新排序(根據(jù):銷量拗军,曝光量任洞,點擊量 等計算排序)
- 商品加載過程中不能出現(xiàn)重復商品
- 客戶端和服務端需要考慮加載商品的交互體驗
- 終極目標:
- 支持高并發(fā)下業(yè)務穩(wěn)定
設計思路
前提:
-
【商品服務API】
:通過商品服務提供的API獲取商品數(shù)據(jù),當商品有上新发侵、字段更新交掏、排序有更新時,通過API都可以獲取到最新的數(shù)據(jù)(db查詢刃鳄,支持獲取未來時間里的商品數(shù)據(jù)) - 緩存使用
Redis
緩存更新分析:
- 商品數(shù)據(jù)緩存到Redis:支撐高并發(fā)的查詢業(yè)務盅弛,數(shù)據(jù)需要進行緩存
- 提供商品緩存刷新接口:商品顯示需要即時性,需要時時展示最新數(shù)據(jù)铲汪,當商品發(fā)生變化的時候熊尉,我們需要刷新商品緩存數(shù)據(jù)
- 支持未來時間緩存提前更新:為了更好支撐即時性,尤其在固定時段商品的大量上新掌腰,緩存更新會比較慢狰住,所以我們需要提前備好未來時間的緩存數(shù)據(jù)
- 緩存刷新需要注意點:緩存更新的過程中不能出現(xiàn)前臺無數(shù)據(jù)展示的情況
- 商品緩存支持版本號區(qū)分:每次緩存更新都要生成一個新的數(shù)據(jù)版本號緩存Key,數(shù)據(jù)存儲在對應的緩存版本Key里
- 緩存版本Key存儲到列表 :列表可以用來篩選出當前時間可以使用的最新版本號
商品緩存更新設計:
- 接口參數(shù):updatetime
【更新時間】
(可空)齿梁,默認等于當前時間催植,可以傳未來時間 - 每次刷新緩存都會生成新的數(shù)據(jù)版本號作為
【商品緩存Key名】
肮蛹,將數(shù)據(jù)存到版本號對應的緩存Key中,所以需要生成一個唯一字符串创南,這里我們把【更新時間】
的時間戳作為緩存的Key名伦忠,為何這么設計,后面會介紹到 - 首先請求
【商品服務API】
獲取【更新時間】
對應的商品數(shù)據(jù)稿辙,接著對數(shù)據(jù)進行字段處理昆码、排序,最后把最終商品數(shù)據(jù)更新到【商品緩存Key名】
的Redis SortedSet中 - 商品緩存成功后邻储,把
【商品緩存Key名】
存到【版本號集合】
Redis SortedSet中赋咽,同時把【更新時間】
的時間戳作為排序的值 -
【商品緩存Key名】
=【更新時間】
的時間戳,這個設計的目的是可以支持未來時間版本數(shù)據(jù)的提前更新吨娜,并且可以通過SortedSet排序脓匿,過濾出當前時間最新的版本號
緩存結構圖
image
今日好貨API設計:
- 接口參數(shù):version:數(shù)據(jù)版本號(可空),pageindex:頁碼
- 響應JSON數(shù)據(jù):Datas:商品數(shù)據(jù)集合宦赠,CurrentVersion:當前數(shù)據(jù)版本號
-
【當前最新版本號】
:【版本號集合】
通過SortedSet機制陪毡,獲取當前時間能夠使用的數(shù)據(jù)版本號,
如:取[當前時間戳]-[(當前時間-1h)時間戳]區(qū)間的版本號勾扭,排序后獲取離當前時間最近的版本號作為最新版本號 <這里為何取區(qū)間毡琉,而不是直接取最新版本號,會有個容錯處理尺借,后面會說到> - 用戶在瀏覽商品的時候客戶端請求
【今日好貨API】
需要上傳版本號和頁數(shù)绊起,如果是第一次(pageindex=1,首頁)燎斩,會獲取【當前最新版本號】
,然后返回最新商品數(shù)據(jù) - 客戶端本地緩存首頁數(shù)據(jù)返回的版本號蜂绎,后續(xù)翻頁需要客戶端上報緩存的版本號栅表,API返回版本號對應的商品分頁數(shù)據(jù),這樣設計的目的是當用戶繼續(xù)加載后面頁數(shù)數(shù)據(jù)的時候不會出現(xiàn)重復的數(shù)據(jù)(數(shù)據(jù)會不定時更新师枣,避免用戶加載到重復的數(shù)據(jù)怪瓶,如:商品A原來是第一頁數(shù)據(jù),數(shù)據(jù)更新后變成第二頁數(shù)據(jù))
- 當請求首頁數(shù)據(jù)践美,客戶端上報的版本號=
【當前最新版本號】
洗贰,就不進行數(shù)據(jù)緩存查詢,直接返回空數(shù)據(jù)(數(shù)據(jù)不變)陨倡,客服端無需重新渲染商品列表敛滋,同時可以避免無限下拉刷新帶來的服務器壓力 - 如果version參數(shù)沒有上傳,獲取
【當前最新版本號】
和當前最新數(shù)據(jù)返回兴革,數(shù)據(jù)版本號參數(shù)有上傳绎晃,就獲取對應版本號的分頁數(shù)據(jù)
其他注意點:
- 版本號無限累加
-
【版本號集合】
隨著時間增長蜜唾,版本號數(shù)據(jù)會不斷累加,需要在每次更新的時候刪除掉最近一天的版本庶艾,操作 SortedSet 過濾掉比(當前時間-1天)的時間戳小的版本號
-
- 容錯處理
- 獲取
【當前最新版本號】
的時候袁余,操作【版本號集合】
集合,獲取最近一個小時的咱揍,即操作SortedSet[當前時間戳]至[(當前時間-1h)時間戳]范圍內的版本號颖榜,然后從大到小排序版本號,過濾出版本號煤裙,并且有版本號相對于的商品數(shù)據(jù)朱转,如果不存在商品數(shù)據(jù),就往下遍歷积暖,直到有符合規(guī)則的版本號返回
- 獲取
雙11模式:
- 一級緩存
- 將商品數(shù)據(jù)短暫的緩存到站點服務區(qū)Cache中
降級方案:
- 資源監(jiān)控藤为,自動降級
- 開啟降級方案后,客服端會從cdn中拉取商品數(shù)據(jù)
- 商品分頁數(shù)據(jù)生成JSON數(shù)據(jù)文件存儲到cdn中
架構圖
image
總結
- 以上舉例的高并發(fā)接口設計的實踐方案夺刑,有些設計可能比較針對此業(yè)務場景缅疟,但是思路是有共性的,重點在于理解設計上的思路
- 高并發(fā)接口的開發(fā)需要考慮因素:
- 接口性能
- 接口的穩(wěn)定
- 容錯機制
- 服務端壓力:竟可能減少服務端壓力遍愿,可以與客戶端交互配合
- 服務降級:資源高壓力的情況下進行降級
有任何想說的歡迎到原文來留言哦
轉載請申明原文地址存淫,謝謝合作
原文地址