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

做网站租服务器多少钱百度网站地图文件

做网站租服务器多少钱,百度网站地图文件,asp商品网站源码,网站建设报价清单明细本博客为个人学习笔记#xff0c;学习网站与详细见#xff1a;黑马程序员Redis入门到实战 P50 - P54 目录 优惠卷秒杀下单功能实现 超卖问题 悲观锁与乐观锁 实现CAS法乐观锁 一人一单功能实现 代码优化 代码细节分析 优惠卷秒杀下单功能实现 ​ ​ Controller层… 本博客为个人学习笔记学习网站与详细见黑马程序员Redis入门到实战 P50 - P54  目录 优惠卷秒杀下单功能实现 超卖问题 悲观锁与乐观锁 实现CAS法乐观锁 一人一单功能实现 代码优化  代码细节分析  优惠卷秒杀下单功能实现 ​ ​ Controller层代码实现 RestController RequestMapping(/voucher-order) public class VoucherOrderController {Resourceprivate IVoucherOrderService voucherOrderService;PostMapping(seckill/{id})public Result seckillVoucher(PathVariable(id) Long voucherId) {return voucherOrderService.seckillVoucher(voucherId);} } Service层代码实现 //接口类 public interface IVoucherOrderService extends IServiceVoucherOrder {Result seckillVoucher(Long voucherId); }//实现类 Service public class VoucherOrderServiceImpl extends ServiceImplVoucherOrderMapper, VoucherOrder implements IVoucherOrderService {Resourceprivate ISeckillVoucherService seckillVoucherService;Resourceprivate RedisIdWorker redisIdWorker;OverrideTransactionalpublic 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.扣减库存boolean success seckillVoucherService.update().setSql(stock stock - 1).eq(voucher_id, voucherId).update();if (!success) {// 扣减失败return Result.fail(库存不足);}// 6.创建订单VoucherOrder voucherOrder new VoucherOrder();// 6.1订单idlong orderId redisIdWorker.nextId(order);voucherOrder.setId(orderId);// 6.2用户idLong userId UserHolder.getUser().getId();voucherOrder.setUserId(userId);// 6.3代金卷idvoucherOrder.setVoucherId(voucherId);save(voucherOrder);// 7.返回订单idreturn Result.ok(orderId);} } 超卖问题 假设秒杀优惠卷库存为1正常情况抢票逻辑如下图所示。  ​ 假设秒杀优惠卷库存为1高并发情况抢票逻辑如下图所示。  ​ 悲观锁与乐观锁 ​ 由于悲观锁采用串行执行线程的方式因此性能劣于乐观锁。 乐观锁的关键是判断之前查询到的数据是否被修改过常见的方式有以下两种 1.版本号法 为每种秒杀优惠卷添加版本号属性每当该优惠卷的库存被更改时令版本号也发生变化。因此只需要在查询库存的同时查询并记录版本号在修改库存时通过查询当前版本号并判断其是否与先前记录的版本号一致来判断查询到的库存是否已经被其他线程修改过。 ​ 2.CAS法即版本号法的简化利用库存代替版本号 ​ 实现CAS法乐观锁 首先查询秒杀优惠卷信息并保存到变量voucher当判断该优惠卷可以被抢购后在修改该优惠卷库存时需要满足当前优惠卷库存与voucher.getStock()相等的条件。​ 尽管添加了乐观锁但在测试时发现用户抢购优惠卷的成功率过低。原因在于在高并发的情况下假设10个用户同时抢购一张优惠卷那么只有一个用户能够抢购成功其他用户均抢购失败。而在抢票的业务场景下当用户同时进行抢购时只要优惠卷库存大于0即可进行抢购因此只需修改判断条件在修改库存时判断当前库存是否大于0即可。 ​ 一人一单功能实现 ​ 修改Service层实现类中优惠卷秒杀下单seckillVoucher方法代码未优化版本如下 Override Transactional 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.一人一单Long userId UserHolder.getUser().getId();//5.1查询订单int count query().eq(user_id, userId).eq(voucher_id, voucherId).count();//5.2判断是否存在if(count1){//用户已经购买过了return Result.fail(用户已经购买过一次);}//6.扣减库存boolean successseckillVoucherService.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);//8.返回订单IDreturn Result.ok(orderId); } 代码优化  存在的问题尽管代码经过修改但在高并发的情况下仍然存在问题即单个用户在同一刻多次下单多个线程均查询到count0该用户未购买过当前优惠券此时多个线程同时创建订单从而导致一人多单问题。 实现为实现一人一单功能我们需要加锁相比超卖问题中每个线程只是对数据进行修改所以可以使用乐观锁通过判断数据值是否被修改来判断其他线程是否已经对当前数据进行操作。但一人多单的问题中每个线程需要进行添加数据而非修改数据的操作即创建新的订单所以这种情况下我们需要使用悲观锁。 优化后的代码如下所示 Service public class VoucherOrderServiceImpl extends ServiceImplVoucherOrderMapper, VoucherOrder implements IVoucherOrderService {Resourceprivate ISeckillVoucherService seckillVoucherService;Resourceprivate RedisIdWorker redisIdWorker;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();synchronized (userId.toString().intern()) {// 获取当前代理对象IVoucherOrderService proxy (IVoucherOrderService) AopContext.currentProxy();return proxy.createVoucherOrder(voucherId);}}Transactionalpublic synchronized Result createVoucherOrder(Long voucherId) {// 5.一人一单模式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) //使用MP设置sql语句.eq(voucher_id, voucherId).gt(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);// 8.返回订单idreturn Result.ok(orderId);} } 代码细节分析  有以下几个细节我们需要特别注意 1. 首先我们将查询、判断、创建订单等过程封装成createVoucherOrder方法但是我们并不能直接对这个方法加锁如果对这个方法加锁的话将导致创建订单的业务是串行执行的在高并发多用户的情况下性能会很差。 2. 因为是一人一单功能我们需要做的是对同一个用户创建订单的流程进行加锁所以我们根据用户ID来加锁。我们为相同的用户ID配置一把锁从而将锁的范围缩小因此我们将createVoucherOrder方法进行修改如下所示。 3. 然而我们需要确保synchronized()传入的参数对象是相同的synchronized锁才能起作用。因此我们不传入查询得到的userId对象因为我们每次查询后都会赋值给新的userId对象这样会导致传入synchronized()的参数始终不是同一个对象因此我们采用的是synchronized(userId.toString())。 4.但是如果我们直接使用userId.toString() 方法拿到的对象实际上是不同的toString() 的底层逻辑是new出一个新对象因此我们需要使用intern()方法该方法是从常量池中拿到数据能确保我们每次取得的对象都是相同的。得到的代码如下所示。 Transactional //将创建订单封装成一个方法 public Result createVoucherOrder(Long voucherId) {//获取用户IdLong userId UserHolder.getUser().getId();synchronized(userId.toString().intern()) {查询、判断、创建订单等流程...} }//错误情况synchronized(userId.toString()) 5.由于我们是在方法里面加锁因此代码的逻辑是先释放锁再提交事务因此在高并发的环境下可能会出现安全问题即释放锁后提交事务还未完成其他线程又进来了。所以我们应该先提交事务再释放锁。因此我们应该在方法外加锁代码如下。 Override public Result seckillVoucher(Long voucherId) {...Long userId UserHolder.getUser().getId();synchronized (userId.toString().intern()) {return createVoucherOrder(voucherId);} } 6.在以上代码中我们调用createVoucherOrder方法其实是通过this.的方式调用的而this代表的是当前VoucherOrderServiceImpl对象并不是createVoucherOrder的代理对象因此事务是不生效的。要想让事务生效我们需要利用代理对象调用createVoucherOrder方法才能使事务生效代码如下。 Override public Result seckillVoucher(Long voucherId) {...Long userId UserHolder.getUser().getId();synchronized (userId.toString().intern()) {// 获取当前代理对象IVoucherOrderService proxy (IVoucherOrderService) AopContext.currentProxy();return proxy.createVoucherOrder(voucherId);} } 此外我们还需做以下三步。 1.添加动态代理依赖 dependencygroupIdorg.aspectj/groupIdartifactIdaspectjweaver/artifactId /dependency 2.在接口中添加createVoucherOrder(Long voucherId);  public interface IVoucherOrderService extends IServiceVoucherOrder {Result seckillVoucher(Long voucherId);Result createVoucherOrder(Long voucherId); } 3.在启动类中添加注解暴露该代理对象 EnableAspectJAutoProxy(exposeProxy true) MapperScan(com.hmdp.mapper) SpringBootApplication public class HmDianPingApplication {public static void main(String[] args) {SpringApplication.run(HmDianPingApplication.class, args);}}
http://www.tj-hxxt.cn/news/233595.html

相关文章:

  • 网站建设补贴是经信局的政策吗鄂尔多斯建设局网站
  • 佛山网站架设具有价值的常州做网站
  • php 网站建设 教学青岛市建设局网站
  • 微网站建设及微信推广方案ppt模板电商公司有哪些?
  • 湛江做网站制作唯品会购物商城
  • 空壳主体接入网站公司网站开发需要做哪些事
  • 深圳网站建设q双赢世讯网页游戏网站网址
  • 做家政有专门的网站吗专业加速器产业园
  • 网站建设设计原则阳江市网站备案幕布
  • 网站建设与管理课程项目时尚字体设计网站
  • WordPress网站修改品牌成功案例100个
  • 官方网站的英文工商网上核名系统
  • 网站群维护方案广州安全教育平台注册
  • 画廊网站模板官网应用商店下载
  • vs网站开发表格大小设置dw网页怎么使用模板
  • 网站动态页面河南电商网站设计
  • 佛山网站建设哪家评价高建设银行海外分行招聘网站
  • 有什么好的手机推荐网站爱战网关键词查询网站
  • 青海建设厅网站学编程要多少钱
  • 建一个交易网站需要多少钱淘宝代运营公司十大排名
  • 匿名网站建设营销型网站策划 ppt
  • 网站建设 菜鸟教程公司做网站 手机 电脑
  • 佛山网络公司哪家便宜淄博网站建设优化运营熊掌号
  • 浙江做网站公司wordpress插件dedecms
  • 网站建设业务前景做网页要花多少钱
  • 深圳微商城网站设计电话常熟seo关键词优化公司
  • 做网站网页的公司婚礼礼网站如何做的
  • 1 建设网站目的是什么意思室内设计公司图片
  • 51个人网站百度公司介绍
  • 上海网站建设流进销存软件终身免费版