秒殺程序數據庫設計

        上個月有幸去騰訊逛了一圈,面試一個職位,雖然沒被錄取但是過程總體來講還是愉快的。面試過程中面試我的小朋友(看年齡大概在26,7歲)問了我一個關於秒殺的問題,他說騰訊遊戲經常會有秒殺的活動,很多次會導致服務器死鎖或壓力太大,應該如何設計減輕數據庫服務器壓力。當然因爲面試的是PHP職位,我做的是C#和JAVA我知道應該沒機會所以本不想太過“配合”的回答,但是看面試我的小朋友看我好像很不削的樣子(可能因爲面試的是PHP職位而且一上來就讓我做題目,雖然我有點不情願做題但是畢竟是騰訊還是做了但是PHP接觸的真的不多所以題目幾乎是連蒙帶猜的完成的,估計不是很好看),所以還是認真想了想解決方案。

        秒殺說到底就是瞬間大規模訪問,導致的壓力,前端我們可以使用集羣技術,數據庫呢?拆表?是個方法,但是如果只是簡單拆表仍然會有問題,畢竟秒殺商品被記錄到表中後用戶秒殺必定是需要通過修改表中已有的秒殺商品記錄來確定這個商品是否已經被秒走。爲了防止搶到同一條記錄加鎖是必須。而數據庫一鎖性能問題就來了。那怎麼辦呢?我想了一個方法(至少有一點可以確定騰訊遊戲沒有用這個方法解決),秒殺時並不是立刻去修改數據庫中記錄(進行update操作),而是先向一張表中插入一條記錄,類似進入等待隊列,爲了防止大規模插入操作導致鎖表我們可以將隊列表拆成多張相同結構表。有一個job會不斷讀取這些隊列表並按照插入時間排列計算那些記錄被秒殺成功。而客戶端在點擊秒殺按鈕後斷開連接,幾秒後再次通過查詢語句來查詢結果,並返回給前臺客戶。

         這樣做的好處秒殺過程是分段的,前臺用戶在秒殺時僅是向(多張隊列表中)某一張隊列表中插入一條記錄,之後便斷開本次連接進入等待,job程序通過合併查詢將多張秒殺表合併按插入時間排序,按規則得出秒殺成功的用戶並修改秒殺商品表,表明此商品已被秒殺,前臺程序在等待幾秒後查詢秒殺商品表獲得自己是否已秒殺成功。

         因爲第一步僅僅是插入操作,無需擔心同步操作帶來的髒數據問題,所以我們可以通過拆表來分散壓力降低隔離等級。更新操作是有一個單獨的job程序完成的,因爲只有一個程序會去改記錄所以就不存在鎖表問題。最後前臺通過查詢語句來獲取結果,因爲查詢商品秒殺結果也不需要任何的順序只需要知道是不是你自己搶到的就好,所以可以使用with(nolock)一類的忽略鎖機制來執行。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章