1. 程式人生 > 其它 >重學SpringBoot. step7 高併發 秒殺

重學SpringBoot. step7 高併發 秒殺

高併發

高併發最容易出現的問題就是資料安全能不能得到保障。

你需要保證速度,又需要保證資料安全,那麼速度也必然會有所下降。

所以最簡單的辦法就是提升硬體。或者把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;
    }

}