程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> MYSQL數據庫 >> MySQL綜合教程 >> 就這麼簡單:秒殺應用的MySQL數據庫優化(1)

就這麼簡單:秒殺應用的MySQL數據庫優化(1)

編輯:MySQL綜合教程

就這麼簡單:秒殺應用的MySQL數據庫優化(1)


關於秒殺

隨著雙11活動的不斷發展,小米饑餓營銷模式的興起,“秒殺”已經成為一個熱點詞匯。在一些活動中,熱銷商品會以驚人的速度售罄,比如最近筆者在搶購美圖M4手機,12點開賣,1分鐘之內就被售罄。

秒殺的實現

對於關注數據庫的筆者來說,更關心的是如何高效的實現秒殺應用。之前淘寶在2013年的數據庫大會上分享過他們的秒殺方案,修改MySQL數據庫源碼來實現高效的秒殺應用。但是,那篇分享過於高大上,沒有給出具體的實現過程。另外,從其他渠道打聽到的是這個方案並沒有在生產環境上線,不知道有沒有其他知道內幕的小伙伴,具體來說說淘寶的方案是否有上線。

當然,有多種方法來優化秒殺應用,比如使用memcached的CAS功能,但是這些方法都不能實現事務的特性。對於深受Jim Gray事務處理教育長大的一代,筆者覺得任何事情都應該事務的,不支持事務只不過能取得暫時的勝利,整個世界的哲學應該就是事務,即要麼全做,要麼全不做,不要處於一個中間狀態。筆者的為人哲學就是,要麼不去設定一個目標,否則這個目標一定會去實現。比如,筆者決定去讀博,那麼一定會完成這個學業。

筆者感覺雖然淘寶沒有給出具體的實現方式,但是拋出了秒殺應用對於數據庫壓力的問題所在,即大並發量下更新同一行數據的壓力。例如並發執行如下的SQL語句模擬秒殺場景:

  1. BEGIN; 
  2.  
  3. INSERT INTO stock_log VALUES 
  4.  
  5. SELECT count FROM stock WHERE id=1 AND count>0 FOR UPDATE; 
  6.  
  7. UPDATE stock SET count = count -1 WHERE id=1 AND count > 0; 
  8.  
  9. COMMIT; 

在做秒殺時,最主要是對庫存表進行操作,在操作前可能需要插入一些其他操作,比如日志等,然後就是對庫存表進行更新。下圖顯示增大並發量的情況下,事務處理的性能:

InsideMySQL

顯而易見的是隨著並發量的增大,事務處理的性能越差。這和淘寶之前分享的數據基本一致。導致其中的原因就是秒殺是對同一件商品進行更新,需要對同一行記錄加鎖,因此秒殺操作雖然是並行的,但是在數據庫層面是串行的。

隨著並發的不斷增大,不斷發生事務的鎖等待與喚醒操作,導致性能的急劇下降。如果通過perf工具來觀察的話,應該可以觀察到類似如下的內容:

  1.  
  2. 59.06% mysqld mysqld [.] lock_deadlock_recursive 
  3.  
  4. 16.63% mysqld libc-2.13.so [.] 0x115171 3.09% mysqld mysqld [.] lock_rec_get_prev 
  5.  
  6. 2.96% mysqld mysqld [.] my_strnncollsp_utf8 
  7.  
  8. ...... 

可以發現鎖的死鎖檢測占據了大部分的CPU時間,究其原因,就是因為鎖等待。

innodb_thread_concurrency

有小伙伴或許會知道可以通過innodb_thread_concurrency參數來控制InnoDB存儲引擎層的並發量。的確,通過這個參數可以限制進入InnoDB引擎層的事務數量,對比測試的話,性能上的確會有一定的提升:

可以發現,將innodb_thread_concurrency設置為16,性能的確會有一定的提升。並發線程數在128的時候,TPS從原有的4300提升為了7200,將近有65%的性能提升。但是在256線程之後,性能依舊堪憂。

導致上述的原因是雖然在InnoDB存儲引擎層做了“限流”,但是MySQL數據庫上層的線程依然需要等待喚醒。




  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved