秒殺架構設計
?先看下普通web項目架構:?
(Nginx : 反向代理、負載均衡,一般是運維部分做生產搭建的時候配置好)
秒殺架構設計:
和普通架構區別:
- 原先由Web 服務或Nginx服務提供的靜態資源放到了CDN
- Nginx的職責放?,前置?來做Web ?關,承擔部分業務邏輯校驗,并且可能增加??名單、限流和流控的功能
秒殺技術選型
核?設計是對巨?的瞬間流量進?層層錯峰。
錯峰1:頁面靜態化。將包含瀏覽者信息的動態數據和不包含的靜態數據進行區分。
錯峰2:秒殺前答題。?的是防?機器刷單,以及錯開?戶的下單時?。
錯峰3:Redis扣減庫存。快速扣減庫存, 扣減庫存完通知nginx.
錯峰4:Nginx快速通知秒殺結束。
錯峰5:MQ進行流量消峰
錯峰6:引? MQ 進?下單服務異步化
秒殺后端鏈路圖
—場完整的秒殺活動的?概流程是這樣的:
1.運營?員在秒殺系統的運營后臺,根據指定商品,創建秒殺活動,指定活動的開始時間、結束時間、活動庫存等。
2.活動開始之前,由秒殺系統運營后臺開啟秒殺,會同時往商城系統的Redis Cluster集群寫? ??秒殺活動信息 和往秒殺系統的Redis主從集群寫諸如 秒殺商品庫存 等信息。
3.?戶進?到秒殺商詳?準備秒殺。
4.商品詳情?可以看到?即搶購的按鈕,這?我們可以通過增加?些邏輯判斷來限制按鈕是否可以點擊,?如是否設置了搶購?戶等級限制,是否還有活動庫存,是否設置了預約等等。如果都沒限制,?戶可以點擊搶購按鈕,進?到秒殺結算?。
5.在結算?,?戶可更改購買數量,切換地址、?付?式等,這?的結算元素也需要按實際業務來定,更復雜的場景還可以?持積分、優惠券、紅包、配送時效等,并且這些都會影響最終價格的計算。
6.確認?誤后,?戶提交訂單,在這?后端服務可以調??控、限購等接?,來完善校驗,都通過之后,完成庫存的扣減和訂單的?成。
7.訂單完成后,根據?戶選擇的?付?式跳轉到對應的??,?如在線?付就跳轉到收銀臺,貨到付款的話,就跳到下單成功提示?。
相關技術點:
- 秒殺活動開始:Canal組件監聽DB里秒殺活動變化,同步到Redis,并在首頁展示
- 商品詳情頁:Nginx配置了詳情頁的頁面,動態數據從Redis中獲取, 靜態數據在Nginx中配置好
- 確認訂單:
- 生成訂單:Redis中扣減庫存
秒殺前流量管控
秒殺中的流量管控
1. 流量削峰
- 驗證碼和回答問題:有兩個?的,?是快速攔截掉部分刷?流量,防?機器作弊,起到防刷的作?;?是平滑秒殺的?刺請求,延緩并發,對流量進?削峰。
- 消息調用:用到兩個業務系統之間的調用中
2. 限流
Nginx限流
Nginx本身也提供了?常強?的限流功能,?如有兩個專?的限流模塊HttpLimitzone和HttpLimitReqest
- HttpLimitzone?來限制?個客戶端的并發連接數,
- HttpLimitReqest通過漏桶算法來限制?戶的連接頻率
// HttpLimitzone示例
// 表示同?ip不同請求地址,進?名為one的zone,限制速率為1請求/秒。http {limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;server {location /search/ {limit_req zone=one burst=2 nodelay;}}
}
應用/服務層限流
1. 線程池:限制連接數
2. 限流組件:QPS的限流
3. 自定義限流:
????????比如用戶的下訂單請求,前端在用戶進入訂單結算頁面時,調用訂單號服務生成個orderId,在用戶提交訂單時,帶著這個orderId.?
????????訂單號的獲取,秒殺場景下的改進是:JVM緩存放置預先生成的orderId, 定時任務定時去生成新的orderId并放入緩存中(注意保證線程安全)。
????????JVM緩存中的訂單號起到限流的作用, 同時前端提前生成orderId, 也防止了同一個訂單提交多次。
分層過濾
舉個例子,秒殺如果商品售罄,會將庫存為0的結果寫到nginx緩存
1. nginx判斷庫存, 先判斷本地緩存, 在判斷redis緩存, 結果為0時終止秒殺
2. 業務鏈路中,同樣都會做庫存的判斷
業務上還要解決退單導致庫存量增加,思路:訂閱對應的Redis的channel.
3. 限購
限購的策略:
- 商品維度:秒殺產品的總量、商品發貨地 等等
- 個人維度:1個手機號1單、1人1天1單 等等
秒殺活動時, 流量先經過限流策略過濾后,在進入到訂單服務。通過限購策略,也可以過濾到一部分流向訂單系統的流量。
庫存扣減
庫存扣減涉及到兩個核心操作,查商品庫存,庫存充足扣減庫存。要保證其原子性
1. 數據庫
1. 查詢和扣減放在一個事務中
2. where 條件保證庫存 >= 0
3. 樂觀鎖, 先查詢,更新時帶著版本號
4. 數據庫特性:無符號整數字段,值不能小于0, 所以扣減到小于0,SQL報錯(性能超,不適合秒殺,適合業務量小的場景)
2. 分布式鎖
商品維度加分布式鎖,但不適合秒殺場景。
- 過期時間的設置,太短,業務流程未走完就過期了;太長,如果當前業務流程異常,導致其他線程一直阻塞鎖,性能不高。
- 秒殺場景,商品還串行下單,性能肯定不好
3. 高并發扣減
降級
降級?般是有損的,那么必然要有所犧牲,?種常?的降級:寫服務降級、讀服務降級。
1. 寫服務降級:犧牲數據─致性獲取更?的性能。 降級手段,同步寫數據庫降級成同步寫緩存、異步寫數據庫。
Redis扣減庫存,通過lua腳本,保證查詢和扣減原子性的執行
2. 讀服務降級:故障場景下緊急降級快速?損。
????????在做?可?系統設計時,要牢記就是微服務?身所依賴的外部中間件服務或者其他RPC服務,隨時都可能發?故障,因此我們需要建設多級緩存,以便故障時能及時降級?損。
????????假設當秒殺的Redis緩存出現故障時,我們就可以通過降級開關,快速將讀請求降級到 從Redis 緩存、MongoDB或者ES上。或者當Redis和備份緩存同時出現故障時(現實中很少出現同時故障的場景),我們還是可以通過降級開關將流量切換到數據庫上,讓數據庫暫時承壓來完成讀請求服務。
簡化系統設計
????????簡化系統功能就是指?掉?些不必要的流程,舍棄?核?功能。
????????商品的基本信息外,還有很多附加的信息,?如你是否收藏過該商品、商品的收藏總數量、商品的排?榜、評價和推薦等樓層。同樣,對于秒殺結算?,還會有禮品卡、優惠券等虛擬?付路徑。
????????不過,實際運?中,這種?核?功能的有損降級,要視具體的SKU?定,?般為了降低影響范圍,我們只對流量?常?的SKU進?降級。?如,如果是?機秒殺,?般是不需要降級的,但是像?罩這樣的爆品,就需要針對SKU維度進??核?功能的降級了。
????????降級開關的怎么設計呢,其實?較簡單,核?思路就是通過配置中?,對降級開關進?變更,然后推送到各個微服務實例上。
4. 熱點數據
?????????般?并發的常規解決思路是:數據庫通過分庫分表來應對;Redis,增加Redis集群的分?來解決,?應?層?般是?狀態的設計。所以從數據庫、Redis緩存到應?服務,都是可以通過增加機器來?平擴展服務能?,解決?并發的問題。
? ? ? ? 但是秒殺場景,就那么幾個商品,這些手段顯然不夠。
1. 讀熱點
1. 增加熱點數據的副本數。?增加Redis從的副本數,然后業務層(Tomcat集群)輪詢查詢不同的副本,提?同?數據的QPS。
2. 讓熱點數據離?戶越近越好。
- 把熱點數據再上移, 在服務內部做熱點數據的本地緩存。但是本地緩存的數據延遲要有解決方案
- 如果還是用redis緩存,nginx和nginx需要的緩存部署在一起,業務服務和業務服務使用的緩存部署在一起, 做到不跨網絡訪問。
3. 直接短路訪問。 要具體業務具體分析, 根據商品的配置,直接不走一些業務邏輯。
2. 寫熱點
- 預約人數場景, 實際展示的預約人數并不要求十分精確, 對應的解決方式:先在JVM內存?累加,延遲提交到 Redis,這樣就可以把 Redis 的OPS降低??倍。
- 寫對象顆粒化,庫存的扣減場景,可以通過把?個熱 key拆解成多個key的?式,避免熱點問題。
單SKU的庫存直接在Redis 單分?上進?扣減。實際上,扣減庫存在秒殺鏈路的末端,通過之前的削峰和限流的各種?段,真正到庫存的流量是有限的,單?的Redis OPS 能承受得了。然后,我們可以針對單SKU的庫存扣減進?單獨限流,保證庫存單?Redis的壓?。這樣雙管?下,單SKU的庫存Redis 扣減壓?就是可控的了。
相關技術
OpenResty
????????Nginx在主要的秒殺系統設計中,扮演著?常重要的??,意味著Nginx上要承載很多的業務邏輯。Nginx的底層模塊?般都是?C語?寫的,如果我們想在Nginx的基礎之上寫業務邏輯會很不?便,所以這個時候我們還得借助OpenResty,它是Nginx的?個社區分?。
????????按照官?的說法,OpenResty 是?個基于 Nginx 與 Lua 的?性能 Web 平臺,其內部集成了?量精良的 Lua庫、第三?模塊以及?多數的依賴項。?于?便地搭建能夠處理超?并發、擴展性極?的動態 Web 應?、Web 服務和動態?關。
????????OpenResty本質上是將 LuaJIT 的虛擬機嵌?到 Nginx 的管理進程和?作進程中,同?個進程內的所有線程都會共享這個虛擬機,并在虛擬機中執?Lua代碼。在性能上,OpenResty接近或超過 Nginx 的C模塊,?且開發效率更?。