当前位置: 首页 > wzjs >正文

网站建设与实践长春建站网站建设

网站建设与实践,长春建站网站建设,郑州抖音代运营公司,网页图片制作目录 一、什么是分布式锁 二、分布式锁的实现演进 一、什么是分布式锁 在一个分布式的系统中, 也会涉及到 多个节点访问同一个公共资源的情况. 此时就需要通过 锁 来做互斥控制, 避免出现类似于 "线程安全" 的问题。而 java 的 synchronized 或者 C 的 std::mutex…

目录

一、什么是分布式锁

二、分布式锁的实现演进


一、什么是分布式锁

在一个分布式的系统中, 也会涉及到

多个节点访问同一个公共资源的情况. 此时就需要通过 锁 来做互斥控制, 避免出现类似于 "线程安全" 的问题。而 java 的 synchronized 或者 C++ 的 std::mutex, 这样的锁都是只能在当前进程中生效, 在分布式的这种多个进程多个主机的场景下就无能为力了。

本质上就是使用一个公共的服务器, 来记录 加锁状态。这个公共的服务器可以是 Redis, 也可以是其他组件(比如 MySQL 或者 ZooKeeper 等), 还可以是我们自己写的一个服务。

二、分布式锁的实现演进

思路非常简单. 本质上就是通过一个键值对来标识锁的状态。Redis 中提供了 setnx 操作, 正好适合这个场景. 即: key 不存在就设置, 存在则直接失败。但上述方案并不完善,当某个服务器加锁成功后,程序突然崩溃,导致没有执行到解决,就会出现问题。

尝试一:引入过期时间

为了解决上述问题, 可以在设置 key 的同时引入过期时间。可以使用 set ex nx 的方式, 在设置锁的同时把过期时间设置进去(即这个锁最多持有多久, 就应该被释放)

注意:此处的过期时间只能使用一个命令的方式设置。

set nx ex/px

尝试二:引入校验 id(锁重入问题)

对于 Redis 中写入的加锁键值对, 其他的节点也是可以删除的。

比如 服务器1 写入一个 "001": 1 这样的键值对, 服务器2 是完全可以把 "001" 给删除掉的。当然, 服务器2 不会进行这样的 "恶意删除" 操作, 不过不能保证因为一些 bug 导致 服务器2 把锁误删除。

 为了解决上述问题, 我们可以引入一个校验 id。比如可以把设置的键值对的值, 不再是简单的设为一个 1, 而是设成服务器的编号. 形如 "001": "服务器1"。这样就可以在删除 key (解锁)的时候, 先校验当前删除 key 的服务器是否是当初加锁的服务器, 如果是,才能真正删除; 不是, 则不能删除。

  • 给服务器编号,每个服务器有一个自己的身份标识​
  • 进行加锁的时候,设置 key-value ,key 针对资源加锁,value存储刚才的服务器编号。​
  • 解锁的时候,首先查询这个锁对应的服务器编号,然后判定当前执行解锁的服务器编号是否正确。

由于上述步骤不是原子性的,服务器内部可能是多线程的,可能结果会出现错误。

尝试三:通过 Lua 解决(原子性问题)

Lua 也是一个编程语言. 读作 "撸啊". 是葡萄牙语中的 "月亮" 的意思. (出自于 Lua 官方文档Lua: about)​

Lua 的语法类似于 JS, 是一个动态弱类型的语言. Lua 的解释器一般使用 C 语言实现。Lua 语法简单精炼, 执行速度快, 解释器也比较轻量(Lua 解释器的可执行程序体积只有 200KB 左右)。因此 Lua 经常作为其他程序内部嵌入的脚本语言. Redis 本身就支持 Lua 作为内嵌脚本。​

​使用 Lua 脚本完成上述解锁功能:

if redis.call('get',KEYS[1]) == ARGV[1] then​return redis.call('del',KEYS[1])​
else​return 0​
end;

上述代码可以编写成一个 .lua 后缀的文件, 由 redis-cli 或者 redis-plus-plus 或者jedis 等客户端加载, 并发送给 Redis 服务器, 由 Redis 服务器来执行这段逻辑。一个 lua 脚本会被 Redis 服务器以原子的方式来执行。

尝试四:引入 watch dog (看门狗)

当我们设置了 key 过期时间之后 (比如 10s), 仍然存在一定的可能性,当任务还没执行完, key 就先过期了,这就导致锁提前失效。

把这个过期时间设置的足够长, 比如 30s, 是否能解决这个问题呢? 很明显, 设置多长时间合适, 是无止境的。即使设置再长, 也不能完全保证就没有提前失效的情况,而且如果设置的太长了, 万一对应的服务器挂了, 此时其他服务器也不能及时的获取到锁。因此相比于设置一个固定的长时间, 不如动态的调整时间更合适。

 初始情况下,设置一个过期时间(比如设置 1s)就提前在还剩 300ms 的时候把过期时间续 1s ,等到时间又快到了就再续。往往需要一个专门的线程负责续约这个事情,我们把这个负责的线程叫做“看门狗”。所谓 watch dog(广义的概念,很多场景都会涉及到), 本质上是加锁的服务器上的一个单独的线程, 通过这个线程来对锁过期时间进行 "续约"。

特殊情况:Redlock 算法

实践中的 Redis 一般是以集群的方式部署的 (至少是主从的形式, 而不是单机). 那么就可能出现以下比较极端的大冤种情况:​

服务器1 向 master 节点进行加锁操作. 这个写入 key 的过程刚刚完成, master 挂了; slave 节点升级成了新的 master 节点. 但是由于刚才写入的这个 key 尚未来得及同步给 slave 呢, 此时就相当于 服务器1 的加锁操作形同虚设了, 服务器2 仍然可以进行加锁 (即给新的 master 写入 key. 因为新的 master 不包含刚才的 key)。为了解决这个问题, Redis 的作者提出了 Redlock 算法:我们引入一组 Redis 节点. 其中每一组 Redis 节点都包含一个主节点和若干从节点. 并且组和组之间存储的数据都是一致的, 相互之间是 "备份" 关系(而并非是数据集合的一部分, 这点有别于 Redis cluster)。加锁的时候, 按照一定的顺序, 写多个 master 节点. 在写锁的时候需要设定操作的 "超时时间",比如50ms。即如果 setnx 操作超过了 50ms 还没有成功, 就视为加锁失败。

如果给某个节点加锁失败, 就立即再尝试下一个节点,当加锁成功的节点数超过总节点数的一半, 才视为加锁成功。这样的话, 即使有某些节点挂了, 也不影响锁的正确性。同理, 释放锁的时候, 也需要把所有节点都进行解锁操作 (即使是之前超时的节点, 也要尝试解锁, 尽量保证逻辑严密)。

http://www.dtcms.com/wzjs/823817.html

相关文章:

  • 网站建设案例 算命网站宁波设计网站公司
  • 一站式做网站公司led高端网站建设
  • 网站开发学习网站前端工资
  • 北京网站制作闪快佛山网站开发公司有哪些
  • 让你的静态网站 做后台做平面设计兼职的网站
  • 上海远东建筑设计院成都自然排名优化
  • 家纺营销型网站百胜招聘 网站开发
  • 做机器人的网站wordpress 显示全部文章
  • 网站建设中应该注意什么自建论坛
  • wordpress怎样连接数据库连接网站优化吧
  • 网站开发合同模板企业搭建什么样的平台
  • 网站制作怎么报价单普通人学python有意义吗
  • 公司网站建设维护的岗位wordpress 本地建站教程
  • 我要自学网官方网站杭州市建设住房保障局网站
  • 做个商城网站多少钱宁波做网站的大公司有哪些
  • 安阳网站建设_wordpress上传中文图片
  • 免费html模板素材网站青浦做网站的公司
  • 惠州网站建设找哪个公司笑话网站html模板
  • 淘宝网站建设不允许wordpress 浏览次数
  • 做系统前的浏览网站能找回吗网站标题关键词怎么做
  • 北京建设银行网站田村lnmp wordpress 502
  • 浙江建设局图审网站高端网站建设费用
  • 如何查询注册过的网站网站建设代理商
  • 吉林电商网站建设公司电话上海牛巨仁seo
  • 河南映天建设网站河南平价的seo整站优化定制
  • 东莞搜索seo网站关键词优化免费网站推广在线观看
  • 1_ 掌握网站开发的基本流程 要求:熟悉网站开发与设计的基本流程.软件项目管理案例教程第四版
  • 网站怎么申请微博登录手机制作网站软件
  • 杭州网站制作建设网店怎么开店注册
  • 深圳自适应网站常用的网络营销方法及效果