Redis实现分布式锁

RedisLock获取 Redis 锁,接受锁的key和过期时间作为参数。通过构造带有特定前缀的键名,使用 Redis 的SetNX操作尝试设置键值对,如果成功则表示获取锁成功。
RedisUnLock释放 Redis 锁,接受锁的key作为参数。构造带有特定前缀的键名,使用 Redis 的Del操作尝试删除指定的键,通常删除成功时返回值为 1。
示例:

func RedisLock(key string, expire int64) (result bool, err error) {
	var rdb = core.Redis.New()
	KeyPrefix := "kezhang:" + key
	result, err = rdb.SetNX(context.Background(), KeyPrefix, 1, time.Duration(expire)*time.Second).Result()

	return
}

func RedisUnLock(key string) (result int64, err error) {
	var rdb = core.Redis.New()
	KeyPrefix := "kezhang:" + key
	result, err = rdb.Del(context.Background(), KeyPrefix).Result()

	return
}

SetNX k v 和Set k v NX的区别

  1. SETNX是 Redis 中的一个原子操作命令,全称为SET if Not eXists。它用于在键不存在时设置键的值。如果键不存在,设置成功并返回1;如果键已经存在,则不进行任何操作并返回0。
  2. SET命令用于设置键的值,它有多个选项,其中NX是一个选项,XX选项与NX相反,EX选项用于设置过期时间等。当使用SET key value NX这种格式时,它的功能和SETNX类似,即只有在键不存在时才设置键的值。如果设置成功,返回OK;如果键已经存在,则不进行设置并返回(nil)。

除Redis外常见的分布式锁实现方式如下:

  1. Lua 脚本在 Redis 中是原子执行的。可以将获取锁、设置过期时间以及其他复杂的判断逻辑封装在一个 Lua 脚本中,这样就能保证操作的原子性,避免出现并发问题。
  2. 乐观锁:通过数据库表中的版本号字段实现。获取锁时查询版本号,更新时使版本号加一,更新成功则获取锁成功。
  3. 悲观锁:使用数据库的排它锁,如SELECT... FOR UPDATE语句。
  4. 基于Zookeeper:利用临时顺序节点。多个客户端创建临时顺序节点,判断自己创建的节点是否序号最小来确定是否获取锁,不是则监听前一序号节点。
    (Zookeeper的分布式锁是客户端基于创建临时节点实现的,对于排他锁,每个客户端都尝试创建临时节点,但是只有一个客户端能成功创建,创建成功则相当于获取了锁。对于共享锁,则会按照一定的顺序队列创建带序号的临时节点并尝试获取锁(可以有多个客户端获取共享锁)。Redis的分布式锁则是通过创建一个从未创建过的key并设置其过期时间实现的,创建成功则获得了锁,并且客户端会在一定时间内循环获取锁,比较消耗服务器性能。)
  5. 基于Consul:借助Session机制创建带TTL的会话。成功创建会话的客户端获取锁,其他客户端监听会话状态判断锁是否释放。

Redis自旋锁
当一个线程在获取锁的时候,如果锁已经被其它线程获取,那么该线程将循环等待,然后不断的判断锁是否能够被成功获取,直到获取到锁才会退出循环,减少线程上下文切换带来的性能消耗。

部分参考:https://blog.csdn.net/qq_22256565/article/details/104147826

posted @   教诲you  阅读(48)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示