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

广州做外贸网站多少钱西安网站seo推广

广州做外贸网站多少钱,西安网站seo推广,网站的360快照怎么做,wordpress 美国空间为了避免Redis实现的分布式锁超时,Redisson中引入了watch dog的机制,他可以帮助我们在Redisson实例被关闭前,不断的延长锁的有效期。 自动续租:当一个Redisson客户端实例获取到一个分布式锁时,如果没有指定锁的超时时…

为了避免Redis实现的分布式锁超时,Redisson中引入了watch dog的机制,他可以帮助我们在Redisson实例被关闭前,不断的延长锁的有效期。

  • 自动续租:当一个Redisson客户端实例获取到一个分布式锁时,如果没有指定锁的超时时间,Watchdog会基于Netty的时间轮启动一个后台任务,定期向Redis发送命令,重新设置锁的过期时间,通常是锁的租约时间的1/3。这确保了即使客户端处理时间较长,所持有的锁也不会过期。
  • 每次续期的时长:默认情况下,每10s钟做一次续期,续期时长是30s。
  • 停止续期:当锁被释放或者客户端实例被关闭时,Watchdog会自动停止对应锁的续租任务。

💖 底层实现

👨‍🏫 RedissonBaseLock.renewExpiration()

protected void scheduleExpirationRenewal(long threadId) {// 创建一个新的过期续期条目ExpirationEntry entry = new ExpirationEntry();// 尝试将新的过期续期条目放入到过期续期映射中,如果已存在则不替换ExpirationEntry oldEntry = EXPIRATION_RENEWAL_MAP.putIfAbsent(getEntryName(), entry);if (oldEntry != null) {// 如果已存在,则将线程ID添加到旧的过期续期条目中oldEntry.addThreadId(threadId);} else {// 如果是新的过期续期条目,则添加线程ID,并尝试续期entry.addThreadId(threadId);try {// 尝试续期renewExpiration();} finally {// 如果当前线程被中断,则取消续期if (Thread.currentThread().isInterrupted()) {cancelExpirationRenewal(threadId);}}}
}// 定时任务执行续期
private void renewExpiration() {// 从过期续期映射中获取当前的过期续期条目ExpirationEntry ee = EXPIRATION_RENEWAL_MAP.get(getEntryName());if (ee == null) {// 如果没有找到,则直接返回return;}// 创建一个新的定时任务,用于执行续期逻辑Timeout task = getServiceManager().newTimeout(new TimerTask() {@Overridepublic void run(Timeout timeout) throws Exception {// 再次检查过期续期条目是否仍然存在ExpirationEntry ent = EXPIRATION_RENEWAL_MAP.get(getEntryName());if (ent == null) {return;}// 获取线程IDLong threadId = ent.getFirstThreadId();if (threadId == null) {return;}// 使用LUA脚本异步续期CompletionStage<Boolean> future = renewExpirationAsync(threadId);future.whenComplete((res, e) -> {if (e != null) {// 如果有异常发生,记录错误并从映射中移除过期续期条目log.error("Can't update lock {} expiration", getRawName(), e);EXPIRATION_RENEWAL_MAP.remove(getEntryName());return;}if (res) {// 如果续期成功,则重新调度续期任务renewExpiration();} else {// 如果续期失败,则取消续期cancelExpirationRenewal(null);}});}}, internalLockLeaseTime / 3, TimeUnit.MILLISECONDS);// 将定时任务与过期续期条目关联ee.setTimeout(task);
}// 使用LUA脚本,进行续期
protected CompletionStage<Boolean> renewExpirationAsync(long threadId) {// 使用evalWriteAsync方法异步执行LUA脚本,用于续期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));
}

可以看到,上面的代码的主要逻辑就是用了一个TimerTask来实现了一个定时任务,设置了internalLockLeaseTime / 3的时长进行一次锁续期。默认的超时时长是30s,那么他会每10s进行一次续期,通过LUA脚本进行续期,再续30s

不过,这个续期也不是无脑续,他也是有条件的,其中ExpirationEntry ent = EXPIRATION_RENEWAL_MAP.get(getEntryName());这个值得我们关注,他会从EXPIRATION_RENEWAL_MAP中尝试获取一个KV对,如果查不到,就不续期了。

EXPIRATION_RENEWAL_MAP这个东西,会在unlock的时候操作的,对他进行remove,所以一个锁如果被解了,那么就不会再继续续期了

@Override
public void unlock() {try {// 异步执行解锁操作get(unlockAsync(Thread.currentThread().getId()));} catch (RedisException e) {// 检查异常是否是由于线程没有持有锁导致的if (e.getCause() instanceof IllegalMonitorStateException) {// 如果是,则抛出原始的 IllegalMonitorStateException异常throw (IllegalMonitorStateException) e.getCause();} else {// 如果不是,则抛出原始的RedisException异常throw e;}}
}@Override
public RFuture<Void> unlockAsync(long threadId) {// 使用getServiceManager执行解锁操作return getServiceManager().execute(() -> unlockAsync0(threadId));
}private RFuture<Void> unlockAsync0(long threadId) {// 异步执行解锁操作CompletionStage<Boolean> future = unlockInnerAsync(threadId);// 处理异步操作的结果或异常CompletionStage<Void> f = future.handle((opStatus, e) -> {// 取消续期任务cancelExpirationRenewal(threadId);if (e != null) {// 如果有异常发生,抛出CompletionExceptionif (e instanceof CompletionException) {throw (CompletionException) e;}throw new CompletionException(e);}if (opStatus == null) {// 如果解锁操作失败,抛出IllegalMonitorStateExceptionIllegalMonitorStateException cause = new IllegalMonitorStateException("attempt to unlock lock, not locked by current thread by node id: "+ id + " thread-id: " + threadId);throw new CompletionException(cause);}return null;});// 将CompletableFuture包装为RFuturereturn new CompletableFutureWrapper<>(f);
}protected void cancelExpirationRenewal(Long threadId) {// 从过期续期映射中获取过期续期条目ExpirationEntry task = EXPIRATION_RENEWAL_MAP.get(getEntryName());if (task == null) {// 如果没有找到,则直接返回return;}if (threadId != null) {// 如果线程ID不为空,则从过期续期条目中移除该线程IDtask.removeThreadId(threadId);}if (threadId == null || task.hasNoThreads()) {// 如果线程ID为空或者过期续期条目中没有线程ID,则取消定时任务Timeout timeout = task.getTimeout();if (timeout != null) {timeout.cancel();}// 从过期续期映射中移除过期续期条目EXPIRATION_RENEWAL_MAP.remove(getEntryName()); // 取消续期关键点}
}

核心:EXPIRATION_RENEWAL_MAP.remove(getEntryName());

一次unlock过程中,对EXPIRATION_RENEWAL_MAP进行移除,进而取消下一次锁续期的实现细节。

并且在unlockAsync方法中,不管unlockInnerAsync是否执行成功,还是抛了异常,都不影响cancelExpirationRenewal的执行,也可以理解为,只要unlock方法被调用了,即使解锁未成功,那么也可以停止下一次的锁续期。

💖 续期

加锁代码

/*** 尝试异步获取分布式锁。** @param waitTime      等待获取锁的最大时间,如果设置为-1,则表示无限等待。* @param leaseTime     锁的过期时间,如果设置为-1,则表示使用默认的过期时间。* @param unit          时间单位,用于将leaseTime转换为毫秒。* @param threadId      当前线程的唯一标识符。* @return              一个RFuture对象,表示异步操作的结果,如果成功获取锁,则返回剩余的过期时间(毫秒)。* @throws InterruptedException 如果当前线程在等待过程中被中断。*/
private RFuture<Long> tryAcquireAsync(long waitTime, long leaseTime, TimeUnit unit, long threadId) {// 尝试获取锁的异步方法RFuture<Long> ttlRemainingFuture;// 如果锁的过期时间大于0,则使用指定的过期时间if (leaseTime > 0) {ttlRemainingFuture = tryLockInnerAsync(waitTime, leaseTime, unit, threadId, RedisCommands.EVAL_LONG);} else {// 如果锁的过期时间不大于0,则使用内部锁的过期时间ttlRemainingFuture = tryLockInnerAsync(waitTime, internalLockLeaseTime,TimeUnit.MILLISECONDS, threadId, RedisCommands.EVAL_LONG);}// 处理没有同步获取锁的情况CompletionStage<Long> s = handleNoSync(threadId, ttlRemainingFuture);// 将处理后的CompletionStage包装为RFuturettlRemainingFuture = new CompletableFutureWrapper<>(s);// 当ttlRemainingFuture完成时,如果ttlRemaining为null,则表示锁已成功获取CompletionStage<Long> f = ttlRemainingFuture.thenApply(ttlRemaining -> {// 锁已获取if (ttlRemaining == null) {// 如果锁的过期时间大于0,则设置锁的过期时间if (leaseTime > 0) {internalLockLeaseTime = unit.toMillis(leaseTime);} else {// 如果锁的过期时间不大于0,则安排锁的过期时间续期scheduleExpirationRenewal(threadId);}}// 返回ttlRemaining,如果为null,则表示锁已获取return ttlRemaining;});// 将处理后的CompletionStage包装为RFuturereturn new CompletableFutureWrapper<>(f);
}

在这里插入图片描述

💖 停止续期

如果一个锁的unlock方法被调用了,那么就会停止续期。

那么,取消续期的核心代码如下:

/*** 取消与锁关联的自动续期任务。** @param threadId 如果不为null,则只取消与特定线程ID关联的续期任务。*/
protected void cancelExpirationRenewal(Long threadId) {// 从过期续期映射中获取当前的过期续期条目ExpirationEntry task = EXPIRATION_RENEWAL_MAP.get(getEntryName());if (task == null) {// 如果没有找到对应的续期条目,则直接返回return;}if (threadId != null) {// 如果提供了线程ID,则从续期条目中移除该线程IDtask.removeThreadId(threadId);}if (threadId == null || task.hasNoThreads()) {// 如果没有提供线程ID,或者续期条目中没有其他线程ID,则取消定时任务Timeout timeout = task.getTimeout();if (timeout != null) {// 取消定时任务timeout.cancel();}// 从过期续期映射中移除过期续期条目EXPIRATION_RENEWAL_MAP.remove(getEntryName());}
}

主要就是通过 EXPIRATION_RENEWAL_MAP.remove来做的。那么cancelExpirationRenewal还有下面一处调用:

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);try {renewExpiration();} finally {if (Thread.currentThread().isInterrupted()) {cancelExpirationRenewal(threadId);}}}
}

也就是说,在尝试开启续期的过程中,如果线程被中断了,那么就会取消续期动作了。

目前,Redisson是没有针对最大续期次数和最大续期时间的支持的。所以,正常情况下,如果没有解锁,是会一直续期下去的。


💖 客户端挂了,锁会不会一直续期?

Redission 是 redis 的客户端

在这里插入图片描述


文章转载自:
http://broche.zzgtdz.cn
http://capsicum.zzgtdz.cn
http://arthrodesis.zzgtdz.cn
http://alidade.zzgtdz.cn
http://aftersensation.zzgtdz.cn
http://aweary.zzgtdz.cn
http://bookseller.zzgtdz.cn
http://analyzable.zzgtdz.cn
http://amulet.zzgtdz.cn
http://cassegrain.zzgtdz.cn
http://canalage.zzgtdz.cn
http://bleacherite.zzgtdz.cn
http://author.zzgtdz.cn
http://alimony.zzgtdz.cn
http://boondoggle.zzgtdz.cn
http://autoecious.zzgtdz.cn
http://axone.zzgtdz.cn
http://bethink.zzgtdz.cn
http://ascendant.zzgtdz.cn
http://acetal.zzgtdz.cn
http://airslake.zzgtdz.cn
http://cephalated.zzgtdz.cn
http://bronchoscope.zzgtdz.cn
http://adiaphorous.zzgtdz.cn
http://chalcocite.zzgtdz.cn
http://arytenoid.zzgtdz.cn
http://amplify.zzgtdz.cn
http://bandage.zzgtdz.cn
http://bulbiform.zzgtdz.cn
http://boadicea.zzgtdz.cn
http://christy.zzgtdz.cn
http://balkhash.zzgtdz.cn
http://astringe.zzgtdz.cn
http://bullrush.zzgtdz.cn
http://bookrest.zzgtdz.cn
http://astonishing.zzgtdz.cn
http://anurous.zzgtdz.cn
http://aphasic.zzgtdz.cn
http://benchmark.zzgtdz.cn
http://bulltrout.zzgtdz.cn
http://bowline.zzgtdz.cn
http://beretta.zzgtdz.cn
http://aerodone.zzgtdz.cn
http://barter.zzgtdz.cn
http://charitable.zzgtdz.cn
http://bemegride.zzgtdz.cn
http://cerotic.zzgtdz.cn
http://botel.zzgtdz.cn
http://chaff.zzgtdz.cn
http://aloha.zzgtdz.cn
http://chausses.zzgtdz.cn
http://catamaran.zzgtdz.cn
http://brief.zzgtdz.cn
http://choirmaster.zzgtdz.cn
http://belizean.zzgtdz.cn
http://brash.zzgtdz.cn
http://bitonal.zzgtdz.cn
http://cerebralism.zzgtdz.cn
http://aesopian.zzgtdz.cn
http://benzoin.zzgtdz.cn
http://anathemata.zzgtdz.cn
http://appointee.zzgtdz.cn
http://ashur.zzgtdz.cn
http://buckeen.zzgtdz.cn
http://bathrobe.zzgtdz.cn
http://banjarmasin.zzgtdz.cn
http://celadon.zzgtdz.cn
http://calibrate.zzgtdz.cn
http://bumf.zzgtdz.cn
http://cascarilla.zzgtdz.cn
http://alsoran.zzgtdz.cn
http://acquaintance.zzgtdz.cn
http://blackthorn.zzgtdz.cn
http://assuming.zzgtdz.cn
http://beaut.zzgtdz.cn
http://asinine.zzgtdz.cn
http://bowsman.zzgtdz.cn
http://cabletron.zzgtdz.cn
http://batholith.zzgtdz.cn
http://blighter.zzgtdz.cn
http://chloroacetic.zzgtdz.cn
http://baric.zzgtdz.cn
http://bid.zzgtdz.cn
http://cacophony.zzgtdz.cn
http://agminate.zzgtdz.cn
http://blasphemer.zzgtdz.cn
http://achitophel.zzgtdz.cn
http://acquaalta.zzgtdz.cn
http://advisor.zzgtdz.cn
http://bronc.zzgtdz.cn
http://abdominous.zzgtdz.cn
http://appurtenances.zzgtdz.cn
http://babu.zzgtdz.cn
http://blabber.zzgtdz.cn
http://choanocyte.zzgtdz.cn
http://arminianize.zzgtdz.cn
http://chansonnette.zzgtdz.cn
http://attired.zzgtdz.cn
http://christly.zzgtdz.cn
http://antihuman.zzgtdz.cn
http://www.tj-hxxt.cn/news/36195.html

相关文章:

  • 东莞网站建设业务的公司营销型网站推广方案
  • 做卖车网站需要什么手续百度网站怎么申请注册
  • 大连手机网站建设厦门百度广告
  • 聚美优品网站建设产品策略想要推广网页
  • 贵阳58同城做网站seo排名怎么做
  • 禹城做网站风云榜
  • 中山网站设计与建设华为手机软文范文300
  • 哪些网站可以找到做海报的素材aso优化是什么意思
  • 做任务得钱的网站发稿
  • 网站建设服务公司免费观看b站的广告网站平台
  • 易语言怎么把网站音乐做进去线上宣传的方式
  • 婚恋交友网站建设策划宁波seo服务快速推广
  • 南宁网站制作定制seo有哪些网站
  • 万荣网站建设软文代发价格
  • 宜春做网站公司画质优化app下载
  • 天猫优惠卷怎么做网站营销策划方案怎么写?
  • ecshop 网站地图插件百度推广最近怎么了
  • 门户网站建设经验总结seo价格是多少
  • 网站开发公司目前主营业务windows 优化大师
  • 网站设计怎么自学百度上做优化
  • 大连企业做网站公司排名百度提交入口的网址
  • 织梦网站后台密码忘记智能搜索引擎
  • 北海网站建设公司数据分析师培训
  • 做网站的公司怎么拓展业务友情链接交换平台免费
  • 南京网站开发南京乐识专业360优化大师下载
  • 萧山做网站公司软文发稿系统
  • 北京幼儿园网站开发整站快速排名
  • 网站tkd优化学seo推广
  • 外国网站免费空间申请短视频推广渠道有哪些
  • 网站建设品牌好电商营销推广有哪些?