天天看點

大話程式猿眼裡的高并發架構

前言

高并發經常會發生在有大活躍使用者量,使用者高聚集的業務場景中,如:秒殺活動,定時領取紅包等。

為了讓業務可以流暢的運作并且給使用者一個好的互動體驗,我們需要根據業務場景預估達到的并發量等因素,來設計适合自己業務場景的高并發處理方案。

在電商相關産品開發的這些年,我有幸的遇到了并發下的各種坑,這一路摸爬滾打過來有着不少的血淚史,這裡進行的總結,作為自己的歸檔記錄,同時分享給大家。

伺服器架構

業務從發展的初期到逐漸成熟,伺服器架構也是從相對單一到叢集,再到分布式服務。

一個可以支援高并發的服務少不了好的伺服器架構,需要有均衡負載,資料庫需要主從叢集,nosql緩存需要主從叢集,靜态檔案需要上傳cdn,這些都是能讓業務程式流暢運作的強大後盾。

伺服器這塊多是需要運維人員來配合搭建,具體我就不多說了,點到為止。

大緻需要用到的伺服器架構如下:

  • 伺服器
    • 均衡負載(如:nginx,阿裡雲SLB)
    • 資源監控
    • 分布式
  • 資料庫
    • 主從分離,叢集
    • DBA 表優化,索引優化,等
  • nosql
    • redis
    • mongodb
    • memcache
  • cdn
    • html
    • css
    • js
    • image

并發測試

高并發相關的業務,需要進行并發的測試,通過大量的資料分析評估出整個架構可以支撐的并發量。

測試高并發可以使用第三方伺服器或者自己測試伺服器,利用測試工具進行并發請求測試,分析測試資料得到可以支撐并發數量的評估,這個可以作為一個預警參考,俗話說知己自彼百戰不殆。

第三方服務:

  • 阿裡雲性能測試

并發測試工具:

  • Apache JMeter
  • Visual Studio性能負載測試
  • Microsoft Web Application Stress Tool

實戰方案

通用方案

日使用者流量大,但是比較分散,偶爾會有使用者高聚的情況;

場景: 使用者簽到,使用者中心,使用者訂單,等

伺服器架構圖:

大話程式猿眼裡的高并發架構

通用

說明:

場景中的這些業務基本是使用者進入APP後會操作到的,除了活動日(618,雙11,等),這些業務的使用者量都不會高聚集,同時這些業務相關的表都是大資料表,業務多是查詢操作,是以我們需要減少使用者直接命中DB的查詢;優先查詢緩存,如果緩存不存在,再進行DB查詢,将查詢結果緩存起來。

更新使用者相關緩存需要分布式存儲,比如使用使用者ID進行hash分組,把使用者分布到不同的緩存中,這樣一個緩存集合的總量不會很大,不會影響查詢效率。

方案如:

  • 使用者簽到擷取積分
    • 計算出使用者分布的key,redis hash中查找使用者今日簽到資訊
    • 如果查詢到簽到資訊,傳回簽到資訊
    • 如果沒有查詢到,DB查詢今日是否簽到過,如果有簽到過,就把簽到資訊同步redis緩存。
    • 如果DB中也沒有查詢到今日的簽到記錄,就進行簽到邏輯,操作DB添加今日簽到記錄,添加簽到積分(這整個DB操作是一個事務)
    • 緩存簽到資訊到redis,傳回簽到資訊
    • 注意

      這裡會有并發情況下的邏輯問題,如:一天簽到多次,發放多次積分給使用者。
    • 我的博文[ 大話程式猿眼裡的高并發 ]有相關的處理方案。
  • 使用者訂單
    • 這裡我們隻緩存使用者第一頁的訂單資訊,一頁40條資料,使用者一般也隻會看第一頁的訂單資料
    • 使用者通路訂單清單,如果是第一頁讀緩存,如果不是讀DB
    • 計算出使用者分布的key,redis hash中查找使用者訂單資訊
    • 如果查詢到使用者訂單資訊,傳回訂單資訊
    • 如果不存在就進行DB查詢第一頁的訂單資料,然後緩存redis,傳回訂單資訊
  • 使用者中心
    • 如果查詢到使用者資訊,傳回使用者資訊
    • 如果不存在進行使用者DB查詢,然後緩存redis,傳回使用者資訊
  • 其他業務
    • 上面例子多是針對使用者存儲緩存,如果是公用的緩存資料需要注意一些問題,如下
    • 注意

      公用的緩存資料需要考慮并發下的可能會導緻大量命中DB查詢,可以使用管理背景更新緩存,或者DB查詢的鎖住操作。
    • 大話Redis進階 ]對更新緩存問題和推薦方案的分享。
以上例子是一個相對簡單的高并發架構,并發量不是很高的情況可以很好的支撐,但是随着業務的壯大,使用者并發量增加,我們的架構也會進行不斷的優化和演變,比如對業務進行服務化,每個服務有自己的并發架構,自己的均衡伺服器,分布式資料庫,nosql主從叢集,如:使用者服務、訂單服務;

消息隊列

秒殺、秒搶等活動業務,使用者在瞬間湧入産生高并發請求

場景:定時領取紅包,等

大話程式猿眼裡的高并發架構

場景中的定時領取是一個高并發的業務,像秒殺活動使用者會在到點的時間湧入,DB瞬間就接受到一記暴擊,hold不住就會當機,然後影響整個業務;

像這種不是隻有查詢的操作并且會有高并發的插入或者更新資料的業務,前面提到的通用方案就無法支撐,并發的時候都是直接命中DB;

設計這塊業務的時候就會使用消息隊列的,可以将參與使用者的資訊添加到消息隊列中,然後再寫個多線程程式去消耗隊列,給隊列中的使用者發放紅包;

  • 定時領取紅包
    • 一般習慣使用 redis的 list
    • 當使用者參與活動,将使用者參與資訊push到隊列中
    • 然後寫個多線程程式去pop資料,進行發放紅包的業務
    • 這樣可以支援高并發下的使用者可以正常的參與活動,并且避免資料庫伺服器當機的危險

附加:

通過消息隊列可以做很多的服務。

如:定時短信發送服務,使用sset(sorted set),發送時間戳作為排序依據,短信資料隊列根據時間升序,然後寫個程式定時循環去讀取sset隊列中的第一條,目前時間是否超過發送時間,如果超過就進行短信發送。

一級緩存

高并發請求連接配接緩存伺服器超出伺服器能夠接收的請求連接配接量,部分使用者出現建立連接配接逾時無法讀取到資料的問題;

是以需要有個方案當高并發時候時候可以減少命中緩存伺服器;

這時候就出現了一級緩存的方案,一級緩存就是使用站點伺服器緩存去存儲資料,注意隻存儲部分請求量大的資料,并且緩存的資料量要控制,不能過分的使用站點伺服器的記憶體而影響了站點應用程式的正常運作,一級緩存需要設定秒機關的過期時間,具體時間根據業務場景設定,目的是當有高并發請求的時候可以讓資料的擷取命中到一級緩存,而不用連接配接緩存nosql資料伺服器,減少nosql資料伺服器的壓力

比如APP首屏商品資料接口,這些資料是公共的不會針對使用者自定義,而且這些資料不會頻繁的更新,像這種接口的請求量比較大就可以加入一級緩存;

大話程式猿眼裡的高并發架構

合理的規範和使用nosql緩存資料庫,根據業務拆分緩存資料庫的叢集,這樣基本可以很好支援業務,一級緩存畢竟是使用站點伺服器緩存是以還是要善用。

靜态化資料

高并發請求資料不變化的情況下如果可以不請求自己的伺服器擷取資料那就可以減少伺服器的資源壓力。

對于更新頻繁度不高,并且資料允許短時間内的延遲,可以通過資料靜态化成JSON,XML,HTML等資料檔案上傳CDN,在拉取資料的時候優先到CDN拉取,如果沒有擷取到資料再從緩存,資料庫中擷取,當管理人員操作背景編輯資料再重新生成靜态檔案上傳同步到CDN,這樣在高并發的時候可以使資料的擷取命中在CDN伺服器上。

CDN節點同步有一定的延遲性,是以找一個靠譜的CDN伺服器商也很重要

其他方案

  • 對于更新頻繁度不高的資料,APP,PC浏覽器,可以緩存資料到本地,然後每次請求接口的時候上傳目前緩存資料的版本号,服務端接收到版本号判斷版本号與最新資料版本号是否一緻,如果不一樣就進行最新資料的查詢并傳回最新資料和最新版本号,如果一樣就傳回狀态碼告知資料已經是最新。

    減少伺服器壓力:資源、帶寬

未完待續...

有補充的留言給我哦

感謝大家的支援,領取天貓【 雙11紅包

】,獲得推廣費用來維持網站的運作,謝謝了解。

大家有啥意見或者建議的到

原文位址 給我留言吧,感謝支援~