秒殺系統的資料庫中的庫存加減操作是最為關鍵的點。12年天貓雙十一的超賣事件,對平台的負面影響是非常巨大的。
資料庫裡做庫存扣減,簡單的可以用以下sql來說明:
update stock_table set inventory=inventory-1 where item_id=xx and inventory>0
該sql的含義是,對於指定商品在庫存充足情況下扣減庫存,該語句在mysql資料庫中執行可以保證其原子性(隔離級別大於等於read-committed)。
在秒殺業務場景下,對某個商品進行高併發扣減庫存時,mysql將會成為高併發業務的瓶頸:
高併發場景下的資料庫瓶頸
mysql使用wal(write ahead log)方式來實現資料的持久化,即事務提交後,被更新資料寫到硬碟後,才能返回成功。而硬碟的讀寫是整個服務中最耗時的操作,也是秒殺系統的瓶頸所在。
為了提高效能,針對資料庫的優化就提到整個寫庫操作之前,即引入組提交機制,同時提交多個事務,這樣多個寫操作只會有一次寫硬碟操作,對於該組事務,耗時仍然是一次硬碟,但提公升了整個系統的吞吐量。
組提交機制並不是萬能的,若事務之間存在衝突(比如針對同一商品進行庫存修改),那麼基於悲觀鎖進行併發控制的mysql,只會排隊執行,即後乙個事務要等前乙個事務提交完成後才能執行。使用扣減庫存的sql舉例如下:
找到並對商品記錄加鎖 --> 判斷庫存餘量 --> 修改庫存餘量 --> 寫盤 --> 釋放鎖
針對同乙個熱點商品的多個併發事務,在上面加鎖和釋放鎖之間的這段操作是無法做到併發執行的,此時系統的瓶頸就是磁碟io。在大量併發事務都在爭搶行鎖的情況下,情況會進一步惡化,系統負載會突增,再加上鎖衝突檢測等額外代價,可能系統的整體吞吐會降低至個位數。
超賣風險
資料庫一般會建立主備,在主庫和從庫間進行資料同步時會有一定的延遲,而一般系統中會採用從庫讀,主庫寫的方式。在高併發場景下,若主庫資料未實時同步到從庫,這樣就會有超賣的風險。例如主庫宕機後,部分binlog未及時同步到從庫,此時從庫切換為主庫,恢復未同步成功的binlog,即已經扣減的庫存,此時就會有超賣風險。
秒殺系統 mysql 秒殺系統之資料庫優化
由之前的文章,我們可以看到資料庫為保證資料持久化,需要落盤,而該操作將會成為秒殺系統的瓶頸所在。那在資料庫層面如何進行優化呢,可以分為以下幾點來考慮 庫存拆分 將同乙個商品的庫存記錄拆分為多行甚至多個表,降低併發衝突。舉乙個簡單的例子 對業務請求中的userid計算hash取模後確定查詢哪個庫那張表...
秒殺 秒殺系統 優化之路
1 im系統,例如qq或者微博,每個人都讀自己的資料 好友列表 群列表 個人資訊 2 微博系統,每個人讀你關注的人的資料,乙個人讀多個人的資料 3 秒殺系統,庫存只有乙份,所有人會在集中的時間讀和寫這些資料,多個人讀乙個資料。例如 小公尺手機每週二的秒殺,可能手機只有1萬部,但瞬時進入的流量可能是幾...
秒殺系統思路
隨著電商的發展,秒殺系統已經發展成為電商必不可少的組成部分,如小公尺手機的秒殺,12306的搶票,這些系統的共同特點都是 庫存只有乙份,瞬時流量非常大,所有人會在集中的時間讀和寫這些資料,多個人讀乙個資料 讀寫衝突,鎖非常嚴重,這是秒殺業務難的地方。那我們怎麼構建秒殺業務的架構呢?構建架構需要總體做...