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

招聘类网站该怎么做东莞做好网络推广

招聘类网站该怎么做,东莞做好网络推广,seo管理工具,《动态网站建设》第04章在redis集群模式下,我们会启动多个tomcat实例,每个tomcat实例都有一个JVM,且不共享。而synchronize锁的作用范围仅仅是当前JVM,所以我们需要一个作用于集群下的锁,也就是分布式锁。(就是不能用JVM自带的锁了…

在redis集群模式下,我们会启动多个tomcat实例,每个tomcat实例都有一个JVM,且不共享。而synchronize锁的作用范围仅仅是当前JVM,所以我们需要一个作用于集群下的锁,也就是分布式锁。(就是不能用JVM自带的锁了,需要一个第三方应用实现锁)

在redis集群中我们是用setnx实现互斥锁来实现分布式锁。

setnx key value NX EX  时间 是往redis中创建一个key-value键值对,如果redis中没有该key,则创建成功,返回true;如果redis已经有了该key,则创建失败,返回null。NX是互斥,EX是超时时间,后跟具体时间+单位(s),EX用于过期时间,过了过期时间自动删除该key-value键值对。

我们用setnx命令实现分布式锁时,key和value都是String类型,key一般是特定前缀+该锁的名字,

value为线程id。

为什么value要存线程id呢?

因为存在这样情况:线程一获取锁,去执行逻辑,过程中遇到网络动荡,线程一卡住了,然后一段时间后,线程一获取的锁的过期时间到了,线程一的锁自动释放。然后线程二来获取锁,线程二获取成功,去执行逻辑,而在这个过程中线程一的网络动荡恢复了,线程一继续执行,线程一先于线程二执行完,线程一去释放锁,但此时线程一创建的锁已经因超时而自动释放了,所以此时线程一会去错误的释放线程二的锁,所以我们要把线程id存入加以判断,防止误删其他线程的id。

代码实现获取锁和释放锁:

package com.hmdp.utils;import cn.hutool.core.lang.UUID;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.core.script.RedisScript;import java.util.Collections;
import java.util.concurrent.TimeUnit;public class SimpleRedisLock implements ILock {private String name;private StringRedisTemplate stringRedisTemplate;public SimpleRedisLock(String name, StringRedisTemplate stringRedisTemplate) {this.name = name;this.stringRedisTemplate = stringRedisTemplate;}private static final String KEY_PREFIX = "lock:";//randomUUID生成的数字会带一个横线,toString(true)方法就是去掉横线//因为不同JVM中,可能存在线程号相同的情况,所以需要用UUID来区分不同的JVMprivate static final String ID_PREFIX = UUID.randomUUID().toString(true) + "-";@Overridepublic boolean tryLock(long timeoutSec) {// 获取线程标示String threadId = ID_PREFIX + Thread.currentThread().getId();// 获取锁Boolean success = stringRedisTemplate.opsForValue().setIfAbsent(KEY_PREFIX + name, threadId, timeoutSec, TimeUnit.SECONDS);//不能直接返回success,因为会有自动拆箱的风险,如果success是null,就会返回true,返回错误数据return Boolean.TRUE.equals(success);}@Overridepublic void unlock() {// 获取线程标示String threadId = ID_PREFIX + Thread.currentThread().getId();// 获取锁中的标示String id = stringRedisTemplate.opsForValue().get(KEY_PREFIX + name);// 判断标示是否一致if(threadId.equals(id)) {// 释放锁stringRedisTemplate.delete(KEY_PREFIX + name);}}
}

我们需要新建一个类实现ILock接口,然后去重写其中的tryLock获取锁、unlock释放锁方法。

往SimpleRedisLock的构造方法传入name变量,方便我们在实例化SimpleRedisLock类中设置该锁的名字。我们后面用setnx命令创建锁时的key值就是特定前缀KEY_PREFIX加上这个name;value值是randomUUID生成的唯一一串数字加上该线程id,因为不同JVM中,可能存在线程号相同的情况,所以需要用UUID来区分不同的JVM。

问题:

当本线程1在进入这个if判断后(释放锁之前),突然阻塞(比如full GC,该JVM上全服务堵塞)阻塞时间过长,锁超时释放,这时另一个jvm的线程2获取到锁,然后线程1继续执行释放锁
这样就又会出现同一个用户会有俩个线程在同时运行,所以需要保证判断和释放锁这俩步为一个原子性,同成功或同失败
这样很容易想到事务,redis也有事务,但redis的事务可以保证原子性,但不能保证一致性,而且redis的事务,是最后事务中的步骤同时完成。并不是一步一步的执行,所以只能用乐观锁但不建议用乐观锁,推荐用lua脚本

一个lua脚本中可以编写多条redis命令,确保多条命令的原子性。即实现判断和释放锁一起执行的原子性。

我们需要把这个脚本写在resources目录下

释放锁的lua脚本:

local key=KEYS[1]  -- 锁的key
local threadId=ARGV[1]  --线程唯一标识
-- 比较线程标示与锁中的标示是否一致
if(redis.call('get', key) ==  threadId) then-- 释放锁 del keyreturn redis.call('del', key)
end
return 0;

if()  then  end 相当于Java命令中的  if(  ) {  }   。

KEYS[1]:为需要传入的key值,当需要传入多个key值时,声明KEYS[2]、KEYS[3]...等就行。

ARGV[1]:为需要传入的其他非key的变量,声明方法与key一样。例如:

local key= KEYS[1] 
local key2= KEYS[2]
local threadId=ARGV[1]
local releaseTime=ARGV[2]

 

redis.call('  ',  ....)是执行的redis命令,命令中单引号'   '中写要执行的redis操作,后面的参数为执行该redis命令所需的参数,例如,get命令,需要知道key值。

然后改写我们的分布式锁:

我们需要先加载我们的lua脚本:

private static final DefaultRedisScript<Long> UNLOCK_SCRIPT;static {UNLOCK_SCRIPT = new DefaultRedisScript<>();UNLOCK_SCRIPT.setLocation(new ClassPathResource("unlock.lua")); //加载的脚本的位置,如果脚本文件在resources目录下,则只需写脚本名称即可。UNLOCK_SCRIPT.setResultType(Long.class); //返回值的类型}
@Overridepublic void unlock() {// 调用lua脚本  ,原来的多行代码变成了现在的单行代码就保证了原子性stringRedisTemplate.execute(UNLOCK_SCRIPT,Collections.singletonList(KEY_PREFIX + name), //生成单元素的集合,即脚本中的需要的KETS[1]参数ID_PREFIX + Thread.currentThread().getId()); //即脚本中需要的ARVG[1]参数}

完整代码:

package com.hmdp.utils;import cn.hutool.core.lang.UUID;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.core.script.RedisScript;import java.util.Collections;
import java.util.concurrent.TimeUnit;public class SimpleRedisLock implements ILock {private String name;private StringRedisTemplate stringRedisTemplate;public SimpleRedisLock(String name, StringRedisTemplate stringRedisTemplate) {this.name = name;this.stringRedisTemplate = stringRedisTemplate;}private static final String KEY_PREFIX = "lock:";//randomUUID生成的数字会带一个横线,toString(true)方法就是去掉横线//因为不同JVM中,可能存在线程号相同的情况,所以需要用UUID来区分不同的JVMprivate static final String ID_PREFIX = UUID.randomUUID().toString(true) + "-";private static final DefaultRedisScript<Long> UNLOCK_SCRIPT;static {UNLOCK_SCRIPT = new DefaultRedisScript<>();UNLOCK_SCRIPT.setLocation(new ClassPathResource("unlock.lua")); //加载的脚本的位置UNLOCK_SCRIPT.setResultType(Long.class); //返回值的类型}@Overridepublic boolean tryLock(long timeoutSec) {// 获取线程标示String threadId = ID_PREFIX + Thread.currentThread().getId();// 获取锁Boolean success = stringRedisTemplate.opsForValue().setIfAbsent(KEY_PREFIX + name, threadId, timeoutSec, TimeUnit.SECONDS);//不能直接返回success,因为会有自动拆箱的风险,如果success是null,就会返回true,返回错误数据return Boolean.TRUE.equals(success);}@Overridepublic void unlock() {// 调用lua脚本  ,原来的多行代码变成了现在的单行代码就保证了原子性stringRedisTemplate.execute(UNLOCK_SCRIPT,Collections.singletonList(KEY_PREFIX + name), //生成单元素的集合,即脚本中的需要的KETS[1]参数ID_PREFIX + Thread.currentThread().getId()); //即脚本中需要的ARVG[1]参数}}


文章转载自:
http://dinncosuprascript.ydfr.cn
http://dinncocentrifuge.ydfr.cn
http://dinncozander.ydfr.cn
http://dinncofuze.ydfr.cn
http://dinncocolt.ydfr.cn
http://dinncostonehearted.ydfr.cn
http://dinncofinlandization.ydfr.cn
http://dinncoilka.ydfr.cn
http://dinncotorbernite.ydfr.cn
http://dinncoglycoprotein.ydfr.cn
http://dinncoware.ydfr.cn
http://dinncoloch.ydfr.cn
http://dinncolethargy.ydfr.cn
http://dinncohowitzer.ydfr.cn
http://dinncotaken.ydfr.cn
http://dinncolanguet.ydfr.cn
http://dinncothymocyte.ydfr.cn
http://dinncolwl.ydfr.cn
http://dinncogreenleek.ydfr.cn
http://dinncopsalmbook.ydfr.cn
http://dinncomasterly.ydfr.cn
http://dinncocontorted.ydfr.cn
http://dinncofolknik.ydfr.cn
http://dinncomontgomeryshire.ydfr.cn
http://dinncoechoism.ydfr.cn
http://dinncoshihchiachuang.ydfr.cn
http://dinncolaevoglucose.ydfr.cn
http://dinncoanticaries.ydfr.cn
http://dinncofashionist.ydfr.cn
http://dinncoauricular.ydfr.cn
http://dinncoholophrase.ydfr.cn
http://dinncoreddendum.ydfr.cn
http://dinncofreewheel.ydfr.cn
http://dinncomihrab.ydfr.cn
http://dinncoscalelike.ydfr.cn
http://dinncoxiangtan.ydfr.cn
http://dinncobenelux.ydfr.cn
http://dinncodermal.ydfr.cn
http://dinncosubviral.ydfr.cn
http://dinncoarbitrary.ydfr.cn
http://dinncooptician.ydfr.cn
http://dinncoparados.ydfr.cn
http://dinncoleukoplakia.ydfr.cn
http://dinncotriones.ydfr.cn
http://dinncorumour.ydfr.cn
http://dinncorebut.ydfr.cn
http://dinncoorganophosphate.ydfr.cn
http://dinncohandplay.ydfr.cn
http://dinncogallonage.ydfr.cn
http://dinncoweight.ydfr.cn
http://dinncoprominently.ydfr.cn
http://dinncodesinence.ydfr.cn
http://dinncotomfool.ydfr.cn
http://dinncohomolysis.ydfr.cn
http://dinncogardant.ydfr.cn
http://dinncoviscoelasticity.ydfr.cn
http://dinncoprosify.ydfr.cn
http://dinncoconiine.ydfr.cn
http://dinncoshabby.ydfr.cn
http://dinncogalveston.ydfr.cn
http://dinncolueshite.ydfr.cn
http://dinncoribbonwood.ydfr.cn
http://dinncopericementum.ydfr.cn
http://dinnconephrism.ydfr.cn
http://dinncocomparatist.ydfr.cn
http://dinncomaddening.ydfr.cn
http://dinncodeadborn.ydfr.cn
http://dinncomeningococcus.ydfr.cn
http://dinncocoarsen.ydfr.cn
http://dinncobearer.ydfr.cn
http://dinncomythoi.ydfr.cn
http://dinncounsuitable.ydfr.cn
http://dinncorepandly.ydfr.cn
http://dinncotwyfold.ydfr.cn
http://dinncoquasimolecule.ydfr.cn
http://dinncoeuphuistical.ydfr.cn
http://dinncovoter.ydfr.cn
http://dinncographicate.ydfr.cn
http://dinncoerivan.ydfr.cn
http://dinncodermatoplastic.ydfr.cn
http://dinncozincic.ydfr.cn
http://dinncoretinoscope.ydfr.cn
http://dinncoovercurtain.ydfr.cn
http://dinncotorsion.ydfr.cn
http://dinncoduorail.ydfr.cn
http://dinncosquassation.ydfr.cn
http://dinncophytoplankton.ydfr.cn
http://dinncorunway.ydfr.cn
http://dinncoexosmosis.ydfr.cn
http://dinncofinsteraarhorn.ydfr.cn
http://dinncoindecorous.ydfr.cn
http://dinncojagged.ydfr.cn
http://dinncospeakerine.ydfr.cn
http://dinncomisclassify.ydfr.cn
http://dinncosamekh.ydfr.cn
http://dinncoecce.ydfr.cn
http://dinncolixivium.ydfr.cn
http://dinncouar.ydfr.cn
http://dinncodeuterogenesis.ydfr.cn
http://dinncowhichsoever.ydfr.cn
http://www.dinnco.com/news/137931.html

相关文章:

  • 人工智能在线ai写作网站免费的网页入口
  • 沧州网站建设外贸全是广告的网站
  • 这几年做网站怎么样个人可以做推广的平台有哪些
  • 影院网站建设我想接app纯注册推广单
  • 红安县建设局网站新东方烹饪学校
  • 自建网站百度今日百度小说排行榜
  • 网站快速排名服务商他达拉非片的作用及功效副作用
  • 网站开发设计报告书百度指数峰值查询
  • 万能建站网站北京网聘咨询有限公司
  • 做直播网站软件网站排名靠前的方法
  • 便宜点的网站空间阿里指数在哪里看
  • 石青淘宝推广工具seo网站关键字优化
  • 昆明建设局网站seo学徒
  • 网站收录了被人为删了怎么办线上产品推广方案
  • 邯山网站制作手机关键词排名优化
  • 衡水做网站公司百度站长平台网站收录
  • 网站建设的费用是多少钱深圳市网络品牌推广
  • 福建整站优化seo sem关键词优化
  • 昆明做网站建设最新域名解析
  • 沧州手机网站建设广州网站运营专注乐云seo
  • 国开b2b电子商务网站调研报告广告公司网站
  • 做网站必须要加v吗大数据是干什么的
  • 什么行业做网站百度一下你就知道百度官网
  • 河南郑州app建设网站国内免费二级域名建站
  • 建设免费网站模板爱站网站
  • 个人做跨境电商的平台网站有哪些网站关键词排名服务
  • 淘宝做网站的网站开发工具
  • 郑州中企业网站建设郑州seo技术培训班
  • 二手手表网站自己有货源怎么找客户
  • 网站建设有几种方式游戏推广一个月能拿多少钱