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

网站 别名乌兰察布seo

网站 别名,乌兰察布seo,seo优化标签,做网站能收回吗各位小伙伴们大家好#xff0c;欢迎来到这个小扎扎的Redis 6专栏#xff0c;在这个系列专栏中我对B站黑马的Redis教程进行一个总结#xff0c;鉴于 看到就是学到、学到就是赚到 精神#xff0c;这波依然是血赚 ┗|#xff40;O′|┛ #x1f4a1;Redis知识点速览#… 各位小伙伴们大家好欢迎来到这个小扎扎的Redis 6专栏在这个系列专栏中我对B站黑马的Redis教程进行一个总结鉴于 看到就是学到、学到就是赚到 精神这波依然是血赚 ┗|O′|┛ Redis知识点速览 分布式锁 业务逻辑分析 Redis命令 代码实现 分布式锁误删问题 问题原因分析 代码实现 Lua脚本 讲过上一节的分析可知服务器集群项目中的锁是无法精准的锁住线程资源的于是我们就是需要使用分布式锁分布式锁该如何使用又有什么注意点呢就让我们进入接下来的学习 首先使用idea模拟搭建一个tomcat服务器集群并使用Nginx对集群中的服务器实现负载均衡配置完负载均衡之后发送两次请求就会在idea的运行窗口中发现两次请求的运行是分别在两个服务器中完成这就是集群的轮询机制 分布式锁 业务逻辑分析 在单JVM虚拟机多线程执行的情况下可以使用JVM内部的锁机制来控制多进程的并发执行借此可以保证一个用户只能下一个优惠券订单。但是在分布式的情况下每一个JVM虚拟机都有一个锁监视器不同JVM里的不同线程之间的访问的并不是同一个锁监视器所以说此时再使用synchronized锁就无法满足一个用户限买一单的业务情况了于是就需要使用分布式锁 分布式锁就是满足分布式系统或集群模式下多进程可见并且互斥的锁。一般实现分布式锁的技术主要就是MySQL、Redis和ZooKeeper但是综合对比来看的话Redis作分布式锁的性能更高一些Redis是在JVM虚拟机之外的一种应用可以满足多线程都可见互斥可以使用setnx这种的互斥命令来实现但是使用Redis会存在安全性问题如果Redis崩溃的话会导致锁无法释放而出现死锁现象解决这一问题的方案就是使用TTL过期时间就算崩溃也可以实现到期自动释放。 Redis命令 使用Redis实现分布式锁的步骤主要就是使用setnx体现互斥锁然后expire过期时间防止宕机死锁但是如果服务在setnx之后expire之前宕机的话依旧会造成死锁现象。于是我们可以使用以下命令在互斥的同时设置超时时间这样的话即是在设置锁之后宕机依旧可以凭借超时时间释放锁 SET lock thread NX EX ttl超时时间代码实现 将获取锁和释放锁业务抽取出来使用接口和实现类来完成 /*** author : mereign* date : 2022/6/10 - 12:01* description : 分布式锁*/ public interface ILock {/*** 尝试获取锁* param timeoutSec 锁的超时时间* return 是否成功获取锁*/boolean tryLock(long timeoutSec);/*** 释放锁*/void unLock(); }/*** author : mereign* date : 2022/6/10 - 13:31* description : 分布式锁的实现类*/ public class SimpleRedisLock implements ILock {private String name;/***先获取StringRedisTemplate对象才能使用代码操作Redis*/private StringRedisTemplate stringRedisTemplate;public SimpleRedisLock(String name, StringRedisTemplate stringRedisTemplate) {this.name name;this.stringRedisTemplate stringRedisTemplate;}Overridepublic boolean tryLock(long timeoutSec) {// 获取当前操作线程的标识long threadId Thread.currentThread().getId();// 获取锁Boolean res stringRedisTemplate.opsForValue().setIfAbsent(RedisConstants.KEY_PREFIX name, threadId , timeoutSec, TimeUnit.SECONDS);// res是Boolean的包装类返回结果的时候涉及到拆箱问题有可能存在结果为null的情况此时就需要返回结果与true的比较避免了空指针风险return Boolean.TRUE.equals(res);}Overridepublic void unLock() {// 释放锁stringRedisTemplate.delete(RedisConstants.KEY_PREFIX name);} }定义了分布式锁的获取和释放接下来就是在一人一单业务代码中将锁机制升级成多线程锁了主要修改的代码为就是5~14行由单体的synchronized锁改为使用自定义的Redis锁并根据不同线程获取锁的不同结果定义了不同的业务 public Result secKillVoucher(Long voucherId) {// 单用户id(拦截器中做登录验证的用户id)Long userId UserHolder.getUser().getId();// 创建锁对象SimpleRedisLock lock new SimpleRedisLock(order: userId, stringRedisTemplate);// 获取锁boolean isLock lock.tryLock(1200);// 判断是否获取锁成功if (!isLock) {// 获取锁失败返回错误或者重试return Result.fail(不允许重复下单 );}// 获取锁成功继续下单的业务逻辑try {// 查询优惠券SeckillVoucher seckillVoucher seckillVoucherService.getById(voucherId);// 获取时间 判断秒杀活动是否开始或者结束if (seckillVoucher.getBeginTime().isAfter(LocalDateTime.now())) {return Result.fail(活动暂未开始);} else if (seckillVoucher.getEndTime().isBefore(LocalDateTime.now())) {return Result.fail(活动已经结束);}// 判断库存是否充足if (seckillVoucher.getStock() 1) {return Result.fail(库存不足活动结束);}// user_id和voucher_id联合查询订单数int count query().eq(user_id, userId).eq(voucher_id, voucherId).count();// 订单数为1 就说明已经下过单了if (count 0) {return Result.fail(您已经购买过该商品了);}// 扣减库存boolean update seckillVoucherService.update().setSql(stock stock - 1).eq(voucher_id, voucherId).gt(stock, 0).update();if (!update) {return Result.fail(库存不足);}// 创建订单 并返回idVoucherOrder order new VoucherOrder();// 订单id(redis全局唯一id) 下单用户id(拦截器中做登录验证的用户id) 优惠券id(直接传过来的id)long orderId generator.nextId(order);order.setId(orderId);order.setUserId(userId);order.setVoucherId(voucherId);save(order);return Result.ok(orderId);} finally {// 释放锁lock.unLock();} }分布式锁误删问题 问题原因分析 这个问题出现在Redis锁设置的超时时间上由于设置了超时时间所以可能出现一下情况即当线程1获取到锁之后执行下单业务但是由于业务堵塞锁已经超出TTL时间自动释放此时线程2趁机获取Redis锁成功执行下单业务线程2的下单业务执行到一半时线程1完成下单使用del命令释放锁此时线程1释放的是线程2的锁于是现在锁又处于闲置状态于是线程3来获取Redis锁成功执行下单业务此时一共有同一个用户的两个线程在同时操作 为了解决以上出现的问题需要在每次释放锁之前都通过锁的线程标识(Redis锁对应的值)判断一下是不是自己的锁如果是就使用del命令释放锁否则就不做操作。但是有一点值得注意之前锁的线程标识使用的是线程的name这样的话很容易就造成不同JVM虚拟机里的线程name冲突影响判断于是可以使用UUID随机生成一组数字加上线程name作为线程的标识这样更能确保唯一性 代码实现 综上所述一共有两处需要改进的地方一个是使用UUID加线程name作为线程标识(主要修改的是获取锁方法加上UUID的获取)一个是在使用del释放锁之前判断一下是否是自己的锁 public static final String ID_PREFIX UUID.randomUUID(true) -;public boolean tryLock(long timeoutSec) {// 获取当前操作线程的标识String threadId RedisConstants.ID_PREFIX Thread.currentThread().getId();// 获取锁Boolean res stringRedisTemplate.opsForValue().setIfAbsent(RedisConstants.KEY_PREFIX name, threadId, timeoutSec, TimeUnit.SECONDS);// res是Boolean的包装类返回结果的时候涉及到拆箱问题有可能存在结果为null的情况此时就需要返回结果与true的比较避免了空指针风险return Boolean.TRUE.equals(res); }public void unLock() {// 获取当前操作线程的标识String threadId RedisConstants.ID_PREFIX Thread.currentThread().getId();// 通过锁名 获取redis中存储的锁对应的标识String rid stringRedisTemplate.opsForValue().get(RedisConstants.KEY_PREFIX name);if (threadId.equals(rid)) {// 释放锁stringRedisTemplate.delete(RedisConstants.KEY_PREFIX name);} }Lua脚本 Redis提供了Lua脚本功能在一个脚本中编写多条Redis命令确保多条命令执行时的原子性。Lua是一种编程语言它的基本语法大家可以参考网站https://www.runoob.com/lua/lua-tutorial.html 使用Redis命令调用脚本的常见命令可以是 EVAL “redis.call(‘set’, ‘key’, ‘value’)” num 上述命令解释为EVAL是调用后面双引号中就是所调用的脚本语句而最后的num即脚本语句中的KEYS类型参数的个数num之外的就是ARGV(value)类型的参数。比如说接下来这一个语句就代表着setname为Rose其中KEYS类型的参数有1个就是num后面的第一个name剩下的都是ARGV(value)类型的数据其中调用的是KEYS[1]和ARGV[2]也就是name和Rose EVAL “redis.call(‘set’, ‘KEYS[1]’, ‘ARGV[2]’)” 1 name age Rose
http://www.zqtcl.cn/news/831193/

相关文章:

  • 哈尔滨建站模板搭建马鞍山市网站建设
  • 上海网站设计专注乐云seo个人简介代码网页制作模板
  • 法律网站建设价格做视频周边的网站
  • 京东物流网站地方门户网站源码下载
  • 重庆建设工程信息网站企业宣传片制作公司光年映画
  • 哪家做网站好 成都ktv网络推广方案
  • 网站开发的软件支持哈尔滨最新消息
  • jsp淘宝客网站有限公司怎么注册
  • 香奈儿电子商务网站建设策划书怎样进行网络营销吸引顾客
  • 昆山网站建设费用我们公司想做网络推广
  • 网站建设一般要多少钱网站开发主要步骤
  • 商用图片的网站网络文化经营许可证查询
  • c 高性能网站开发弄一个公司网站需要多少钱
  • 建设部网站招标投标文件网页设计专业公司
  • 使用iis6搭建网站wordpress调用搜索功能
  • 装配式建筑网站生活家装饰
  • 怎样做软件网站建设百度网站认证官网
  • phpcms网站什么网站都能进的浏览器
  • 建设配资网站有要求吗网站建设不一定当地
  • 永兴网站开发智慧门店管理服务平台
  • 网站建设前的市场分析李炎辉网站建设教程
  • 乱起封神是那个网站开发的?广州市建设注册中心网站首页
  • 网站开发配置网络广告的投放技巧
  • wordpress 漫画网站安徽省建设厅八大员报名网站
  • 音乐网站排名建设部证书查询网站
  • 长沙建站挺找有为太极wordpress eshop 教程
  • 郑州平台类网站网站开发常见面试题
  • 城乡建设网站职业查询系统做网站设计的需要什么材料
  • ui做的好看的论坛网站加工制造网
  • 南庄网站开发厦门建设局网站城市建设