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的区别
- SETNX是 Redis 中的一个原子操作命令,全称为SET if Not eXists。它用于在键不存在时设置键的值。如果键不存在,设置成功并返回1;如果键已经存在,则不进行任何操作并返回0。
- SET命令用于设置键的值,它有多个选项,其中NX是一个选项,XX选项与NX相反,EX选项用于设置过期时间等。当使用SET key value NX这种格式时,它的功能和SETNX类似,即只有在键不存在时才设置键的值。如果设置成功,返回OK;如果键已经存在,则不进行设置并返回(nil)。
除Redis外常见的分布式锁实现方式如下:
- Lua 脚本在 Redis 中是原子执行的。可以将获取锁、设置过期时间以及其他复杂的判断逻辑封装在一个 Lua 脚本中,这样就能保证操作的原子性,避免出现并发问题。
- 乐观锁:通过数据库表中的版本号字段实现。获取锁时查询版本号,更新时使版本号加一,更新成功则获取锁成功。
- 悲观锁:使用数据库的排它锁,如
SELECT... FOR UPDATE
语句。 - 基于Zookeeper:利用临时顺序节点。多个客户端创建临时顺序节点,判断自己创建的节点是否序号最小来确定是否获取锁,不是则监听前一序号节点。
(Zookeeper的分布式锁是客户端基于创建临时节点实现的,对于排他锁,每个客户端都尝试创建临时节点,但是只有一个客户端能成功创建,创建成功则相当于获取了锁。对于共享锁,则会按照一定的顺序队列创建带序号的临时节点并尝试获取锁(可以有多个客户端获取共享锁)。Redis的分布式锁则是通过创建一个从未创建过的key并设置其过期时间实现的,创建成功则获得了锁,并且客户端会在一定时间内循环获取锁,比较消耗服务器性能。) - 基于Consul:借助Session机制创建带TTL的会话。成功创建会话的客户端获取锁,其他客户端监听会话状态判断锁是否释放。
Redis自旋锁
当一个线程在获取锁的时候,如果锁已经被其它线程获取,那么该线程将循环等待,然后不断的判断锁是否能够被成功获取,直到获取到锁才会退出循环,减少线程上下文切换带来的性能消耗。
部分参考:https://blog.csdn.net/qq_22256565/article/details/104147826
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)