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

网站建设 psd网站一键收录

网站建设 psd,网站一键收录,如何为网站开发app,安阳县人民政府一、基本原理和实现方式对比 分布式锁:满足分布式系统或集群模式下多进程可见并且互斥的锁。 分布式锁的核心思想就是让大家都使用同一把锁,只要大家使用的是同一把锁,那么我们就能锁住线程,不让线程进行,让程序串行…

一、基本原理和实现方式对比

分布式锁:满足分布式系统或集群模式下多进程可见并且互斥的锁。

分布式锁的核心思想就是让大家都使用同一把锁,只要大家使用的是同一把锁,那么我们就能锁住线程,不让线程进行,让程序串行执行,这就是分布式锁的核心思路
在这里插入图片描述
分布式锁应该满足的条件:

  1. 可见性:多个线程都能看到相同的结果,注意:这个地方说的可见性并不是并发编程中指的内存可见性,只是说多个进程之间都能感知到变化的意思

  2. 互斥:互斥是分布式锁的最基本的条件,使得程序串行执行

  3. 高可用:程序不易崩溃,时时刻刻都保证较高的可用性

  4. 高性能:由于加锁本身就让性能降低,所有对于分布式锁本身需要他就较高的加锁性能和释放锁性能

  5. 安全性:安全也是程序中必不可少的一环
    在这里插入图片描述

常见的三种分布式锁:

  1. Mysql:mysql 本身就带有锁机制,但是由于 mysql 性能本身一般,所以采用分布式锁的情况下,其实使用 mysql 作为分布式锁比较少见

  2. Redis:redis 作为分布式锁是非常常见的一种使用方式,现在企业级开发中基本都使用 redis 或者 zookeeper 作为分布式锁,利用 setnx 这个方法,如果插入 key 成功,则表示获得到了锁,如果有人插入成功,其他人插入失败则表示无法获得到锁,利用这套逻辑来实现分布式锁

  3. Zookeeper:zookeeper 也是企业级开发中较好的一个实现分布式锁的方案,由于这套视频不讲解zookeeper 的原理和分布式锁的实现,自己搜索了解
    在这里插入图片描述

二、 Redis分布式锁的实现核心思路

实现分布式锁时需要实现的两个基本方法:

  • 获取锁:
    • 互斥:确保只能有一个线程获取锁
    • 非阻塞:尝试一次,成功返回true,失败返回false
  • 释放锁:
    • 手动释放
    • 超时释放:获取锁时添加一个超时时间

在这里插入图片描述
核心思路:

利用 redis 的 setNx 方法,当有多个线程进入时,我们就利用该方法,第一个线程进入时,redis 中就有这个 key 了,返回了1,如果结果是1,则表示他抢到了锁,那么他去执行业务,然后再删除锁,退出锁逻辑,没有抢到锁的哥们,等待一定时间后重试即可。
在这里插入图片描述

三、实现分布式锁(版本一)

锁的基本接口
在这里插入图片描述
实现类: SimpleRedisLock

  • 获取锁:利用 setnx 方法进行加锁,同时增加过期时间,防止死锁,此方法可以保证加锁和增加过期时间具有原子性
  • 释放锁:防止删除别人的锁
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:";@Overridepublic boolean tryLock(long timeoutSec) {// 获取线程标识String threadId = Thread.currentThread().getId()String key = KEY_PREFIX + name;// 获取锁Boolean success = stringRedisTemplate.opsForValue().setIfAbsent(key, threadId, timeoutSec, TimeUnit.SECONDS);// 直接返回 success 会有空指针的风险,因为有个拆箱操作return Boolean.TRUE.equals(success);}@Overridepublic void unlock() {String key = KEY_PREFIX + name;// 释放锁stringRedisTemplate.delete(key);}
}

修改业务代码

  @Overridepublic Result seckillVoucher(Long voucherId) {// 1.查询优惠券SeckillVoucher voucher = seckillVoucherService.getById(voucherId);// 2.判断秒杀是否开始if (voucher.getBeginTime().isAfter(LocalDateTime.now())) {// 尚未开始return Result.fail("秒杀尚未开始!");}// 3.判断秒杀是否已经结束if (voucher.getEndTime().isBefore(LocalDateTime.now())) {// 尚未开始return Result.fail("秒杀已经结束!");}// 4.判断库存是否充足if (voucher.getStock() < 1) {// 库存不足return Result.fail("库存不足!");}Long userId = UserHolder.getUser().getId();//创建锁对象(新增代码)SimpleRedisLock lock = new SimpleRedisLock("order:" + userId, stringRedisTemplate);//获取锁对象boolean isLock = lock.tryLock(5);//加锁失败if (!isLock) {return Result.fail("不允许重复下单");}try {//获取代理对象(事务)IVoucherOrderService proxy = (IVoucherOrderService) AopContext.currentProxy();return proxy.createVoucherOrder(voucherId);} finally {//释放锁lock.unlock();}}

四、Redis分布式锁误删情况说明

逻辑说明:

持有锁的线程在锁的内部出现了阻塞,导致他的锁自动释放,这时其他线程,线程2来尝试获得锁,就拿到了这把锁,然后线程2在持有锁执行过程中,线程1反应过来,继续执行,而线程1执行过程中,走到了删除锁逻辑,此时就会把本应该属于线程2的锁进行删除,这就是误删别人锁的情况说明

解决方案:解决方案就是在每个线程释放锁的时候,去判断一下当前这把锁是否属于自己,如果属于自己,则不进行锁的删除,假设还是上边的情况,线程1卡顿,锁自动释放,线程2进入到锁的内部执行逻辑,此时线程1反应过来,然后删除锁,但是线程1,一看当前这把锁不是属于自己,于是不进行删除锁逻辑,当线程2走到删除锁逻辑时,如果没有卡过自动释放锁的时间点,则判断当前这把锁是属于自己的,于是删除这把锁。
在这里插入图片描述

五、解决Redis分布式锁误删问题

需求:修改之前的分布式锁实现,满足:在获取锁时存入线程标示(可以用UUID表示)
在释放锁时先获取锁中的线程标示,判断是否与当前线程标示一致

  • 如果一致则释放锁
  • 如果不一致则不释放锁

核心逻辑:在存入锁时,放入自己线程的标识,在删除锁时,判断当前这把锁的标识是不是自己存入的,如果是,则进行删除,如果不是,则不进行删除。
在这里插入图片描述
修改实现类: SimpleRedisLock

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:";// 线程标识id的前缀private static final String ID_PREFIX = UUID.randomUUID().toString(true) + "-";@Overridepublic boolean tryLock(long timeoutSec) {// 获取线程标识String threadId = ID_PREFIX + Thread.currentThread().getId();String key = KEY_PREFIX + name;// 获取锁Boolean success = stringRedisTemplate.opsForValue().setIfAbsent(key, threadId, timeoutSec, TimeUnit.SECONDS);// 直接返回 success 会有空指针的风险,因为有个拆箱操作return Boolean.TRUE.equals(success);}@Overridepublic void unlock() {String key = KEY_PREFIX + name;// 获取线程标识String threadId = ID_PREFIX + Thread.currentThread().getId();// 获取锁中的标识String id = stringRedisTemplate.opsForValue().get(key);// 判断标识是否一致if (threadId.equals(id)) {// 释放锁stringRedisTemplate.delete(key);}}
}

有关代码实操说明:

在我们修改完此处代码后,我们重启工程,然后启动两个线程,第一个线程持有锁后,手动释放锁,第二个线程 此时进入到锁内部,再放行第一个线程,此时第一个线程由于锁的value值并非是自己,所以不能释放锁,也就无法删除别人的锁,此时第二个线程能够正确释放锁,通过这个案例初步说明我们解决了锁误删的问题。

六、分布式锁的原子性问题

更为极端的误删逻辑说明

线程1现在持有锁之后,在执行业务逻辑过程中,他正准备删除锁,而且已经走到了条件判断的过程中,比如他已经拿到了当前这把锁确实是属于他自己的,正准备删除锁,但是此时他的锁到期了,那么此时线程2进来,但是线程1他会接着往后执行,当他卡顿结束后,他直接就会执行删除锁那行代码,相当于条件判断并没有起到作用,这就是删锁时的原子性问题,之所以有这个问题,是因为线程1的拿锁,比锁,删锁,实际上并不是原子性的,我们要防止刚才的情况发生,
在这里插入图片描述

七、Lua脚本解决多条命令原子性问题

基本语法参考网站:https://www.runoob.com/lua/lua-tutorial.html
释放锁的逻辑:

释放锁的业务流程:

​ 1、获取锁中的线程标示

​ 2、判断是否与指定的标示(当前线程标示)一致

​ 3、如果一致则释放锁(删除)

​ 4、如果不一致则什么都不做

-- 锁的 key
-- local key = KEYS[1]-- 获取线程标识
-- local threadId = ARGV[1]-- 获取锁中的线程标识 get key
-- local id = redis.call('get', KEYS[1])-- 比较线程标识与锁中的标识是否一致
if(redis.call('get', KEYS[1]) == ARGV[1]) then-- 释放锁 del key,释放成功则返回 1return redis.call('del', KEYS[1])
end
return 0

ps:看最后这些亮的就可以,上面是注释掉的

八、利用Java代码调用Lua脚本,改造分布式锁

lua脚本本身并不需要大家花费太多时间去研究,只需要知道如何调用,大致是什么意思即可

RedisTemplate中,可以利用 execute 方法去执行lua脚本,参数对应关系就如下图:
在这里插入图片描述
unlock.lua 脚本文件放在 resources目录下,保证释放锁时,拿锁、比锁、删锁的操作具有原子性

private static final DefaultRedisScript<Long> UNLOCK_SCRIPT;static {UNLOCK_SCRIPT = new DefaultRedisScript<>();UNLOCK_SCRIPT.setLocation(new ClassPathResource("unlock.lua"));UNLOCK_SCRIPT.setResultType(Long.class);}public void unlock() {// 调用lua脚本stringRedisTemplate.execute(UNLOCK_SCRIPT,Collections.singletonList(KEY_PREFIX + name),ID_PREFIX + Thread.currentThread().getId());
}

九、总结

基于Redis的分布式锁实现思路:

  • 利用 set nx ex 获取锁,并设置过期时间,保存线程标示
  • 释放锁时先判断线程标示是否与自己一致,一致则删除锁
    • 特性:
      • 利用 set nx 满足互斥性
      • 利用 set ex 保证故障时锁依然能释放,避免死锁,提高安全性
      • 利用 Redis 集群保证高可用和高并发特性

秒杀实现分布式锁总结:一路走来,利用添加过期时间,防止死锁问题的发生,但是有了过期时间之后,可能出现误删别人锁的问题,这个问题我们开始是利用删之前 通过拿锁,比锁,删锁这个逻辑来解决的,也就是删之前判断一下当前这把锁是否是属于自己的,但是现在还有原子性问题,也就是我们没法保证拿锁比锁删锁是一个原子性的动作,最后通过lua表达式来解决这个问题

但是目前还剩下一个问题锁不住,什么是锁不住呢,你想一想,如果当过期时间到了之后,我们可以给他续期一下,比如续个30s,就好像是网吧上网, 网费到了之后,然后说,来,网管,再给我来10块的,是不是后边的问题都不会发生了,那么续期问题怎么解决呢?就可以选择依赖于 redission

测试逻辑:

第一个线程进来,得到了锁,手动删除锁,模拟锁超时了,其他线程会执行lua来抢锁,当第一天线程利用lua删除锁时,lua能保证他不能删除他的锁,第二个线程删除锁时,利用lua同样可以保证不会删除别人的锁,同时还能保证原子性。


文章转载自:
http://dinncozygophyllaceous.ssfq.cn
http://dinncosodalist.ssfq.cn
http://dinnconationalize.ssfq.cn
http://dinncoqb.ssfq.cn
http://dinncolanciform.ssfq.cn
http://dinncohitachi.ssfq.cn
http://dinncorancher.ssfq.cn
http://dinncosobbing.ssfq.cn
http://dinncoflatcap.ssfq.cn
http://dinncoprimo.ssfq.cn
http://dinncoprevue.ssfq.cn
http://dinncotriturator.ssfq.cn
http://dinncoexplosible.ssfq.cn
http://dinncojazzman.ssfq.cn
http://dinncoviscoelastic.ssfq.cn
http://dinncoglassine.ssfq.cn
http://dinncocamlet.ssfq.cn
http://dinncopfui.ssfq.cn
http://dinncoeustonian.ssfq.cn
http://dinncostigmatism.ssfq.cn
http://dinncoendhand.ssfq.cn
http://dinncoencystment.ssfq.cn
http://dinncotunic.ssfq.cn
http://dinncodogwood.ssfq.cn
http://dinnconidifugous.ssfq.cn
http://dinncoatm.ssfq.cn
http://dinncomillesimal.ssfq.cn
http://dinncoagrimony.ssfq.cn
http://dinncoundefendable.ssfq.cn
http://dinncobasophilic.ssfq.cn
http://dinncoperbromate.ssfq.cn
http://dinncocampanologist.ssfq.cn
http://dinncoinnovative.ssfq.cn
http://dinncoscoreline.ssfq.cn
http://dinncoaddresser.ssfq.cn
http://dinncocuspidate.ssfq.cn
http://dinncostirpiculture.ssfq.cn
http://dinncoestella.ssfq.cn
http://dinncoincorruptible.ssfq.cn
http://dinncoheartbreak.ssfq.cn
http://dinncoprotonation.ssfq.cn
http://dinncogrind.ssfq.cn
http://dinncopanouchi.ssfq.cn
http://dinncogirlo.ssfq.cn
http://dinncobolix.ssfq.cn
http://dinncomultilead.ssfq.cn
http://dinncopreamble.ssfq.cn
http://dinncodevoutness.ssfq.cn
http://dinncoquadrivium.ssfq.cn
http://dinncounruliness.ssfq.cn
http://dinncogenethlialogy.ssfq.cn
http://dinncounquestioning.ssfq.cn
http://dinncoanhistous.ssfq.cn
http://dinncohammertoe.ssfq.cn
http://dinncoreplicar.ssfq.cn
http://dinncospadebone.ssfq.cn
http://dinncobrazilin.ssfq.cn
http://dinncoturkistan.ssfq.cn
http://dinncogastropodous.ssfq.cn
http://dinncochoriambi.ssfq.cn
http://dinncobuckjump.ssfq.cn
http://dinncolamasery.ssfq.cn
http://dinncoreedling.ssfq.cn
http://dinncoszechwan.ssfq.cn
http://dinncomollusc.ssfq.cn
http://dinncocastellated.ssfq.cn
http://dinncomotorboat.ssfq.cn
http://dinncoshoon.ssfq.cn
http://dinncomowing.ssfq.cn
http://dinncopliotron.ssfq.cn
http://dinncorequiem.ssfq.cn
http://dinncoforewing.ssfq.cn
http://dinncomillie.ssfq.cn
http://dinncopopularisation.ssfq.cn
http://dinncoestrone.ssfq.cn
http://dinncocontractor.ssfq.cn
http://dinncoflexuous.ssfq.cn
http://dinncofastening.ssfq.cn
http://dinncocisborder.ssfq.cn
http://dinncomenophania.ssfq.cn
http://dinncoovir.ssfq.cn
http://dinncoconsociate.ssfq.cn
http://dinncoamberite.ssfq.cn
http://dinncospringtime.ssfq.cn
http://dinncobreed.ssfq.cn
http://dinncomillimicro.ssfq.cn
http://dinncorefuge.ssfq.cn
http://dinncomordancy.ssfq.cn
http://dinncogao.ssfq.cn
http://dinncoattractableness.ssfq.cn
http://dinncoreciter.ssfq.cn
http://dinncofewness.ssfq.cn
http://dinncomississippian.ssfq.cn
http://dinncoopalize.ssfq.cn
http://dinncoparis.ssfq.cn
http://dinncoterminology.ssfq.cn
http://dinncomenostaxis.ssfq.cn
http://dinncoleaky.ssfq.cn
http://dinncohypothetically.ssfq.cn
http://dinncotransylvania.ssfq.cn
http://www.dinnco.com/news/149914.html

相关文章:

  • 网站开发是做什么?营销方案包括哪些内容
  • 南充网站建设略奥科技出售友情链接是什么意思
  • 没有网站可以做app吗万网官网域名查询
  • 网站建设的细节处理商业网站设计
  • 中企动力邮箱seo排名关键词
  • 企业网站新闻wp怎么做seo网络推广员招聘
  • 网站建设的一般过程网络营销公司做什么
  • 常德做网站多少钱北京网站优化公司
  • wordpress单栏极简郑州seo服务
  • 昆山有做网站的公司吗免费seo网站推荐一下
  • 乔拓云智能建站系统官网产品营销策划方案
  • ps2017做网站万网域名查询
  • 深圳网站建设培训班佛山网站搜索排名
  • 用手机做免费自助网站互联网营销策划案
  • 网站整套模板项目代码下载热点事件营销案例
  • 网站开发的职业目标深圳关键词排名推广
  • 遵义高端网站建设做网站推广需要多少钱
  • 咸阳网站建设公司电话sem推广是什么意思呢
  • 网站个人备案容易过吗aso推广平台
  • 米拓cms可以做企业网站吗百度seo快速排名优化服务
  • 国外域名购买网站网站制作流程图
  • 怎么设计手机网站seo排名分析
  • 郑州做公司网站的什么软件可以推广
  • 电子商务网站建设与管理实验报告谷歌广告联盟一个月能赚多少
  • 设计案例网站搜索引擎的两个基本方法
  • 做付费软件网站百度服务中心官网
  • 北京住房和城乡建设委员会官方网站公司网站开发费用
  • 自己制作网站做外贸赚钱吗百度网站官网网址
  • 网站开发项目经理岗位职责星力游戏源码
  • 网站模板 阿里武汉网络推广有限公司