重學SpringBoot. step7 高併發 秒殺
阿新 • • 發佈:2022-05-11
高併發
高併發最容易出現的問題就是資料安全能不能得到保障。
你需要保證速度,又需要保證資料安全,那麼速度也必然會有所下降。
所以最簡單的辦法就是提升硬體。或者把Mysql換成MongoDB,加個Redis,等等。
其實最好的辦法就是加Redis,因為你的資料的佔用時間不會太長,也就沒有什麼影響,任務可以等到後面再處理資料。
書上的思路上,先把資料存到Redis,然後再凌晨一點時候,沒有什麼人的時候,再用空餘的資源去處理這些資料。
但要思考的還是資料安全的問題,Redis萬一掛了怎麼辦?當然這些問題不是高併發目標要解決的問題。
現在是使用SpringBoot相關的技術來實現一個1000到2000的併發的解決方案。
我在實操的時候,2000的併發,會有600多是伺服器無法處理的,因為超時了,等等。整體而言就是反應不過來,伺服器如果不用快取技術,除非提升硬體,那麼根本處理不過來。
叢集?是個好辦法,建議把伺服器全升級到執行緒撕裂者。然後配一百個叢集。
直接用Redis
業務需求:秒殺搶購
思路:獲取庫存,然後判斷Redis列表內的數量是否等於庫存,如果不等於,就新增,如果等於,就是搶購失敗。
快取後的資料直接用訊息佇列控制主機的服務來處理這些資料。單機的話,可以用定時器到凌晨1點,再用空餘的資源來解決這些問題。
程式碼實現可能都不用看了。
不過我之前學的時候,還有一種方案是引入這個任務佇列,不過我好像沒學會用Netty怎麼來操作這種秒殺。那樣就更為底層了。
下面是傳統的基於版本號的秒殺。
public boolean buyId(Integer id) { long start = System.currentTimeMillis(); while (true) { long end = System.currentTimeMillis(); if((end - start) > 100) return false; Product product = this.getById(id); if(product.getStock() < 1){ return false; } // 指定 delete Flag為 version吧 int version = product.getDeleteFlag(); product.setStock(product.getStock()-1); product.setDeleteFlag(version+1); boolean result = this.update(product,new QueryWrapper<Product>().lambda().eq(Product::getId,product.getId()).eq(Product::getDeleteFlag,product.getDeleteFlag()-1)); if(!result) continue; return true; } }