返回顶部
首页 > 资讯 > 精选 >怎么用Go+Redis实现分布式锁
  • 803
分享到

怎么用Go+Redis实现分布式锁

2023-06-22 03:06:35 803人浏览 安东尼
摘要

这篇文章主要介绍怎么用Go+Redis实现分布式锁,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!为什么需要分布式锁用户下单锁住 uid,防止重复下单。库存扣减锁住库存,防止超卖。余额扣减锁住账户,防止并发操作。分布式

这篇文章主要介绍怎么用Go+Redis实现分布式,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

    为什么需要分布式锁

    用户下单
    锁住 uid,防止重复下单。

    库存扣减
    锁住库存,防止超卖。

    余额扣减
    锁住账户,防止并发操作。
    分布式系统中共享同一个资源时往往需要分布式锁来保证变更资源一致性。

    分布式锁需要具备特性

    排他性
    锁的基本特性,并且只能被第一个持有者持有。

    防死锁
    高并发场景下临界资源一旦发生死锁非常难以排查,通常可以通过设置超时时间到期自动释放锁来规避。

    可重入
    锁持有者支持可重入,防止锁持有者再次重入时锁被超时释放。

    高性能高可用
    锁是代码运行的关键前置节点,一旦不可用则业务直接就报故障了。高并发场景下,高性能高可用是基本要求。

    实现 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 实现整体操作的原子性。

    go-zero 分布式锁 RedisLock 源码分析

    core/stores/redis/redislock.go

    加锁流程

    -- KEYS[1]: 锁key-- ARGV[1]: 锁value,随机字符串-- ARGV[2]: 过期时间-- 判断锁key持有的value是否等于传入的value-- 如果相等说明是再次获取锁并更新获取时间,防止重入时过期-- 这里说明是“可重入锁”if redis.call("GET", KEYS[1]) == ARGV[1] then    -- 设置    redis.call("SET", KEYS[1], ARGV[1], "PX", ARGV[2])    return "OK"else    -- 锁key.value不等于传入的value则说明是第一次获取锁    -- SET key value NX PX timeout : 当key不存在时才设置key的值    -- 设置成功会自动返回“OK”,设置失败返回“NULL Bulk Reply”    -- 为什么这里要加“NX”呢,因为需要防止把别人的锁给覆盖了    return redis.call("SET", KEYS[1], ARGV[1], "NX", "PX", ARGV[2])end

    怎么用Go+Redis实现分布式锁

    解锁流程

    -- 释放锁-- 不可以释放别人的锁if redis.call("GET", KEYS[1]) == ARGV[1] then    -- 执行成功返回“1”    return redis.call("DEL", KEYS[1])else    return 0end

    怎么用Go+Redis实现分布式锁

    源码解析

    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"    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`    randomLen = 16    // 默认超时时间,防止死锁    tolerance       = 500 // milliseconds    millisPerSecond = 1000)// A RedisLock is a redis lock.type RedisLock struct {    // redis客户端    store *Redis    // 超时时间    seconds uint32    // 锁key    key string    // 锁value,防止锁被别人获取到    id string}func init() {    rand.Seed(time.Now().UnixNano())}// NewRedisLock returns a RedisLock.func NewRedisLock(store *Redis, key string) *RedisLock {    return &RedisLock{        store: store,        key:   key,        // 获取锁时,锁的值通过随机字符串生成        // 实际上go-zero提供更加高效的随机字符串生成方式        // 见core/stringx/random.go:Randn        id:    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.key}, []string{        rl.id, strconv.Itoa(int(seconds)*millisPerSecond + tolerance),    })    if err == red.Nil {        return false, nil    } else if err != nil {        logx.Errorf("Error on acquiring 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 when acquiring lock for %s: %v", rl.key, resp)    return false, nil}// Release releases the lock.// 释放锁func (rl *RedisLock) Release() (bool, error) {    resp, err := rl.store.Eval(delCommand, []string{rl.key}, []string{rl.id})    if err != nil {        return false, err    }    reply, ok := resp.(int64)    if !ok {        return false, nil    }    return reply == 1, nil}// SetExpire sets the expire.// 需要注意的是需要在Acquire()之前调用// 不然默认为500ms自动释放func (rl *RedisLock) SetExpire(seconds int) {    atomic.StoreUint32(&rl.seconds, uint32(seconds))}func randomStr(n int) string {    b := make([]byte, n)    for i := range b {        b[i] = letters[rand.Intn(len(letters))]    }    return string(b)}

    以上是“怎么用Go+Redis实现分布式锁”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注编程网精选频道!

    --结束END--

    本文标题: 怎么用Go+Redis实现分布式锁

    本文链接: https://lsjlt.com/news/302108.html(转载时请注明来源链接)

    有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

    猜你喜欢
    • 怎么用Go+Redis实现分布式锁
      这篇文章主要介绍怎么用Go+Redis实现分布式锁,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!为什么需要分布式锁用户下单锁住 uid,防止重复下单。库存扣减锁住库存,防止超卖。余额扣减锁住账户,防止并发操作。分布式...
      99+
      2023-06-22
    • Go结合Redis怎么实现分布式锁
      这篇文章主要介绍了Go结合Redis怎么实现分布式锁,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。单Redis实例场景如果熟悉Redis的命令,可能会马上想到使用Redis的...
      99+
      2023-06-28
    • 怎么用Redis实现分布式锁
      本文小编为大家详细介绍“怎么用Redis实现分布式锁”,内容详细,步骤清晰,细节处理妥当,希望这篇“怎么用Redis实现分布式锁”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。单机...
      99+
      2024-04-02
    • Redis分布式锁怎么实现
      这篇文章给大家分享的是有关Redis分布式锁怎么实现的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。分布式锁一般有三种实现方式:1、数据库乐观锁;2、基于Redis的分布式锁;3、...
      99+
      2024-04-02
    • Redis怎么实现分布式锁
      这篇文章主要介绍“Redis怎么实现分布式锁”,在日常操作中,相信很多人在Redis怎么实现分布式锁问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Redis怎么实现分布式锁”的疑惑有所帮助!接下来,请跟着小编...
      99+
      2023-06-02
    • 分布式锁的原理及Redis怎么实现分布式锁
      这篇文章主要介绍“分布式锁的原理及Redis怎么实现分布式锁”,在日常操作中,相信很多人在分布式锁的原理及Redis怎么实现分布式锁问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解...
      99+
      2023-02-02
      redis
    • Redis中怎么实现分布式锁
      本篇内容介绍了“Redis中怎么实现分布式锁”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!为什么需要分布式...
      99+
      2024-04-02
    • Redis怎么样实现分布式锁
      这篇文章主要介绍了Redis怎么样实现分布式锁,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。在一个分布式系统中,会遇到一些需要对多个节点共享的资源加锁的情况,这个时候需要用到...
      99+
      2023-06-21
    • spring redis分布式锁怎么实现
      在Spring中实现Redis分布式锁可以使用RedisTemplate来操作Redis进行加锁和解锁。 首先,我们需要定义一个分布...
      99+
      2023-10-27
      spring redis
    • Redis——》实现分布式锁
      推荐链接:     总结——》【Java】     总结——》【Mysql】     总结——》【Redis】     总结——》【Kafka】     总结——》【Spring】     总结—...
      99+
      2023-09-03
      redis 分布式 过期 lua
    • Redis实现分布式锁
      单体锁存在的问题 在单体应用中,如果我们对共享数据不进行加锁操作,多线程操作共享数据时会出现数据一致性问题。 (下述实例是一个简单的下单问题:从redis中获取库存,检查库存是否够,>0才允许下单) 我们的解决办法通常是加锁。如下加单体锁...
      99+
      2023-08-16
      分布式 java jvm
    • java怎么使用redis实现分布式锁
      在Java中使用Redis实现分布式锁可以通过以下步骤:1. 引入Redis相关的依赖,例如Jedis或Lettuce。2. 创建一...
      99+
      2023-10-09
      java redis
    • Go与Redis实现分布式互斥锁和红锁
      目录前言互斥锁TryLock和Unlock实现Lock实现实现看门狗机制看门狗实现红锁加锁实现看门狗实现解锁实现前言 在项目中我们经常有需要使用分布式锁的场景,而Redis是实现分布式锁最常见的一种方式,这篇文章主要是使...
      99+
      2024-04-02
    • 怎么通过redis实现分布式锁
      本篇文章展示了通过redis实现分布式锁的具体操作,代码简明扼要容易理解,绝对能让你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。分布式锁是控制分布式系统之间同步访问共享资源的一种方式。在分布式系统中,...
      99+
      2024-04-02
    • Redisson中怎么实现Redis分布式锁
      Redisson中怎么实现Redis分布式锁,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。Redis几种架构Redis发展到现在,几种常见的部署架构有:单机模式;主从模式;...
      99+
      2023-06-20
    • 用Go+Redis实现分布式锁的示例代码
      目录为什么需要分布式锁 分布式锁需要具备特性 实现 Redis 锁应先掌握哪些知识点 set 命令 Redis.lua 脚本 go-zero 分布式锁 RedisLock 源码分析 ...
      99+
      2024-04-02
    • redis分布式锁的实现
      一、使用分布式锁要满足的几个条件:1、系统是一个分布式系统(关键是分布式,单机的可以使用ReentrantLock或者synchronized代码块来实现)2、共享资源(各个系统访问同一个资源,资源的载体可...
      99+
      2024-04-02
    • Redis Template实现分布式锁
      今天就跟大家聊聊有关Redis Template实现分布式锁,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。可靠性首先,为了确保分布式锁可用,我们至少...
      99+
      2024-04-02
    • PHP+Redis实现分布式锁
      目录 一、分布式锁概述 二、redis实现锁的命令 1、redis实现锁的命令 3、释放锁的步骤 三、PHP+redis分布式锁示例 四、redis集群分布式锁 一、分布式锁概述         在分布式环境下,各个线程通过对公共资...
      99+
      2023-09-15
      分布式锁
    • Redis实现分布式锁(SETNX)
      目录 1、什么是分布式锁 2、分布式锁应具备的条件         3、为什么使用分布式锁 4、SETNX介绍 5、分布式锁实现 6、效果演示 7、Redisson分布式锁详解 8、Lua脚本实现可重入分布式锁 1、什么是分布式锁  ...
      99+
      2023-10-21
      redis 分布式 java spring boot 后端
    软考高级职称资格查询
    编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
    • 官方手机版

    • 微信公众号

    • 商务合作