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

重庆手机网站制作/湖南企业网站建设

重庆手机网站制作,湖南企业网站建设,做网站需要写代码吗,网站建设 服务内容上一章说了在单体应用中加锁解决缓存击穿问题,但是在分布式中,每个服务会有很多个,如果使用本地锁,它只锁自己的服务,而不能实现在所有的服务中只查询一次数据库,所以在这种情况下,我们可以考虑…

  上一章说了在单体应用中加锁解决缓存击穿问题,但是在分布式中,每个服务会有很多个,如果使用本地锁,它只锁自己的服务,而不能实现在所有的服务中只查询一次数据库,所以在这种情况下,我们可以考虑使用分布式锁
  

基本原理

在这里插入图片描述
  所有的服务都去一个公共的地方占锁,当一个服务拿到锁以后,他就可以执行相关的逻辑,而其他的服务就处于等待状态,这个公共的地方可以使MySQL,也可以是Redis,当然,我们的服务开发使用Redis做缓存,肯定是在Redis中加锁更加的方便,而Redis本身也提供对应的占锁的命令,详细请查看官方文档(传送门)
在这里插入图片描述
EX seconds-设置指定的到期时间,以秒为单位。
PX 毫秒-设置指定的到期时间(以毫秒为单位)。
NX -只有key不存在时设置key,相当于Redis中有锁,线程等待,我们在使用时就基于此
XX -只有key存在时设置key。
KEEPTTL -保留与key关联的生存时间。
GET-返回存储在key处的旧值;如果key不存在,则返回nil。
  先来测试哈这个命令,可以看到,当我同时向Redis中set数据,并且使用NX,只有一个成功,这就是分布式锁的基本原理
在这里插入图片描述
  用Java代码来表达

public void redisLock() throws InterruptedException {// 通过NX方式存值,占分布式锁Boolean flag = template.opsForValue().setIfAbsent("lock", "lock is not exist");if (flag) {//占锁成功//执行业务System.out.println(template.opsForValue().get("lock"));//业务执行成功后,需要删除锁给其他人用template.delete("lock");} else {//占锁失败,进行重试TimeUnit.SECONDS.sleep(50);redisLock();}
}

  这个锁相当于一个占位符,当服务拿到这个锁就可以进行后面的逻辑代码,而没有拿到锁的服务只能进行等待,这个锁是不参与实际业务的
  但是这个锁就会衍生出一个问题,当我们的业务代码出现异常,而导致该进程结束而没有删除锁,那么锁将一直被占用,这就造成了死锁,这个问题可以通过设置过期时间来解决,在加锁时设置锁的过期时间,但是要保证这两个操作原子性

public void redisLock() throws InterruptedException {// 通过NX方式存值,占分布式锁,设置过期时间防止死锁Boolean flag = template.opsForValue().setIfAbsent("lock", "lock is not exist",30,TimeUnit.SECONDS);if (flag) {//占锁成功//执行业务System.out.println(template.opsForValue().get("lock"));//业务执行成功后,需要删除锁给其他人用template.delete("lock");} else {//占锁失败,进行重试TimeUnit.SECONDS.sleep(50);redisLock();}
}

  同样的在删除锁的还会出现问题,例如:业务逻辑执行时间较长,而锁的过期时间较短,当业务还没执行完锁已经过期,而其他的业务已经可以占锁了,当第一个业务逻辑执行完后进行删锁,就删除了是其他服务的锁。解决办法:给自己的服务指定uuid唯一值

public void redisLock() throws InterruptedException {// 通过NX方式存值,占分布式锁,设置过期时间防止死锁String uuid = UUID.randomUUID().toString();Boolean flag = template.opsForValue().setIfAbsent("lock", uuid, 30, TimeUnit.SECONDS);if (flag) {//占锁成功//执行业务String lock = template.opsForValue().get("lock");System.out.println(lock);//业务执行成功后,需要删除锁给其他人用if (lock.equals(uuid)){//判断当前锁的值,防止误删其他服务的锁template.delete("lock");}} else {//占锁失败,进行重试TimeUnit.SECONDS.sleep(50);redisLock();}
}

  在删锁的时候还有其它问题,当获取锁的值,由于网络传输的延时,在比对成功后还没执行删除之前,这个锁的就失效了,所以这个时候删除的锁依旧是其他服务的锁,这是有网络传输需要消耗时间造成的,这个需要使用lua脚本进行处理,Redis官方也是推荐给我们这么做,而我们的代码时是没办法直接处理的,所以最后就演变成下面的结果

public void redisLock() throws InterruptedException {// 通过NX方式存值,占分布式锁,设置过期时间防止死锁String uuid = UUID.randomUUID().toString();Boolean flag = template.opsForValue().setIfAbsent("lock", uuid, 30, TimeUnit.SECONDS);if (flag) {//占锁成功try {//执行业务String lock = template.opsForValue().get("lock");System.out.println(lock);} finally {//业务执行成功后,需要删除锁给其他人用//lua脚本解锁String script = "if redis.call('get',KEYS[1]) == ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end";//删除锁template.execute(new DefaultRedisScript<Long>(script, Long.class), Arrays.asList("lock"), uuid);}} else {//占锁失败,进行重试TimeUnit.SECONDS.sleep(50);redisLock();}
}

  分布式锁还有更加强大专业的框架来处理,下一章就使用Redisson来解决这一些的问题

http://www.jmfq.cn/news/4921507.html

相关文章:

  • 专业做网站套餐/优化网哪个牌子好
  • 用vs2012做简单网站/临沂今日头条新闻最新
  • 网站服务器ecs/seo网站优化
  • 连云港北京网站建设/百度手机助手安卓版
  • 重庆好网互联/上海搜索优化推广
  • 做简历最好的网站/百度关键词排名原理
  • 开县网站建设/四川seo关键词工具
  • 工程公司资质怎么申请/长春网站优化平台
  • 政府网站建设的建议/免备案域名
  • 如何销售做网站/seo的搜索排名影响因素有哪些
  • 淇县住房和城乡建设局网站/seo深圳网络推广
  • 做棋盘游戏辅助的网站/百度竞价广告收费标准
  • seo免费工具/seo具体是什么
  • 佛山有那些定制网站建设公司/百度客服在哪里找
  • 做网站的人是什么职位/百度竞价培训班
  • 深圳网站建设 东毅虎/整站优化推广
  • 阿里云服务器配置网站/今日新闻最新消息50字
  • 做彩票网站能挣到钱吗?/优化视频
  • 穹拓做网站/青岛seo整站优化哪家专业
  • wordpress wp_enqueue_style/北京谷歌seo公司
  • 屏蔽收索引擎抓取网站/深圳十大教育培训机构排名
  • 建立网站需要什么设备/广告软文范例大全100字
  • 民政局网站建设工作总结/重庆网站网络推广
  • 网站建设主题/晚上看b站
  • 网站查询域名访问/com域名多少钱一年
  • 网站是怎么制作的/最新军事新闻 今日 最新消息
  • 委托网络公司做网站的合同/海南百度推广运营中心
  • 物流官网网站/营销型网站的分类不包含
  • 问答类咨询网站的建设/百度网盘怎么用
  • 上海网站建设联系电话/推广网站排名优化seo教程