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

广州市疫情防控最新消息seo搜索优化是什么意思

广州市疫情防控最新消息,seo搜索优化是什么意思,wordpress评论插入图片,首页风格优惠券秒杀一人一单 前言一、需求以及之前存在的问题二、增加一人一单逻辑1.初步代码2.封装一人一单逻辑3.控制锁的粒度 三、事务控制问题四、总结 前言 跟随黑马虎哥学习redis: 这是我认为b站上最好的redis教程,各方面讲解透彻,知识点覆盖…

优惠券秒杀一人一单

  • 前言
  • 一、需求以及之前存在的问题
  • 二、增加一人一单逻辑
    • 1.初步代码
    • 2.封装一人一单逻辑
    • 3.控制锁的粒度
  • 三、事务控制问题
  • 四、总结


前言

跟随黑马虎哥学习redis:

这是我认为b站上最好的redis教程,各方面讲解透彻,知识点覆盖比较全。
黑马redis视频链接:B站黑马redis教学视频
本文参考黑马redis课程笔记


一、需求以及之前存在的问题

需求:修改秒杀业务,要求同一个优惠券,一个用户只能下一单。

之前的问题:
优惠卷是为了引流,但是目前的情况是,一个人可以无限制的抢这个优惠卷,所以我们应当增加一层逻辑,让一个用户只能下一个单,而不是让一个用户下多个单。

具体操作逻辑如下:比如时间是否充足,如果时间充足,则进一步判断库存是否足够,然后再根据优惠卷id和用户id查询是否已经下过这个订单,如果下过这个订单,则不再下单,否则进行下单。

二、增加一人一单逻辑

实现流程:
在这里插入图片描述

1.初步代码

@Override
public 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("库存不足!");}// 5.一人一单逻辑// 5.1.用户idLong userId = UserHolder.getUser().getId();int count = query().eq("user_id", userId).eq("voucher_id", voucherId).count();// 5.2.判断是否存在if (count > 0) {// 用户已经购买过了return Result.fail("用户已经购买过一次!");}//6,扣减库存boolean success = seckillVoucherService.update().setSql("stock= stock -1").eq("voucher_id", voucherId).update();if (!success) {//扣减库存return Result.fail("库存不足!");}//7.创建订单VoucherOrder voucherOrder = new VoucherOrder();// 7.1.订单idlong orderId = redisIdWorker.nextId("order");voucherOrder.setId(orderId);voucherOrder.setUserId(userId);// 7.3.代金券idvoucherOrder.setVoucherId(voucherId);save(voucherOrder);return Result.ok(orderId);}

存在问题:
现在的问题还是和之前一样,并发过来,查询数据库,都不存在订单,所以我们还是需要加锁,但是乐观锁比较适合更新数据,而现在是插入数据,所以我们需要使用悲观锁操作

注意:
在这里提到了非常多的问题,我们需要慢慢的来思考,首先我们的初始方案是封装了一个createVoucherOrder方法,同时为了确保他线程安全,在方法上添加了一把synchronized

2.封装一人一单逻辑

@Transactional
public synchronized Result createVoucherOrder(Long voucherId) {Long userId = UserHolder.getUser().getId();// 5.1.查询订单int count = query().eq("user_id", userId).eq("voucher_id", voucherId).count();// 5.2.判断是否存在if (count > 0) {// 用户已经购买过了return Result.fail("用户已经购买过一次!");}// 6.扣减库存boolean success = seckillVoucherService.update().setSql("stock = stock - 1") // set stock = stock - 1.eq("voucher_id", voucherId).gt("stock", 0) // where id = ? and stock > 0.update();if (!success) {// 扣减失败return Result.fail("库存不足!");}// 7.创建订单VoucherOrder voucherOrder = new VoucherOrder();// 7.1.订单idlong orderId = redisIdWorker.nextId("order");voucherOrder.setId(orderId);// 7.2.用户idvoucherOrder.setUserId(userId);// 7.3.代金券idvoucherOrder.setVoucherId(voucherId);save(voucherOrder);// 7.返回订单idreturn Result.ok(orderId);
}

此时面临的问题:
这样添加锁,锁的粒度太粗了,在使用锁过程中,控制锁粒度 是一个非常重要的事情,因为如果锁的粒度太大,会导致每个线程进来都会锁住

3.控制锁的粒度

intern() 这个方法是从常量池中拿到数据,如果我们直接使用userId.toString() 他拿到的对象实际上是不同的对象,new出来的对象,我们使用锁必须保证锁必须是同一把,所以我们需要使用intern()方法

@Transactional
public  Result createVoucherOrder(Long voucherId) {Long userId = UserHolder.getUser().getId();synchronized(userId.toString().intern()){// 5.1.查询订单int count = query().eq("user_id", userId).eq("voucher_id", voucherId).count();// 5.2.判断是否存在if (count > 0) {// 用户已经购买过了return Result.fail("用户已经购买过一次!");}// 6.扣减库存boolean success = seckillVoucherService.update().setSql("stock = stock - 1") // set stock = stock - 1.eq("voucher_id", voucherId).gt("stock", 0) // where id = ? and stock > 0.update();if (!success) {// 扣减失败return Result.fail("库存不足!");}// 7.创建订单VoucherOrder voucherOrder = new VoucherOrder();// 7.1.订单idlong orderId = redisIdWorker.nextId("order");voucherOrder.setId(orderId);// 7.2.用户idvoucherOrder.setUserId(userId);// 7.3.代金券idvoucherOrder.setVoucherId(voucherId);save(voucherOrder);// 7.返回订单idreturn Result.ok(orderId);}
}

三、事务控制问题

以上代码还是存在问题,问题的原因在于当前方法被spring的事务控制,如果你在方法内部加锁,可能会导致当前方法事务还没有提交,但是锁已经释放也会导致问题,所以我们选择将当前方法整体包裹起来,确保事务不会出现问题:

在这里插入图片描述

但是以上做法依然有问题,因为你调用的方法,其实是this.的方式调用的,事务想要生效,还得利用代理来生效,所以这个地方,我们需要获得原始的事务对象, 来操作事务

Long userId = UserHolder.getUser().getId();//创建锁对象SimpleRedisLock simpleRedisLock = new SimpleRedisLock("order" + userId, stringRedisTemplate);//获取锁boolean isLock = simpleRedisLock.tryLock(1200);if (!isLock) {//获取锁失败,返回错误信息或重试return Result.fail("不允许重复下单");}try {//增加代理对象进行事务的控制IVoucherOrderService proxy = (IVoucherOrderService) AopContext.currentProxy();return proxy.createVoucherOrder(voucherId);}finally {simpleRedisLock.unlock();}

四、总结

这只是一人一单单机实现的方法,因为synchronized锁只能确保在一个jvm中实现锁的互斥,如果在集群中,有多个jvm,那就不能实现互斥锁,最终还是会导致并发问题,这个问题的解决由集群中的分布式锁解决。
在这里插入图片描述

http://www.tj-hxxt.cn/news/15068.html

相关文章:

  • 做钓鱼网站犯法吗开鲁seo服务
  • bbs网站模板互联网域名交易中心
  • 做前端项目怎么进行网站切图搜狗竞价推广效果怎么样
  • 网站上传后打不开网络seo营销推广
  • 廉洁 网站建设下载百度网盘
  • 网站建设怎样找客户设计公司企业网站
  • 做网站签合同百度关键词搜索排名统计
  • 德州哪里做网站专业seo整站优化
  • 北京出名做网站的公司婚恋网站排名前十名
  • 网站开发相关技术百度怎么优化网站排名
  • 整站seo怎么做沙坪坝区优化关键词软件
  • 设计企业展厅的公司成都网站快速优化排名
  • 做网站前台要学什么课程移动优化课主讲:夫唯老师
  • 做ic比较有名的网站广州网络推广专员
  • 品牌创意网站公司网页网站建设
  • 欧洲美妇做爰网站外贸营销策略都有哪些
  • 电子商务网站建设 市场分析seo提升排名
  • 网站一般怎么维护江苏网站建设推广
  • 越南做网站服务器百度秒收录技术
  • 多语言企业网站源码网络推广外包公司
  • 中国风网站配色方案百度开户需要什么资质
  • 使用腾讯云建设网站教程广告多的网站
  • 搅拌机东莞网站建设技术支持重庆网站建设软件
  • 中山建网站咨询电话关于手机的软文营销
  • 东莞网站建设排名 南城泰安网站seo
  • 网站 的空间网站外链购买平台
  • 招商加盟网站建设目的app引导页模板html
  • 南昌网站建设 南昌做网站公司seo优化在哪里学
  • 动漫网站源码免费3a汽车集团公司网络营销方案
  • 石家庄网站建设加王道下拉张家界百度seo