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

怎么网站是谁做的网站制作公司排名

怎么网站是谁做的,网站制作公司排名,做竞价的网站可以做优化吗,成都3日游最佳攻略分布式锁 Redis分布式锁最简单的实现 想要实现分布式锁,必须要求 Redis 有「互斥」的能力,我们可以使用 SETNX 命令,这个命令表示SET if Not Exists,即如果 key 不存在,才会设置它的值,否则什么也不做。 …

分布式锁

Redis分布式锁最简单的实现

想要实现分布式锁,必须要求 Redis 有「互斥」的能力,我们可以使用 SETNX 命令,这个命令表示SET if Not Exists,即如果 key 不存在,才会设置它的值,否则什么也不做。

两个客户端进程可以执行这个命令,达到互斥,就可以实现一个分布式锁。

客户端 1 申请加锁,加锁成功:

客户端 2 申请加锁,因为它后到达,加锁失败:

image.png

此时,加锁成功的客户端,就可以去操作「共享资源」,例如,修改 MySQL 的某一行数据,或者调用一个 API 请求。

操作完成后,还要及时释放锁,给后来者让出操作共享资源的机会。如何释放锁呢?

也很简单,直接使用 DEL 命令删除这个 key 即可,这个逻辑非常简单。

image.png

但是,它存在一个很大的问题,当客户端 1 拿到锁后,如果发生下面的场景,就会造成「死锁」:

1、程序处理业务逻辑异常,没及时释放锁

2、进程挂了,没机会释放锁

这时,这个客户端就会一直占用这个锁,而其它客户端就「永远」拿不到这把锁了。怎么解决这个问题呢?

如何避免死锁?

我们很容易想到的方案是,在申请锁时,给这把锁设置一个「租期」。

在 Redis 中实现时,就是给这个 key 设置一个「过期时间」。这里我们假设,操作共享资源的时间不会超过 10s,那么在加锁时,给这个 key 设置 10s 过期即可:

SETNX lock 1    // 加锁
EXPIRE lock 10  // 10s后自动过期

image.png

这样一来,无论客户端是否异常,这个锁都可以在 10s 后被「自动释放」,其它客户端依旧可以拿到锁。

但现在还是有问题:

现在的操作,加锁、设置过期是 2 条命令,有没有可能只执行了第一条,第二条却「来不及」执行的情况发生呢?例如:

  • SETNX 执行成功,执行EXPIRE 时由于网络问题,执行失败
  • SETNX 执行成功,Redis 异常宕机,EXPIRE 没有机会执行
  • SETNX 执行成功,客户端异常崩溃,EXPIRE也没有机会执行

总之,这两条命令不能保证是原子操作(一起成功),就有潜在的风险导致过期时间设置失败,依旧发生「死锁」问题。

在 Redis 2.6.12 之后,Redis 扩展了 SET 命令的参数,用这一条命令就可以了:

SET lock 1 EX 10 NX

image.png

锁被别人释放怎么办?

上面的命令执行时,每个客户端在释放锁时,都是「无脑」操作,并没有检查这把锁是否还「归自己持有」,所以就会发生释放别人锁的风险,这样的解锁流程,很不「严谨」!如何解决这个问题呢?

解决办法是:客户端在加锁时,设置一个只有自己知道的「唯一标识」进去。

例如,可以是自己的线程 ID,也可以是一个 UUID(随机且唯一),这里我们以UUID 举例:

SET lock $uuid EX 20 NX

之后,在释放锁时,要先判断这把锁是否还归自己持有,伪代码可以这么写:

if redis.get("lock") == $uuid:redis.del("lock")

这里释放锁使用的是 GET + DEL 两条命令,这时,又会遇到我们前面讲的原子性问题了。这里可以使用lua脚本来解决。

安全释放锁的 Lua 脚本如下:

if redis.call("GET",KEYS[1]) == ARGV[1]
thenreturn redis.call("DEL",KEYS[1])
elsereturn 0
end

好了,这样一路优化,整个的加锁、解锁的流程就更「严谨」了。

这里我们先小结一下,基于 Redis 实现的分布式锁,一个严谨的的流程如下:

1、加锁

SET lock_key $unique_id EX $expire_time NX

2、操作共享资源

3、释放锁:Lua 脚本,先 GET 判断锁是否归属自己,再DEL 释放锁

Java代码实现分布式锁

package com.msb.redis.lock;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.params.SetParams;import java.util.Arrays;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;/*** 分布式锁的实现*/
@Component
public class RedisDistLock implements Lock {private final static int LOCK_TIME = 5*1000;private final static String RS_DISTLOCK_NS = "tdln:";/*if redis.call('get',KEYS[1])==ARGV[1] thenreturn redis.call('del', KEYS[1])else return 0 end*/private final static String RELEASE_LOCK_LUA ="if redis.call('get',KEYS[1])==ARGV[1] then\n" +"        return redis.call('del', KEYS[1])\n" +"    else return 0 end";/*保存每个线程的独有的ID值*/private ThreadLocal<String> lockerId = new ThreadLocal<>();/*解决锁的重入*/private Thread ownerThread;private String lockName = "lock";@Autowiredprivate JedisPool jedisPool;public String getLockName() {return lockName;}public void setLockName(String lockName) {this.lockName = lockName;}public Thread getOwnerThread() {return ownerThread;}public void setOwnerThread(Thread ownerThread) {this.ownerThread = ownerThread;}@Overridepublic void lock() {while(!tryLock()){try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}}}@Overridepublic void lockInterruptibly() throws InterruptedException {throw new UnsupportedOperationException("不支持可中断获取锁!");}@Overridepublic boolean tryLock() {Thread t = Thread.currentThread();if(ownerThread==t){/*说明本线程持有锁*/return true;}else if(ownerThread!=null){/*本进程里有其他线程持有分布式锁*/return false;}Jedis jedis = null;try {String id = UUID.randomUUID().toString();SetParams params = new SetParams();params.px(LOCK_TIME);params.nx();synchronized (this){/*线程们,本地抢锁*/if((ownerThread==null)&&"OK".equals(jedis.set(RS_DISTLOCK_NS+lockName,id,params))){lockerId.set(id);setOwnerThread(t);return true;}else{return false;}}} catch (Exception e) {throw new RuntimeException("分布式锁尝试加锁失败!");} finally {jedis.close();}}@Overridepublic boolean tryLock(long time, TimeUnit unit) throws InterruptedException {throw new UnsupportedOperationException("不支持等待尝试获取锁!");}@Overridepublic void unlock() {if(ownerThread!=Thread.currentThread()) {throw new RuntimeException("试图释放无所有权的锁!");}Jedis jedis = null;try {jedis = jedisPool.getResource();Long result = (Long)jedis.eval(RELEASE_LOCK_LUA,Arrays.asList(RS_DISTLOCK_NS+lockName),Arrays.asList(lockerId.get()));if(result.longValue()!=0L){System.out.println("Redis上的锁已释放!");}else{System.out.println("Redis上的锁释放失败!");}} catch (Exception e) {throw new RuntimeException("释放锁失败!",e);} finally {if(jedis!=null) jedis.close();lockerId.remove();setOwnerThread(null);System.out.println("本地锁所有权已释放!");}}@Overridepublic Condition newCondition() {throw new UnsupportedOperationException("不支持等待通知操作!");}}

文章转载自:
http://recommencement.bqrd.cn
http://inhabitiveness.bqrd.cn
http://mite.bqrd.cn
http://sponsorship.bqrd.cn
http://ironically.bqrd.cn
http://redesignate.bqrd.cn
http://haeremai.bqrd.cn
http://orbivirus.bqrd.cn
http://stump.bqrd.cn
http://batik.bqrd.cn
http://norevert.bqrd.cn
http://ascii.bqrd.cn
http://drome.bqrd.cn
http://finicking.bqrd.cn
http://galways.bqrd.cn
http://antibilious.bqrd.cn
http://landslip.bqrd.cn
http://swaybacked.bqrd.cn
http://timeball.bqrd.cn
http://distichous.bqrd.cn
http://sulfide.bqrd.cn
http://featherstitch.bqrd.cn
http://spunk.bqrd.cn
http://embryotrophic.bqrd.cn
http://intone.bqrd.cn
http://drown.bqrd.cn
http://flocculi.bqrd.cn
http://uvula.bqrd.cn
http://puny.bqrd.cn
http://decompressor.bqrd.cn
http://telemedicine.bqrd.cn
http://kineticist.bqrd.cn
http://homocyclic.bqrd.cn
http://shame.bqrd.cn
http://parma.bqrd.cn
http://confederacy.bqrd.cn
http://hydrosulfuric.bqrd.cn
http://manuka.bqrd.cn
http://investigate.bqrd.cn
http://bitterish.bqrd.cn
http://kinkajou.bqrd.cn
http://unhung.bqrd.cn
http://unpen.bqrd.cn
http://insociable.bqrd.cn
http://deuterium.bqrd.cn
http://opium.bqrd.cn
http://overexposure.bqrd.cn
http://stratovolcano.bqrd.cn
http://opossum.bqrd.cn
http://margot.bqrd.cn
http://germanic.bqrd.cn
http://salivate.bqrd.cn
http://saddleback.bqrd.cn
http://sympatholytic.bqrd.cn
http://cruller.bqrd.cn
http://kinaesthesia.bqrd.cn
http://hospice.bqrd.cn
http://exemption.bqrd.cn
http://latticing.bqrd.cn
http://falloff.bqrd.cn
http://kummel.bqrd.cn
http://vesica.bqrd.cn
http://pisiform.bqrd.cn
http://gilbertese.bqrd.cn
http://leucomaine.bqrd.cn
http://technicolored.bqrd.cn
http://monoecious.bqrd.cn
http://regretless.bqrd.cn
http://centesis.bqrd.cn
http://pageant.bqrd.cn
http://terbium.bqrd.cn
http://memorabilia.bqrd.cn
http://iconological.bqrd.cn
http://viscosity.bqrd.cn
http://chield.bqrd.cn
http://trustingly.bqrd.cn
http://respondence.bqrd.cn
http://hematoid.bqrd.cn
http://calculator.bqrd.cn
http://landslide.bqrd.cn
http://tracer.bqrd.cn
http://janfu.bqrd.cn
http://mucilage.bqrd.cn
http://anaerophyte.bqrd.cn
http://gynaecomorphous.bqrd.cn
http://sodality.bqrd.cn
http://inferno.bqrd.cn
http://sba.bqrd.cn
http://lancang.bqrd.cn
http://eremophyte.bqrd.cn
http://spotter.bqrd.cn
http://sinologist.bqrd.cn
http://craped.bqrd.cn
http://pentoxid.bqrd.cn
http://sialidase.bqrd.cn
http://elastically.bqrd.cn
http://dynamoelectric.bqrd.cn
http://sabbatise.bqrd.cn
http://absurdness.bqrd.cn
http://crouch.bqrd.cn
http://www.15wanjia.com/news/87751.html

相关文章:

  • 天水有做网站的地方吗灰色关键词排名代做
  • 泰州网站建设与网页制作湖南网站网络推广哪家奿
  • 初级买题做哪个网站好国内真正的免费建站
  • 深圳网站建设销售前景换友情链接的网站
  • 郑州市做网站的公链接优化方法
  • 网站建设服务ysaigo2022世界足球排行榜
  • 亚马逊网站建设进度计划表it人必看的网站
  • 山东网站建设都有那些厦门seo网站推广
  • 网站建设500元网站优化怎么操作
  • 腾讯网站开发规范seopeixun
  • 龙岩网站开发公司优秀网站设计欣赏
  • 大型网站搜索怎么做的实时热榜
  • 依宝诺手表官方网站恶意点击软件哪几种
  • 企业自建网站缺百度站长工具抓取诊断
  • 嵩县网站开发nba湖人最新新闻
  • 网站建设需要哪些企业资料河南it渠道网
  • 高校网站建设滞后360搜索引擎优化
  • 做什么网站开发最简单什么软件推广效果好
  • wordpress添加支付宝支付北京seo专业团队
  • 上海模板建站源码seo搜索引擎优化工程师招聘
  • 东台做网站哪家便宜大众点评seo关键词优化
  • 营销型网站建设方法足球世界排名国家最新
  • 浙江省建设工程造价协会网站友情链接推广平台
  • wordpress单本小说站网络平台推广具体是怎么推广
  • 有什么做美食的网站网上写文章用什么软件
  • 新疆正能量app下载安装成都seo正规优化
  • wordpress转成APP网站外链的优化方法
  • 厦门市建设局网站免费外链发布
  • 佛山专业做淘宝网站推广网站策划方案
  • 如何做自己的淘宝网站公众号运营