如何使用redis實現分佈式鎖

如何使用redis實現分佈式鎖

爲什麼要使用分佈式鎖?場景?

涉及到重複提交或交易的地方

場景一:提交訂單

提交訂單

用戶購買商品,下單時,有時不小心連續點擊多次;
或者網絡不好,導致用戶以爲沒有提交,重複點擊提交按鈕;
網絡層面比如nginx的重發.

對於分佈式系統,提交訂單的n個請求可能會被不同的服務單體消費,
那麼就會生成多個相同(除了訂單號,其他購買信息完全一樣)的訂單,

後果:

  1. 產生了髒數據,影響了校驗,有時甚至會影響正常業務的執行;
  2. 前端用戶會發現產生了多個訂單,讓用戶迷茫,不知所措.

場景二:

有哪些解決方法呢?

使用其他方式實現分佈式鎖

參考: 分佈式系統後臺如何防止重複提交

使用redis

流程如下:


代碼如下:

/***
     * 提交訂單
     * @param model
     * @param request
     * @param response
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/order/submit/json", produces = SystemHWUtil.RESPONSE_CONTENTTYPE_JSON_UTF)
    public String jsonSubmitOrder2(Model model, HttpServletRequest request, HttpServletResponse response
            , @RequestParam(required = false) Boolean del) {
        //可以抽取出常量
        String lockUniquePrefix = "lock";

        Jedis jedis = getJedis();
        //1. 獲取鎖
        // key:"lock"+方法名,value:時間戳
        //NX -- Only set the key if it does not already exist.
        String key = lockUniquePrefix + Thread.currentThread().getStackTrace()[1].getMethodName();
        //"OK":成功;null:失敗
        String result = jedis.set(key, "aa", "NX", "EX"/*seconds*/, 1000);
        Const.pool.returnResource(jedis);
        boolean success = "OK".equals(result);
        System.out.println("success :" + success);
        System.out.println("result :" + result);

        if (success) {
            //2. 執行具體業務邏輯
            //...
        }


        //3. 業務邏輯執行完成之後,釋放鎖
        
        jedis = getJedis();
        jedis.del(key);
        Const.pool.returnResource(jedis);
        

        return BaseResponseDto.put2("result", result).put("success", success).toJson();
    }

 


 爲什麼jedis.set方法中要使用"NX"呢? 因爲只有當key不存在時,操作纔會成功, 即key不存在時,jedis.set返回"OK",表示獲取鎖成功; key存在時,jedis.set返回null,表示獲取鎖失敗

爲什麼要使用redis

因爲關於鎖有兩個重要的操作:

  1. 獲取鎖;
  2. 釋放鎖.

在分佈式環境,必須保證這兩個操作是原子性的,
即不能把獲取鎖分爲兩步:先查詢,再add.
同時,獲取鎖時,能夠設置有效期.

分佈式鎖實現時要注意的問題

  1. 提供鎖的服務必須是一個唯一的服務,即負載均衡的n個服務單體訪問的是同一個服務;
  2. 能夠設置鎖的有效期,不能讓某個消費者永久地持有鎖;
  3. 能夠釋放鎖;
  4. 不同的業務邏輯競爭不同的鎖,必須下單和減庫存 使用不同的鎖.

redis 還能做什麼

redis除了可以實現分佈式鎖,還能作爲緩存服務器,
在實現需求中,我經常把一些容易變化的配置放在redis中, 這樣當產品經理需求變更時,我只需修改redis,即時生效,不用上線

參考:

https://my.oschina.net/huangweiindex/blog/1853160

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章