1. 程式人生 > >zookeeper學習筆記(五)——具體應用:秒殺

zookeeper學習筆記(五)——具體應用:秒殺

秒殺一般有幾個場景

1.電商秒殺商品 2.搶紅包 3.搶票

假設一個場景如下

     某電商公司搞活動,一折秒殺,推出幾種秒殺的商品,每種商品1000個,預計100w人搶購 要求: 不能超賣.絕對不可以賣多了. 資料庫要扣減庫存,並且記錄訂單明細

難點分析

1.不能阻塞. 海量的請求就像血栓一樣,遍走周身,一旦遇到瓶頸,就會堵塞整個血管. 所以一定要讓海量的使用者請求,儘快結束.

2.資料庫單行更新 大量的 update 庫存表 set 剩餘數量=剩餘數量-1 where 商品ID=? 這種單行更新,有行鎖,會阻塞其他事務,佔用寶貴的資料庫處理能力.

解決思路

1.Web伺服器叢集層,解除安裝流量

海量的使用者秒殺請求,本質上是一個排序,先到先得. 但是如此之多的請求,完全響應,難度又很大. 所以在Web伺服器叢集,可以考慮解除安裝流量. 比如每十個請求,隨機拋棄九個,只放行一個請求到後續處理環節. 把秒殺的排序模式,變為隨機抽獎的模式.

2.Web伺服器叢集層,縮小鎖範圍. 每次秒殺活動開始之前.先計算活動推出的商品數量,然後分配一個限額到每個Web伺服器. 比如一個活動推出秒殺商品 電視,手機,衣服各1000件,那麼每臺伺服器的限額就是125件. 將這個限額寫入ZooKeeper,Web伺服器監聽到限額的變化,就會重新初始化各自的商品剩餘數量.

模擬例項

private static ConcurrentHashMap<
String,Integer> map=new ConcurrentHashMap<String, Integer>(); private void zooKeeperHandle(){ //將ZooKeeper的變化,初始化到Web伺服器全域性容器 map.put("電視機", 125); map.put("手機", 125); map.put("衣服", 125); }

假設使用者請求秒殺電視機,它只是鎖了該Web伺服器電視機的數量。(該Web伺服器手機和衣服還可以繼續併發處理,當然其他的Web伺服器也在同時處理電視機的秒殺請求) 這樣縮小了鎖定的範圍,增加了系統處理的吞吐量.

如果這個剩餘數量大於零,則將使用者ID放入電視機購買佇列,
然後告知使用者秒殺成功如果這個剩餘數量等於零,則告知使用者秒殺失敗.
即便別的Web伺服器還有電視機的剩餘配額.

3.ZooKeeper層,ZooKeeper變更庫存資訊 假設活動期間,需要修改庫存資訊。 兩種可能, 第一種,該商品已經賣了500件,電商不想繼續賣了. 第二種,從倉庫中又找到了一些積壓庫存..

兩種情況,都直接修改ZooKeeper中相應商品的配額.
Web伺服器會監聽變化,並重新初始化全域性容器.

4.訊息佇列層,多消費者處理
消費者主要是從佇列獲取購買請求,傳送至資料庫
扣減資料庫庫存
寫訂單明細記錄

5.資料庫層,使用儲存過程代替JDBC呼叫 由於使用了多消費者處理同一佇列,增加吞吐量,避免佇列堆積過大. 但是多消費者,必然導致資料庫出現單行更新問題(不推薦)

單行更新問題就是多個執行緒,併發修改同一條記錄,導致事務相互阻塞.浪費了資料庫寶貴的處理能力.