服了,头条4面:因为一个问题问题砍了我10万薪水( 三 )
4、方式2:redis 的方式4.1、用到的几个命令
- setnx命令格式:SETNX key value;是『SET if Not eXists』(如果不存在 , 则 SET)的简写 , 只在简 key 不存在的情况下 , 将键 key 的值设置为 value。 若键 key 已经存在 ,则 SETNX 命令不做任何动作 。 命令在设置成功时返回 1, 设置失败时返回 0。
- getset命令格式:GETSET key value , 将键 key 的值设为 value, 并返回键 key 在被设置之前的旧的value 。 返回值:如果键 key 没有旧值 ,也即是说 ,键 key 在被设置之前并不存在 ,那么命令返回 nil。 当键 key 存在但不是字符串类型时 , 命令返回一个错误 。
- expire命令格式:EXPIRE key seconds , 使用:未给定 key 设置生存时间 , 当 key 过期时(生存时间为 0 ) , 它会被自动删除 。 返回值:设置成功返回 1。 当 key 不存在或者不能为 key 设置生存时间时(比如在低于 2.1.3 版本的 Redis 中你尝试更新 key 的生存时间) , 返回 0。
- del命令格式:DEL key [key …] , 使用:删除给定的一个或多个 key, 不存在的 key 会被忽略 。 返回值:被删除 key 的数量 。
文章插图过程分析 , 先看图左边过程:
1、A尝试去获取锁lockkey , 通过setnx(lockkey,currenttime+timeout)命令 , 对lockkey进行setnx,将value值设置为当前时间+锁超时时间;
2、如果返回值为1 , 说明redis服务器中还没有lockkey , 也就是没有其他用户拥有这个锁 , A就能获取锁成功;
3、在进行相关业务执行之前 , 先执行expire(lockkey) , 对lockkey设置有效期 , 防止死锁;因为如果不设置有效期的话 , lockkey将一直存在于redis中 , 其他用户尝试获取锁时 , 执行到setnx(lockkey,currenttime+timeout)时 , 将不能成功获取到该锁;
4、执行相关业务
5、释放锁 , A完成相关业务之后 , 要释放拥有的锁 , 也就是删除redis中该锁的内容 , del(lockkey) , 接下来的用户才能进行重新设置锁新值
再看右边过程
6、当A通过setnx(lockkey,currenttime+timeout)命令不能成功设置lockkey时 , 这是不能直接断定获取锁失败;因为我们在设置锁时 , 设置了锁的超时时间timeout , 当当前时间大于redis中存储键值为lockkey的value值时 , 可以认为上一任的拥有者对锁的使用权已经失效了 , A就可以强行拥有该锁;具体判定过程如下;
7、A通过get(lockkey) , 获取redis中的存储键值为lockkey的value值 , 即获取锁的相对时间lockvalueA
8、lockvalueA!=null--tt-darkmode-color: #595959;">9、步骤4返回结果为true后 , 通过getSet设置新的超时时间 , 并返回旧值lockvalueB , 以作判断 , 因为在分布式环境 , 在进入这里时可能另外的进程获取到锁并对值进行了修改 , 只有旧值与返回的值一致才能说明中间未被其他进程获取到这个锁
10、lockvalueB == null || lockvalueA==lockvalueB , 判断:如果lockvalueB为null , 说明该锁已经被释放了 , 此时该进程可以获取锁;旧值与返回的lockvalueB一致说明中间未被其他进程获取该锁 , 可以获取锁;否则不能获取锁 , 结束 , 获取锁失败 。
4.3、代码留给给大家 , 按照上面的过程实现下 。
5、方式3:zookeeper5.1、原理zookeeper是什么?是一个开源的中间件 , 可以做高可用配置中心使用 , 简单点理解:可以用来保存用户的一些数据 。
zookeeper有3个特点比较重要 , 这2个特点是实现分布式锁的关键 。
第1个特点:节点天然有序
zookeeper中存储数据是树结构 , 树下面可以创建很多节点 , 节点中可以存储用户的数据 。
在每一个节点下面创建子节点时 , 只要选择的创建类型是有序类型 , 那么 , 此节点将自动在客户端指定的节点名后面添加一个单调递增序号 , 重点是 , 并发创建子节点的情况下 , 也可以确保多个子节点的有序性 。
比如并发在/lock/lock1下面创建4个有序的节点 , 如下:
文章插图客户端可以判断创建的节点序号是不是最小的 , 如果编号是子节点中最小的 , 则获取锁成功 。
第2个特点:临时节点
客户端操作zookeeper , 需要和zookeeper之间建立连接 , 如果客户端请求在zookeeper上创建的节点类型是临时节点 , 那么当客户端和zookeeper之间连接断开的时候 , 创建的临时节点自动会被zookeeper删除 。
这个可以防止死锁多功能 , 比如客户端获取锁之后挂了 , 那么节点会自动被删除 , 此时锁的其他获取者才有机会获取锁 。
- 对手|一加9Pro全面曝光,或是小米11最大对手
- 面临|“熟悉的陌生人”不该被边缘化
- 页面|如何简单、快速制作流程图?上班族的画图技巧get
- 桌面|日常使用的软件及网站分享 篇一:几个动态壁纸软件和静态壁纸网站:助你美化你的桌面
- Win10系统桌面|手机桌面秒变Win10电脑系统,这波操作太给力了!
- 覆盖|iPhone13Pro概念机:机身正面被屏幕全覆盖,库克想搞事情?
- 页面|流程图怎样画?老板要我帮他做个组织结构图
- 成本|越拆越亏!旧家电回收面临成本困境:拆解一台旧电视亏损超20元
- 机器人|网络里面的假消息忽悠了非常多的小喷子和小机器人
- 用户|把更多主动权交还给用户,市面上敢这么做的或许只有OriginOS了
