Java高併發秒殺優化

只要拋出異常事務就會回滾嗎?前端

Spring 的事務默認是發生了RunTimeException纔會回滾,發生了其餘異常不會回滾數據庫

不是全部的方法都須要事務,如只有一條修改操做、只讀操做json

Service層中的拋出異常是爲了讓Spring可以回滾,Controller層中捕獲異常是爲了將異常轉換爲對應的json供前臺使用。後端

return "detail";  //我認爲是沒有意義的,只是一個字符串而已

優化總結緩存

  • 前端控制

暴露接口,按鈕防重複(點擊一次按鈕後就變成灰色,禁止重複點擊按鈕)服務器

  • 動靜態數據分離

CDN緩存,後端緩存網絡

  • 事務競爭優化

減小事務行級鎖的持有時間併發


Redis屬於NoSQL,即非關係型數據庫,它是key-value型數據庫,是直接在內存中進行存取數據的,因此有着很高的性能。
利用Redis能夠減輕MySQL服務器的壓力,減小了跟數據庫服務器的通訊次數。秒殺的瓶頸就在於跟數據庫服務器的通訊速度(MySQL自己的主鍵查詢很是快)
Redis有不少客戶端,咱們的項目是用Java語言寫的,天然選擇對應Java語言的客戶端,而官網最推薦咱們的Java客戶端是Jedis,在pom.xml裏配置了Jedis依賴就可使用它了,記得要先開啓Redis的服務器,Jedis才能鏈接到服務器。
因爲Jedis並無實現內部序列化操做,而Java內置的序列化機制性能又不高,咱們是一個秒殺系統,須要考慮高併發優化,在這裏咱們採用開源社區提供的更高性能的自定義序列化工具protostuff。
使用Redis優化地址暴露接口
本來查詢秒殺商品時是經過主鍵直接去數據庫查詢的,選擇將數據緩存在Redis,在查詢秒殺商品時先去Redis緩存中查詢,以此下降數據庫的壓力。若是在緩存中查詢不到數據再去數據庫中查詢,再將查詢到的數據放入Redis緩存中,這樣下次就能夠直接去緩存中直接查詢到。
 

第一:經過Jedis儲存對象的方式有大概三種高併發

  1. 本項目採用的方式:將對象序列化成byte字節,最終存byte字節;
  2. 對象轉hashmap,也就是你想表達的hash的形式,最終存map;
  3. 對象轉json,最終存json,其實也就是字符串

3. 秒殺操做——併發優化

3.1 簡單優化

爲何要先insert再update
首先是在更新操做的時候給行加鎖,插入並不會加鎖,若是更新操做在前,那麼就須要執行完更新和插入之後事務提交或回滾才釋放鎖。而若是插入在前,更新在後,那麼只有在更新時纔會加行鎖,以後在更新完之後事務提交或回滾釋放鎖。
在這裏,插入是能夠並行的,而更新因爲會加行級鎖是串行的。
也就是說是更新在前加鎖和釋放鎖之間兩次的網絡延遲和GC,若是插入在前則加鎖和釋放鎖之間只有一次的網絡延遲和GC,也就是減小的持有鎖的時間。
這裏先insert並非忽略了庫存不足的狀況,而是由於insert和update是在同一個事務裏,光是insert並不必定會提交,只有在update成功纔會提交,因此並不會形成過量插入秒殺成功記錄。
相關文章
相關標籤/搜索