日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當前位置:首頁 > 科技  > 軟件

用Go語言&&Redis實現分布式鎖,我還是第一次

來源: 責編: 時間:2024-04-19 09:28:46 183觀看
導讀一、為什么需要分布式鎖共享資源訪問控制: 當多個節點需要同時訪問共享資源時,為了避免并發寫入導致數據不一致,需要使用分布式鎖確保同時只有一個節點可以寫入或修改共享資源。避免重復執行: 在分布式系統中,某些操作可能

一、為什么需要分布式鎖

共享資源訪問控制: 當多個節點需要同時訪問共享資源時,為了避免并發寫入導致數據不一致,需要使用分布式鎖確保同時只有一個節點可以寫入或修改共享資源。sXw28資訊網——每日最新資訊28at.com

避免重復執行: 在分布式系統中,某些操作可能需要在整個系統中只執行一次,比如定時任務、數據初始化等。為了避免多個節點同時執行這些操作,需要使用分布式鎖來確保只有一個節點可以執行。sXw28資訊網——每日最新資訊28at.com

任務協調: 在分布式任務隊列中,多個節點競爭執行任務時,可能需要對任務進行加鎖,以確保每個任務只被一個節點執行,避免重復執行或者操作沖突。sXw28資訊網——每日最新資訊28at.com

防止死鎖: 在分布式系統中,由于網絡延遲、節點故障等原因,可能會導致死鎖情況的發生。分布式鎖可以用來避免死鎖的發生,通過設置合理的超時時間和重試機制,確保鎖在一定時間內被釋放。sXw28資訊網——每日最新資訊28at.com

分布式系統中共享同一個資源時,就需要分布式鎖來確保變更資源的一致性。這就是為什么要用到分布式鎖的原因咯。sXw28資訊網——每日最新資訊28at.com

二、分布式鎖需要具備特性

1 互斥性(Mutual Exclusion): 在任何時刻,只能有一個客戶端持有鎖,其他客戶端不能同時持有該鎖。這是最基本的鎖特性,確保在同一時間只有一個客戶端能夠訪問共享資源。sXw28資訊網——每日最新資訊28at.com

2 安全性(Safety): 在鎖被釋放之前,任何其他客戶端都不能獲得該鎖。即使是在網絡分區、節點故障等異常情況下,也要確保鎖的安全性,避免數據不一致或者操作沖突。sXw28資訊網——每日最新資訊28at.com

3 活性(Liveness): 鎖應該能夠在合理的時間內被獲取,避免長時間的等待導致死鎖或者無法響應其他客戶端請求?;钚砸舶ㄔ阪i被釋放后,其他客戶端能夠盡快地獲取到該鎖。sXw28資訊網——每日最新資訊28at.com

4 容錯性(Fault Tolerance): 分布式系統中可能會發生網絡分區、節點故障等異常情況,分布式鎖需要具備容錯性,能夠在這些異常情況下正確地工作。比如,鎖的實現應該能夠處理網絡分區導致的消息丟失或者超時等情況。sXw28資訊網——每日最新資訊28at.com

5 性能(Performance): 鎖的實現應該盡可能地減少鎖競爭和通信開銷,提高系統的性能。例如,可以使用高效的算法和數據結構來減少鎖的持有時間和等待時間,或者采用緩存和批處理等技術來減少通信開銷。sXw28資訊網——每日最新資訊28at.com

6 可擴展性(Scalability): 鎖的實現應該能夠隨著系統規模的增長而擴展,確保在高并發和大規模的分布式環境下仍然能夠保持良好的性能和可用性。sXw28資訊網——每日最新資訊28at.com

三、實現 Redis 鎖應先掌握的知識點

set 命令

SET key value [EX seconds] [PX milliseconds] [NX|XX]
  • EX second :設置鍵的過期時間為 second 秒。SET key value EX second 效果等同于 SETEX key second value。
  • PX millisecond :設置鍵的過期時間為 millisecond 毫秒。SET key value PX millisecond ,效果等同于 PSETEX key millisecond value 。
  • NX :鍵不存在時,才對鍵進行設置操作。SET key value NX 等同于 SETNX key value 。
  • XX :鍵已經存在時,才對鍵進行設置操作。

Redis.lua 腳本

我們可以使用 redis lua 腳本,將一系列命令操作封裝成 pipline,實現整體操作的原子性。sXw28資訊網——每日最新資訊28at.com

加鎖的整個流程,詳細原理說明看注釋sXw28資訊網——每日最新資訊28at.com

-- Lua 腳本實現 Redis 分布式鎖-- 生成唯一標識local requestId = ARGV[1]-- 嘗試獲取鎖local lockKey = KEYS[1]local lockValue = requestIdlocal lockExpireTime = tonumber(ARGV[2])local result = redis.call('SET', lockKey, lockValue, 'NX', 'PX', lockExpireTime)-- 判斷獲取鎖的結果if result == 'OK' then    -- 獲取鎖成功,設置鎖的過期時間    return 'OK'else    -- 獲取鎖失敗    return 'FAIL'end

1 生成唯一標識: 首先,在客戶端生成一個唯一的標識,可以是 UUID、Snowflake 算法生成的分布式 ID 等。sXw28資訊網——每日最新資訊28at.com

2 嘗試獲取鎖: 客戶端將生成的唯一標識作為參數,調用 Redis 的 SET 命令嘗試獲取鎖??梢允褂?nbsp;NX(如果鍵不存在則設置)和 PX(設置鍵的過期時間)選項,確保只有一個客戶端能夠成功獲取到鎖。sXw28資訊網——每日最新資訊28at.com

3 判斷獲取鎖的結果: 如果獲取鎖成功,SET 命令會返回 OK,表示當前客戶端成功獲取了鎖。如果獲取鎖失敗,說明已經有其他客戶端持有了鎖,此時客戶端需要進行等待或者返回失敗。sXw28資訊網——每日最新資訊28at.com

4 設置鎖的過期時間: 在成功獲取鎖之后,客戶端需要設置鎖的過期時間,以防止因為客戶端崩潰或者其他原因導致鎖一直占用,造成死鎖。sXw28資訊網——每日最新資訊28at.com

5 返回獲取鎖的結果: 根據 SET 命令的返回值,客戶端判斷是否成功獲取到了鎖,并將結果返回給調用方。sXw28資訊網——每日最新資訊28at.com

加鎖流程圖sXw28資訊網——每日最新資訊28at.com

圖片圖片sXw28資訊網——每日最新資訊28at.com

解鎖流程sXw28資訊網——每日最新資訊28at.com

if redis.call("get", KEYS[1]) == ARGV[1] then    return redis.call("del", KEYS[1])else    return 0end

1 使用 KEYS[1] 獲取傳入的鎖鍵名。sXw28資訊網——每日最新資訊28at.com

2 使用 ARGV[1] 獲取傳入的鎖值(即加鎖時設置的唯一標識)。sXw28資訊網——每日最新資訊28at.com

3 判斷當前鎖是否存在且鎖值與傳入的鎖值相同,若是,則調用 DEL 命令刪除該鎖,并返回 1 表示解鎖成功。sXw28資訊網——每日最新資訊28at.com

4 若鎖不存在或鎖值不匹配,則返回 0 表示解鎖失敗。sXw28資訊網——每日最新資訊28at.com

解鎖的流程圖sXw28資訊網——每日最新資訊28at.com

圖片圖片sXw28資訊網——每日最新資訊28at.com

源碼解析sXw28資訊網——每日最新資訊28at.com

package redisimport (    "math/rand"    "strconv"    "sync/atomic"    "time"    red "github.com/go-redis/redis"    "github.com/tal-tech/go-zero/core/logx")const (    letters  = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"    randomLen = 16    // 默認超時時間,用來防止死鎖    tolerance       = 300 // milliseconds    millisPerSecond = 800    lockCommand = `if redis.call("GET", KEYS[1]) == ARGV[1] then    redis.call("SET", KEYS[1], ARGV[1], "PX", ARGV[2])    return "OK"else    return redis.call("SET", KEYS[1], ARGV[1], "NX", "PX", ARGV[2])end`    delCommand = `if redis.call("GET", KEYS[1]) == ARGV[1] then    return redis.call("DEL", KEYS[1])else    return 0end`)type redisLock struct {    // redis客戶端    store *Redis    // 超時時間    seconds uint32    // 鎖key    keys string    // 鎖value,防止鎖被別人獲取到    value string}func init() {    rand.Seed(time.Now().UnixNano())}// NewRedisLock returns a RedisLock.func NewRedisLock(store *Redis, keys string) *RedisLock {    return &RedisLock{        store: store,        keys:   keys,        // 獲取鎖時,鎖的值通過隨機字符串生成        // 實際上go-zero提供更加高效的隨機字符串生成方式        // 見core/stringx/random.go:Randn        value:    randomStr(randomLen),    }}// Acquire acquires the lock.// 加鎖func (rl *RedisLock) Acquire() (bool, error) {    // 獲取過期時間    seconds := atomic.LoadUint32(&rl.seconds)    // 默認鎖過期時間為500ms,防止死鎖    resp, err := rl.store.Eval(lockCommand, []string{rl.keys}, []string{        rl.value, strconv.Itoa(int(seconds)*millisPerSecond + tolerance),    })    if err == red.Nil {        return false, nil    } else if err != nil {        logx.Errorf("Error on lock for %s, %s", rl.key, err.Error())        return false, err    } else if resp == nil {        return false, nil    }    reply, ok := resp.(string)    if ok && reply == "OK" {        return true, nil    }    logx.Errorf("Unknown reply lock for %s: %v", rl.keys, resp)    return false, nil}// Release releases the lock.// 釋放鎖func (rl *RedisLock) Release() (bool, error) {    resp, err := rl.store.Eval(delCommand, []string{rl.keys}, []string{rl.value})    if err != nil {        return false, err    }    reply, ok := resp.(int64)    if !ok {        return false, nil    }    return reply == 1, nil}func randomStr(n int) string {    b := make([]byte, n)    for i := range b {        b[i] = letters[rand.Intn(len(letters))]    }    return string(b)}// SetExpire sets the expire.// 需要注意的是需要在Acquire()之前調用// 不然默認為300ms自動釋放func (rl *RedisLock) SetExpire(seconds int) {    atomic.StoreUint32(&rl.seconds, uint32(seconds))}

這個詳細源碼根據自己的業務需要,可以利用。sXw28資訊網——每日最新資訊28at.com

本文鏈接:http://www.www897cc.com/showinfo-26-84022-0.html用Go語言&&Redis實現分布式鎖,我還是第一次

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: Formik:讓用戶體驗更加出色的表單解決方案

下一篇: 我用這十招,減少了80%的BUG

標簽:
  • 熱門焦點
  • 天貓精靈Sound Pro體驗:智能音箱沒有音質?來聽聽我的

    這幾年除了手機作為智能生活終端最主要的核心之外,第二個可以成為中心點的產品是什么?——是智能音箱。 手機在執行命令的時候有兩種操作方式,手和智能語音助手,而智能音箱只
  • 7月安卓手機好評榜:三星S23Ultra好評率第一

    性能榜和性價比榜之后,我們來看最后的安卓手機好評榜,數據來源安兔兔評測,收集時間2023年7月1日至7月31日,僅限國內市場。第一名:三星Galaxy S23 Ultra好評率:95.71%在即將迎來新
  • CSS單標簽實現轉轉logo

    轉轉品牌升級后更新了全新的Logo,今天我們用純CSS來實現轉轉的新Logo,為了有一定的挑戰性,這里我們只使用一個標簽實現,將最大化的使用CSS能力完成Logo的繪制與動畫效果。新logo
  • 為什么你不應該使用Div作為可點擊元素

    按鈕是為任何網絡應用程序提供交互性的最常見方式。但我們經常傾向于使用其他HTML元素,如 div span 等作為 clickable 元素。但通過這樣做,我們錯過了許多內置瀏覽器的功能。
  • 2023年,我眼中的字節跳動

    此時此刻(2023年7月),字節跳動從未上市,也從未公布過任何官方的上市計劃;但是這并不妨礙它成為中國最受關注的互聯網公司之一。從2016-17年的抖音強勢崛起,到2018年的“頭騰
  • 猿輔導與新東方的兩種“歸途”

    作者|卓心月 出品|零態LT(ID:LingTai_LT)如何成為一家偉大企業?答案一定是對“勢”的把握,這其中最關鍵的當屬對企業戰略的制定,且能夠站在未來看現在,即使這其中的
  • 認真聊聊東方甄選:如何告別低垂的果實

    來源:山核桃作者:財經無忌爆火一年后,俞敏洪和他的東方甄選依舊是頗受外界關心的“網紅”。7月5日至9日,為期5天的東方甄選“甘肅行”首次在自有App內直播,
  • 攜眾多高端產品亮相ChinaJoy,小米帶來一場科技與人文的視聽盛宴

    7月28日,全球數字娛樂領域最具知名度與影響力的年度盛會中國國際數碼互動娛樂展覽會(簡稱ChinaJoy)在上海新國際博覽中心盛大開幕。作為全球領先的科
  • 三星折疊屏手機去年銷售近1000萬臺 今年目標定為1500萬

    7月29日消息,三星率先發力可折疊手機市場,在全球市場已經取得了非常亮眼的成績,接下來會進一步鞏固和擴大這一優勢。三星在推出Galaxy Z Flip5和Galax
Top 主站蜘蛛池模板: 沭阳县| 廉江市| 库尔勒市| 永州市| 鄯善县| 沈阳市| 仁化县| 洱源县| 平邑县| 张北县| 墨竹工卡县| 深泽县| 大悟县| 临猗县| 满洲里市| 澄江县| 游戏| 黑河市| 鄱阳县| 金塔县| 扎赉特旗| 柘荣县| 临夏县| 吕梁市| 杭锦后旗| 宝清县| 个旧市| 堆龙德庆县| 康乐县| 岳阳县| 灵宝市| 乐安县| 宜兴市| 司法| 墨竹工卡县| 元江| 开阳县| 伊春市| 思南县| 托克托县| 乃东县|