优惠券订单
在多组织架构下加入优惠券系统的必要性
在多组织架构下加入优惠券系统是非常必要的,因为优惠券系统可以帮助组织吸引并留住客户,提高销售额和同行竞争力。通常优惠券系统可以在下列方面提供显著帮助:
- 促进销售增长:优惠券可以激励客户购买更多的产品或服务,从而实现销售增长。通过在不同的组织之间进行优惠券的分享和兑换,可以进一步扩大销售范围并增加客户数量。
- 提高品牌忠诚度:优惠券系统可以使客户感到被重视,提高客户的满意度和忠诚度。这对于长期发展品牌和巩固市场地位非常重要。
- 精准定位客户:通过优惠券系统收集客户的消费习惯和兴趣爱好,可以更好地理解客户需求和购买意愿,实现更精准的客户定位和营销。
- 节约成本:通过优惠券系统,可以实现更精细的营销策略,同时减少广告和促销成本。另外,优惠券系统还可以帮助组织管理库存和销售数据,实现成本节约和效率提高。
综合以上几点,可以看出在多组织架构下加入优惠券系统的必要性非常大,而智慧停车场管理系统作为平台为了提升自身的竞争力,加入优惠券系统也是非常必要的。
如何设计
优惠券作为一种经典的促销手段,有两种类型:平价券和秒杀券。它们的主要区别在于促销的形式和目的。
平价券通常是一种固定金额或折扣幅度的优惠券,一般适用于所有商品或一定范围内的商品。客户可以在下单时输入优惠码或者点击相关链接进行领取,使订单金额直接减少优惠金额或折扣后的金额。平价券一般适用于需要推广的商品或需要促销的活动,它通过高折扣的方式吸引客户,达到促销的目的。
秒杀券则是一种时间限制性的优惠券,主要目的是推动销售和清理库存。秒杀券会设定一个非常低的价格,并且限定一定时间内销售,一旦时间耗尽或者库存被抢购完毕,秒杀活动就会结束。客户可以通过在设定的时间范围内进入特定的页面或链接来抢购秒杀商品。秒杀券一般适用于滞销商品或过季商品,其目的在于通过低价促销的方式清除库存,同时也可以提升客户的购物满足感和留存热度。
综上根据优惠券的概念和需求设计的表结构如下:
有了表结构就可以设计我们的实体模型,然后就能完成基本的额增删改查业务了。停车场可以适时发布自己的优惠券吸引用户消费,而用户则需要针对平价券或者秒杀券进行抢购。
而购买优惠券和购买普通的商品流程是一样的,首先需要下订单,然后去支付,再进行使用。因此应用中还应存在一张优惠券订单表:
而针对秒杀券业务则较为复杂,需要重点解释。
首先是秒杀券的下单业务流程,由于秒杀券往往是促销和减库存,因此优惠力度一般比较大,因此它不会像评价券一样无限制购买,一般会限定数量。同时会再限定时间段开始,并且售完即终止。因此下单时需要判断两点:
- 秒杀是否开始或结束,如果尚未开始或已经结束则无法下单
- 库存是否充足,不足则无法下单
下面是具体业务流程:
按照业务流程实现时还需注意一些问题:
- 多线程并发下库存超卖的问题
- 乐观锁失败率高如何解决
- 如何保证一人一单
- 悲观锁实现一人一单但事务失效的问题
库存超卖该如何解决
什么是库存超卖问题:
库存超卖是电子商务中常见的问题,它指的是在电商平台上卖家所提供的某一个商品的库存数量已经不足,但是,由于种种原因(比如系统数据更新延迟等),仍在平台上继续销售并接受用户的下单,最终导致实际库存已经不足以满足所有订单的情况。这时,平台和卖家将面临未能交货或延迟交货的情况,给顾客带来极大的不便和巨大的损失,对于电商的品牌形象和信誉带来很大的打击。
库存超卖是一个非常严重的问题,不仅会影响卖家和买家之间的交易,还会对电商平台的声誉产生负面影响,损害品牌形象。因此,对于电商平台和卖家来说,很有必要及时管理和更新库存数据,避免库存超卖的情况发生,促进在线交易的良性发展。
秒杀券库存超卖出现的原因:
秒杀是指在特定时间内对于特定商品进行特价销售的活动,其特点是时间短、价格优惠极大、商品数量有限等。在这种场景下,会出现较高的用户流量和系统并发量,因此需要具备一定的系统可靠性和稳定性。因此在这种情况下并发问题出现的非常频繁,而超卖问题就是一种典型并发问题。
库存超卖是指销售平台上的商品库存数量与实际库存数量不一致,导致一些顾客购买的商品实际上已经售罄或不存在。
从高并发的角度来看,库存超卖出现的原因可能是因为并发量过大,系统无法及时地将一个订单的状态及时更新到库存中,导致同一时间多个顾客都可以购买同一个已售罄的商品。从而出现库存超卖。
当系统面对大量的并发请求时,需要处理大量的订单信息、库存信息、支付信息等,这需要消耗大量的计算资源和存储资源。如果系统无法及时地响应请求或处理数据,就容易出现数据不一致的情况,从而导致库存超卖的发生。
因此,在系统设计和架构方面,应该考虑如何提高系统的性能和吞吐量,避免因高并发而导致的库存超卖等问题的发生。这种情况下有一种常见的解决方案,乐观锁方案
乐观锁解决库存超卖问题
什么是乐观锁:
认为现场安全问题不一定会发生,因此不加锁,只是再更新数据时去判断有没有其他线程对数据做了修改。
- 如果没有修改则认为是安全的,自己才更新数据
- 如果已经被其它线程修改说明发生了安全问题,此时可以重试或异常
说到乐观锁就不得不说明一下悲观锁,两种解决方案是一种相反的设计理念,悲观锁认为:
线程安全问题一定会发生,因此再操作数据之前先获取锁,确保线程串行执行,例如 Synchronized 和 Lock 都属于悲观锁
乐观锁的常见实现方案有两种:
- 版本号法
- CAS法
CAS 是根据情景对版本号法做了简化。将乐观锁整合进应用确实能够解决超卖问题,但是却产生了新的问题,乐观锁解决方案会造成抢购失败率较高
如何解决抢购失败率较高的问题
以库存为例,乐观锁的关键是判断之前查到的库存数据是否被修改过,原来是保持一致,实际可以以 stock > 0 为条件,这样就能减少秒杀失败率低的问题。
如何保证一人一单
在实现秒杀业务时,这种一人一单的限制是非常关键的,因为秒杀业务具有高并发和短时间内大量交易的特点,如果没有这种限制,很容易导致库存被少数人大量占用,让更多的顾客失去机会,并引起品牌形象的损害。
因此,针对秒杀业务的实现,需要在系统中引入一些限流措施,确保每个顾客只能购买一次,并且库存数量能够得到及时的更新。那么如何实现呢?
一人一单业务逻辑如下:
实现方式也是以先查询再修改的形式,不过这次是插入。因此依然会出现并发问题,即同一个用户可能下多个订单。不同于先查询再修改的形式,插入无法使用乐观锁,因此必须使用悲观锁的解决方案
如何使用悲观锁保证一人一单
- 不能锁方法,锁方法就是锁 this,那么每个新用户都会被锁住,实际上只需让同一个用户多次访问时被锁住就行了,这里需要锁 userId.intern(),intern() 代表使用常量池
- 由于加了事务,事务是再方法返回时提交,而之前并没有锁整个方法,导致可能订单未插入同一个用户却已经多次查询并插入多条订单了,因此需要锁定整个方法调用
- 锁方法调用事务没有生效,this.method 的 this 并不是代理对象,而事务使用 aop 实现的,因此实际应该用 proxy.method 调用,才能触发 @trasactional 事务回滚
这样一个人只能创建一个订单就完成了。
停车缴费订单
每次根据计费规则查询费用时自动生成缴费订单。如果用户充值了钱包就自动扣费。