redis 实现并发锁go

redis 实现并发锁go,第1张

锁的作用是:当多个线程竞争一个资源时,会出现资源被干掉或者资源重置为另一个值,这时锁的作用就出现了,锁住当前的资源,其他线程就不会修改此数据了。

使用redis锁的思想是:将资源作为一个独立标识,然后放在字符串里面,并且使用过期时间来声明锁:

也可以手动释放,才去循环设置超时时间

SetNX 这个命令就很好地作为资源声明,创建一个锁:

import (

"context"

"go-redis/client"

"time"

"github.com/go-redis/redis/v8"

"github.com/google/uuid"

)

var ctx = context.TODO()

func Lock(lockname string, locktime int64) string {

u, _ := uuid.NewUUID()

ustr := u.String()

end := time.Now().Unix() + locktime

for {

  if time.Now().Unix() <end {

  client.RedisClient().SetNX(ctx, "lock:"+lockname, ustr, time.Hour)

  return ustr

  }

}

}

而释放锁,一般是两步合并的 *** 作,因为它会减少IO *** 作。

两步分为:

获取资源

如果有此资源,释放锁(删除资源uuid)

package redislock

import (

"context"

"go-redis/client"

"time"

"github.com/go-redis/redis/v8"

"github.com/google/uuid"

)

var ctx = context.TODO()

// 释放锁

func Release(lockname string, indetifier string) bool {

pipline := client.RedisClient().TxPipeline()

lockname = "lock:" + lockname

for {

  pipline.Get(ctx, lockname).Val()

  cmders, _ := pipline.Exec(ctx)

  perm, _ := cmders[0].(*redis.StringCmd).Result()

  if perm == indetifier {

  pipline.Del(ctx, lockname) // 删除锁

  pipline.Exec(ctx)

  return true

  }

}

}

在日常开发中,很多业务场景必须保证原子性。举几个例子:

如果你只有一台服务器,只运行一个Java程序,那么可以使用Java语言自身的一些锁来实现原子性。但如果我们有多台服务器,甚至不同服务器上跑的是不同的语言。那这时候,我们就需要一个跨平台、跨语言的加锁方式。redis就是其中最方便的一种。

使用redis实现并发锁,主要是靠两个redis的命令:setnx和getset。

那我们的设计思路就是:

上面的代码使用了一个RedisService的类,里面主要是简单封装了一下redis的 *** 作,你可以替换为自己的service。代码如下:

以上代码有任何疑问,可以点击右侧边栏联系作者。收费5毛~交个朋友,欢迎来撩!

版权声明:《Springboot使用redis的setnx和getset实现并发锁、分布式锁》为CoderBBB作者「ʘᴗʘ」的原创文章,转载请附上原文出处链接及本声明。

原文链接:https://www.coderbbb.com/articles/2


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/bake/7930216.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-11
下一篇 2023-04-11

发表评论

登录后才能评论

评论列表(0条)

保存