用壓測模擬並發、並發處理(synchronized,redis分布式鎖)


使用工具:Apache an

測壓命令: ab -n 100 -c 100 http://www.baidu.com -n代表模擬100個請求,-c代表模擬100個並發,相當於100個人同時訪問

    ab -t 60 -c 100 http://www.baidu.com 60秒100個並發,不斷發送請求

  

並發處理:

1.加synchronized鎖單線程處理、缺點: 無法做到細粒度控制,處理速度也會很慢  只適合單點的情況

2.redis分布式鎖:

可以支撐每秒10多萬的並發,支持分布式,可以更細粒的控制代碼(多台機器上多個線程對一個數據進行操作的互斥)

SETNX key value

將key設置值為value,如果key不存在,這種情況下等同於SET命令,當key存在時,什么也不做

GETSET key value

自動將key對應到value並且返回原來key和對應的value,如果key存在但是對應的value不是字符串,就返回錯誤

DEMO演示:

加鎖處理方法:

@Component
@Slf4j
public class RedisLock {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    //加鎖
    /*
    * @param key id
    * @param value 當前時間+超時時間
    *
    * */
    public  boolean lock(String key,String value){
        if (stringRedisTemplate.opsForValue().setIfAbsent(key,value)){
            return true;//加鎖成功就返回true
        }
        //不加下面這個可能出現死鎖情況
     //代碼value加了過期時間* @param value 當前時間+超時時間
    //獲取上一個鎖的時間,並判斷是否小於當前時間,小於就下一步判斷,就返回true加鎖成功
        //currentValue=A 這兩個線程的value都是B 其中一個線程拿到鎖
        String currentValue=stringRedisTemplate.opsForValue().get(key);
        //如果鎖過期
        if (!StringUtils.isEmpty(currentValue)
                && Long.parseLong(currentValue)<System.currentTimeMillis()){//存儲時間要小於當前時間
    //出現死鎖的另一種情況,當多個線程進來后都沒有返回true,接着往下執行,執行代碼有先后,而if判斷里只有一個線程才能滿足條件
    //oldValue=currentValue
    //多個線程進來后只有其中一個線程能拿到鎖(即oldValue=currentValue),其他的返回false
            //獲取上一個鎖的時間
            String oldValue=stringRedisTemplate.opsForValue().getAndSet(key,value);
            if (!StringUtils.isEmpty(oldValue)&& oldValue.equals(currentValue)){//上一個時間不為空,並且等於當前時間
                return true;
            }

        }
        return  false;//失敗返回false
    }



    //解鎖
    public void unlock(String key,String value){//執行刪除可能出現異常需要捕獲
        try {
            String currentValue = stringRedisTemplate.opsForValue().get(key);
            if (!StringUtils.isEmpty(currentValue) && currentValue.equals(value)) {//如果不為空,就刪除鎖
                stringRedisTemplate.opsForValue().getOperations().delete(key);
            }
        }catch (Exception e){
            log.error("[redis分布式鎖] 解鎖",e);
        }
    }
}

  

 

  

//秒殺demo
pprivate static final int TIMEOUT=10*1000;//超時時間設置為10s
@Autowrite
private RedisLock redisLock;
public void method(String  id){

//加鎖-死鎖出現:即在加鎖后運行程序出現意外報了異常,而此時還沒調用解鎖方法
//那么在下一個線程調用加鎖方法是就不能set,直接返回fale,然后一直停留在加鎖失敗狀態 這就出現了死鎖
long time=System.currentTimeMillis()+TIMEOUT;
//如果加鎖不成功就拋出異常

 if(!redisLock.lock.get(id,String.valueof(time))){
throw new WechatSellException(101,"哎喲喂,人也太多了,換個姿勢再試試");
}
//加鎖成功就實現業務代碼處理

//1.查詢該商品庫存,為0表示活動結束


//2.下單


3.扣庫存


//解鎖
redisLock.unlock(id,String.valueof(time)));

}

  

 

  

  

   


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM