日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

基于redis的分布式锁

發布時間:2024/8/23 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 基于redis的分布式锁 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

概述

在之前, 我也使用redis做過分布式鎖, 當時的做法是這樣的:

  • setnx: 向 redis中創建一個過期時間為1s的key, 若創建失敗, 則鎖獲取失敗
  • expire: 獲取鎖成功后, 給鎖增加過期時間
  • del: 處理后釋放鎖
  • 當時覺得貌似沒什么問題. 是我太天真了, 今天突然想到, 恩, 有問題.

    問題

    1.如果在第一步之后, 程序崩了, 沒有給鎖設置過期時間, 導致所有后續操作都無法正常獲取到鎖. 怎么破?

    2.在A成功上鎖后, 因為IO阻塞等原因, 執行時間有點長, 鎖已經過期了, 這時B過來成功上鎖, A在釋放鎖的時候釋放的就是B的鎖.

    3.redis突然掛了. 如果redis突然掛了, 怎么辦? 當然, 可以增加redis節點, 主節點掛了, 從節點立刻補上. 但是, 主節點的數據同步到從節點也是需要時間的吧. 假設一個場景:

  • A在主節點設置鎖
  • 主節點還沒有同步數據的時候, 掛了
  • 從節點接替成為主節點
  • B在主節點也成功設置了鎖
  • 這個時候, 分布式鎖就失效了.

    解決

    那么有沒有辦法解決上面的問題呢? 我到萬能的谷歌上找了一下, 恩, 真的有.

    上面的問題一個一個解決.

    問題一

    如何避免沒有給鎖設置過期時間的問題?

    其實看看就知道了, 問題出在設置key和設置value分成兩條命令執行, 所以導致如果在 setnx命令執行過后, 程序崩潰, expire命令沒有正常執行, 將其合并為一條命令就好啦.

    set key value NX PX 5000

    其中NX表示存在則不設置, PX表示過期時間.

    如此, 至少可以保證不會出現沒有過期時間的鎖了

    問題二

    如何避免A釋放了B的鎖.

    如何避免釋放了其他人的鎖呢? 換個問題, 如何保證這個鎖是你加的呢? so easy, 加鎖的時候, 講value值設置成一個只有我知道的隨機數字, 釋放的時候看看值是不是我的就行了.

    如此在釋放的時候需要兩步操作:

  • 獲取redis鎖的值
  • 若值是我的, 釋放鎖
  • 當然, 為了保證釋放鎖操作的原子性, 這兩步操作最好也能合并為一步操作. 那redis如何實現值是否相同的判斷呢? Lua腳本.

    簡單介紹一下

    eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 argv1 argv2 # 看懂了吧, 哈哈 # eval 是redis內置的命令 # 第一個參數是運行的腳本邏輯 # 第二個參數表示后面有幾個key # 第五個參數開始就是附加參數, 在腳本邏輯中使用的

    所以, 腳本內容如下:

    if redis.call("get",KEYS[1]) == ARGV[1] thenreturn redis.call("del",KEYS[1]) elsereturn 0 end

    如此, 至少可以保證不會出現A釋放了B鎖的情況了

    問題三

    如何保證在主節點掛掉的時候, 從節點接替后, 不會重復獲得鎖?

    官網上提供了一個方法, 從多個redis實例同時獲取鎖. 因為我沒看太明白, 之后看懂了在說吧. 過…

    其實, 如果不是處理金錢這種不容出錯的業務, 這種小概率事件個人覺得還是可以容忍的.


    總結

    最終, 在redis單機下實現的分布式鎖操作如下:

    # 獲取分布式鎖,過期時間可調 set lock_key random_value NX PX 5000 # ...do something # 釋放分布式鎖 eval "if redis.call("get",KEYS[1]) == ARGV[1] then return redis.call("del",KEYS[1]) else return 0 end" 1 lock_key random_value

    總結

    以上是生活随笔為你收集整理的基于redis的分布式锁的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。