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

安阳市网站建设_网站建设公司_留言板_seo优化

网站建设情况介绍,谷歌浏览器怎么下载,wordpress加标题,营销型网站建设多少钱什么是分布式锁#xff0c;为什么需要分布式锁 在多线程并发请求当中#xff0c;为了保证我们的资源同一时刻只有一个线程进行操作#xff08;如商品超卖问题、购票系统等#xff09;#xff0c;我们通常要添加锁机制#xff0c;如ReentrantLock#xff0c;也就是可重入…什么是分布式锁为什么需要分布式锁 在多线程并发请求当中为了保证我们的资源同一时刻只有一个线程进行操作如商品超卖问题、购票系统等我们通常要添加锁机制如ReentrantLock也就是可重入的互斥锁与synchronized功能类似因为比较灵活所以经常使用。这在单机情况下是没有问题的但在多节点的情况下也就意味着有多个进程ReentrantLock锁机制可能就会不起作用所以我们需要一种能够跨进程的锁也就是同一时刻只能让一个进程获取锁来控制共享资源的访问。 分布式锁有哪些实现方式 基于数据库分布式锁悲观锁如select xxx for update、乐观锁如version版本号机制基于 Redis 实现分布式锁基于分布式协调服务 ZooKeeper 实现分布式锁 核心也是使用了每个节点都会用到的第三方组件例如mysql、redis、zookeeper Redis 实现分布式锁 使用setnx命令在 Redis 中setnx 命令是可以帮助我们实现互斥setnx 即 set if not exists (对应 Java 中的 setIfAbsent 方法)如果 key 不存在的话会设置 key 的值如果 key 已经存在 则啥也不做。 if(redisTemplate.opsForValue().setIfAbsent(key, value , time, TimeUnit)){ //加锁try {do something //业务处理}catch(){}finally {// 释放锁String delVal valueOperations.get(key).toString();if (value.equals(delVal)){redisTemplate.delete(key);}} }通常情况下我们一般使用setnx expire来实现防止死锁但仍然会有锁被别的线程误删的问题查询删除不是一个原子操作会有并发问题 为什么会有锁被别的线程误删假如线程A和线程B都执行同一段代码进行加锁线程A加锁成功当出现业务执行时间过长超过了过期时间这时线程A释放了锁此时线程B就能加锁成功接下来执行线程B业务操作这个时候线程A业务操作执行完了在finally方法中执行delete key这个时候线程A就会把线程B的锁给释放了。 所以一般释放的锁的时候最好使用lua脚本来进行释放来实现原子性的查询比较并删除锁。 if redis.call(get,KEYS[1]) ARGV[1] then return redis.call(del,KEYS[1]) elsereturn 0 end;lua脚本的话可以保证我们执行的时候多个命令执行期间不回被其他线程打断或出现竞争状态也就是可以看作一次请求保证了我们命令的原子性。 但这个方案仍然有个缺点锁过期释放了业务还没执行完。对于可能存在锁过期释放业务没执行完的问题。我们可以稍微把锁过期时间设置长一些让其大于正常业务处理时间。如果你觉得不是很稳还可以给获得锁的线程开启一个定时守护线程每隔一段时间检查锁是否还存在存在则对锁的过期时间延长防止锁过期提前释放如每5秒查看一下锁的过期时间如果小于10秒就延期针对这种锁续约机制redission框架就帮我们解决了这个问题 基于Redisson的分布式锁的实现 首先redission使用方式也比较简单 引入依赖 dependencygroupIdorg.redisson/groupIdartifactIdredisson/artifactIdversion3.17.0/version /dependency 写redisson的配置类 Bean public RedissonClient redissonClient(){...// 添加redis地址// 设置锁的超时时间// 创建 RedissonClient 对象 }使用redissonClient客户端加锁 Autowired private RedissonClient redissonClient;public void test() throws InterruptedException {RLock lock redissonClient.getLock(anyLock);boolean locked lock.tryLock(1,10,TimeUnit.SECONDS);// 参数1.获取锁的最大等待时间期间会重试2.锁自动释放时间3.时间单位if(locked){try{// 业务操作}finally{//释放锁lock.unlock();}} }假如我们加锁没有传参数直接使用tryLock()Redisson则会设置默认的锁过期时间为30s并且如果任务超过了30s还没有执行完毕则后台会有一个线程默认没隔10s执行task重置过期时间也就是WatchDog机制 redisson看门狗自动续期源码 private T RFutureLong tryAcquireAsync(long waitTime, long leaseTime, TimeUnit unit, long threadId) {RFutureLong ttlRemainingFuture;if (leaseTime ! -1) {ttlRemainingFuture tryLockInnerAsync(waitTime, leaseTime, unit, threadId, RedisCommands.EVAL_LONG);} else {ttlRemainingFuture tryLockInnerAsync(waitTime, internalLockLeaseTime,TimeUnit.MILLISECONDS, threadId, RedisCommands.EVAL_LONG);}ttlRemainingFuture.onComplete((ttlRemaining, e) - {if (e ! null) {return;}// lock acquiredif (ttlRemaining null) {if (leaseTime ! -1) {internalLockLeaseTime unit.toMillis(leaseTime);} else {scheduleExpirationRenewal(threadId);}}});return ttlRemainingFuture;}tryAcquireAsync方法 如果没有设置过期时间就会执行默认的过期时间lockWatchdogTimeout 30 * 1000(ms)执行回调函数即看门狗机制 protected void scheduleExpirationRenewal(long threadId) {ExpirationEntry entry new ExpirationEntry();// 将线程放入缓存操作ExpirationEntry oldEntry EXPIRATION_RENEWAL_MAP.putIfAbsent(getEntryName(), entry);if (oldEntry ! null) {// 如果已经有该线程则不再延期oldEntry.addThreadId(threadId);} else {entry.addThreadId(threadId);renewExpiration();}} //--------------------------------------------------------------- private void renewExpiration() {ExpirationEntry ee EXPIRATION_RENEWAL_MAP.get(getEntryName());if (ee null) {// 缓存不存在则不再续约return;}Timeout task commandExecutor.getConnectionManager().newTimeout(new TimerTask() {Overridepublic void run(Timeout timeout) throws Exception {ExpirationEntry ent EXPIRATION_RENEWAL_MAP.get(getEntryName());if (ent null) {return;}Long threadId ent.getFirstThreadId();if (threadId null) {return;}// 执行续约的lua脚本RFutureBoolean future renewExpirationAsync(threadId);future.onComplete((res, e) - {if (e ! null) {log.error(Cant update lock getRawName() expiration, e);EXPIRATION_RENEWAL_MAP.remove(getEntryName());return;}if (res) {// 延期成功回调自己继续续约renewExpiration();}});}// 每隔internalLockLeaseTime/310秒检查一次}, internalLockLeaseTime / 3, TimeUnit.MILLISECONDS);ee.setTimeout(task);}// ----------------------------------------------------------------------- protected RFutureBoolean renewExpirationAsync(long threadId) {return evalWriteAsync(getRawName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN,if (redis.call(hexists, KEYS[1], ARGV[2]) 1) then redis.call(pexpire, KEYS[1], ARGV[1]); return 1; end; return 0;,Collections.singletonList(getRawName()),internalLockLeaseTime, getLockName(threadId));}关键方法renewExpiration() 函数开启了一个定时任务在10s后执行并且会在调用成功后再次调用“自己”即续约机制可以看到Redisson也是使用Lua脚本进行锁续约的lua脚本里会进行判断锁是否存在如果存在则重置过期时间为30s 最后关于Redisson Redisson是Java的redis客户端之一提供了一些api方便操作redis。锁只是它的一个工具类其他还包括分布式对象、分布式集合等等详细可参考https://github.com/redisson/redisson/wiki/
http://www.ihoyoo.com/news/91805.html

相关文章:

  • 旅行社做网站微信链接网页网站制作
  • 网站建设和客户对接内容做网站的得多少钱
  • 网站制作制作西宁网站公司
  • 哪些网站做推广比较有效果wordpress 5.1不提示自动更新
  • m开头的网站建设公司经济技术开发区人才网
  • 南阳建站公司深圳微商城网站设计电话
  • 论网站建设的重要性织梦网站定时
  • php红酒网站建设效果图网址
  • 东莞手机网站建设入门重庆网站推广入口
  • 有些电影网站是怎么做的十大黄金软件免费下载
  • 上海建站模板系统石家庄网站建设解决方案
  • 专业的做网站的网站内页布局的不同
  • python怎么开发网站海南工程网站建设
  • 欢迎访问陕西省交通建设集团公司网站wordpress相册滑动
  • 普拓网站建设百度助手免费下载
  • 网站商城方案百度灰色词优化排名
  • 免费商品交易网站代码下载网站设计怎么做明信片
  • 网站开发课程设计报告一对一直播交友app开发
  • 制作asp.net网站四川建设网有限责任公司官网
  • 四川省建设网站电子签章制作视频的方法
  • 网站原型图怎么做dede查看网站
  • 网站建设方法氵金手指排名27免费做deal的网站
  • 虚拟技术对网站建设维护的影响大连搜狗推广
  • 网页版qq登陆入口潍坊外贸网站优化
  • 广州市住房建设公租房网站中山专业门户网站制作策划
  • 义乌制作网站要多少钱万网主机建wordpress
  • 东莞网站设计教程wordpress需要安装php模块
  • 网站付费模板个人网站怎么填写
  • 死链接对网站的影响手机网站后台管理
  • 贵阳网站建设三思网络wordpress首页不显示该分类下文章