首页 > 其他分享 >敲重点!!!项目实战须知

敲重点!!!项目实战须知

时间:2024-09-08 23:49:23浏览次数:3  
标签:实战 优惠券 领取 coupon 线程 须知 支付 重点 分布式

项目使用的功能的具体场景

举例说明项目中使用线程池的具体场景

签到送积分
针对掉单表中的数据进行相关的轮询判断
拉新分发优惠券
mes系统批量导入物料信息时(比如10000条需要导入,每500条分批导入,分批导入时使用线程池)
针对头一天文章的点赞数,分批批量更新时,线程池

举例说明项目中使用定时任务的场景

针对头一天文章的点赞数,分批批量更新时
掉单处理

举例说明项目中使用分布式锁的场景

抢优惠券
支付回调处理,修改业务订单状态
spring task中

一、支付宝支付功能实现

支付宝扫码付

自己的项目发起预支付,返回二维码的路径

前端展示二维码,用户通过手机扫码支付,支付宝系统通知用户支付结果

支付宝系统通过异步回调的方式,通知我们的系统,支付成功,我们的系统要给支付宝系统返回success

为了防止一些特殊性情况的出现(异步回调失败、终止支付过程),进行掉单处理

我们的系统要进行定时轮询的操作,通过轮询判断交易订单的状态

若一定次数后,交易订单还是未完成状态,关闭交易订单

支付宝h5支付操作(手机网站)

后端发起支付,返回form表单格式的字符中

前端通过js模拟触发form提交,进行支付宝的支付界面(输入密码进行支付)

支付完成,通过return_url,返回我们自己的前端页面

如果中途取消支付,通过quit_ur返回我们的前端页面

另外,支付完成后,支付宝端通过回调的url(notify_url),通知后台系统支付完成

针对回调可能失败的情况,后台通过定时任务进行掉单处理

使用定时任务实现掉单处理 (重要)

使用扫码付,前端定时轮询,进行掉单处理

使用手机网页支付、app支付,后端进行轮询(方案1:使用定时任务;方案2:使用mq消息队列)

本例,使用方案1:

生成交易订单后,同时向掉单表添加一条记录

通过定时任务,轮询掉单表,获取所有的掉单数据,根据orderNo判断交易订单的状态

如果支付完成,删除掉单表数据,修改业务订单数据

如果没有完成,判断轮询次数,如果没有达到指定次数,修改轮询次数,如果达到了,认为不再进行支付,删除掉单数据,关闭交易订单

二、怎么实现签到

(1)首先判断当天是否签到

获取当前时间年月并对日期格式化;获取用户id同时设置key的过期时间;获取当天用户的签到状态,使用bitmap存储签到记录

(2)若没有签到,就进行签到操作

(3)送积分,把积分存储到数据库

根据积分类型获取规则数据;进行异步送积分

(4)获取连续签到天数

根据日期获取指定范围的签到数据;两个方案:1、将数据转为二进制字符串 2、从后往前进行遍历,获取连续1的个数(使用位运算)

(5)根据连续签到天数 来判断是否送积分

过滤查询(用stream流)

如:连签3天送5积分 连签5天送10积分

三、如何实现点赞

1、首先使用Hash存储点赞数据 比如说key代表文章id,field代表用户id,value则为点赞或取消点赞 设1为点赞,0为取消点赞

2、然后用Redis存储当天的文章点赞数 用key表示当天日期,field表示文章id,values表示当天的点赞数

3、再通过Redis的key和field获取数据;

如果没有点赞,就进行点赞操作,将点赞记录存储数据库,针对当天的点赞总数加1;

如果已点赞,就取消并删除点赞记录,对当天的点赞总数减1

4、获取点赞状态,从数据库中获取点赞总数加上当天Redis存储,计算谋篇文章的总数

四、优惠券功能实现

分类:

1.代金券 ,满多少可以使用,比如:5元代金券满100可用,充值100,使用优惠券 最终支付95,

2.满送劵,充值满多少可以送多少,比如:10元满送券满100可用,充值100,支付100,使用优惠券,最终给110

3.折扣券 ,对应的折扣,比如9折券满100可用,充值100,使用优惠券,最终支付90

对应的规则:

新用户 奖励折扣券

用户领取优惠券,只有代金券领取

拉新才奖励 满送劵

每种优惠券,同一个用户,只能领取一个

领取方式:

有2种,第一种:系统发送(新用户、拉新等)第二种:主动领取(是否限制数量)

分析:

梳理需求,明确要实现的内容:

1、新增优惠券 2、审核优惠券 3、查询优惠券列表 4、用户领取优惠券 5、查询我的优惠券

用户领取优惠券:

1、校验

2、查询用户是否以及领过

3、获取分布式锁

尝试加锁,同时设置超时的时间,防止出现问题不会自动释放

4、查询对应的优惠券

验证优惠券状态

5、验证优惠券数量

优惠券数量num,领取数量takenNum

判断num,num = 0 不限制数量; num > 0,说明有限制,就不能超领

===> num - takenNum > 0

6、创建对象,新增到数据库

获取日历对象,用于计算日期,计算优惠券的失效日期

7、修改优惠券领取的数量

8、记录优惠券操作日志

9、释放分布式锁

秒杀:

单位时间,瞬时并发量特别高,但命中率特别低,都需要小心:

1.防止服务器宕机—限流 2.防止超卖 3.性能 4.安全

核心:

用户领取优惠券:1.校验-参数 2.校验-是否领取过 3.校验剩余数量 4.校验优惠券状态 5.分布式锁(优惠券服务集群部署)6.领取 7.改变领取数量 8.记录日志

五、分布式锁的使用

线程安全:多个线程,同时操作同一个资源,可能会重复

怎么解决线程安全?

有2种方式:

1.加锁

保证任何一个时刻,只能有1个线程操作

Java中锁有2个:synchronized和Lock(接口)

synchronized 自动释放,三种用法(区别锁的范围) =》分为同步实例方法、同步静态方法和同步代码块,分别控制不同范围的锁。

2.线程副本

ThreadLocal 每个线程都有自己的资源 =》 提供了一种线程隔离机制,让每个线程都有自己独立的变量副本,从而避免了线程间的竞争和干扰。

为什么使用分布式锁:

如果项目是集群部署,那么可能需要分布式锁来保证线程安全

因为synchronized是基于jvm实现的,可是集群下,多台服务器,就表示多个jvm实例,这样synchronized只能保证在一台机器上可以线程安全

所以需要使用分布式锁解决集群下并发安全的问题

实现原理:

请求来了,先去第三方(Mysql,Redis,zookeeper),尝试加锁,如果加锁成功,那么就执行代码,其他请求也同样操作,加锁失败就不再执行

分布式锁的实现方案:

第一种:基于Mysql实现 特点:慢

第二种:基于Redis实现 特点:快,准确性一般

第三种:基于Zookeeper实现 特点:性能一般,准确性强

选择Redis实现,特别是秒杀场景(短时间内,并发量高,命中率低)

Redis怎么实现分布式分布式锁:

直接使用RLock(红锁),在Redisson内部已经实现了,直接使用即可

RLock原理:

Lock+Lua+setnx+集群+看门狗

代码展示:

1.依赖jar

<!-- https://mvnrepository.com/artifact/org.redisson/redisson -->
<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson</artifactId>
    <version>3.34.1</version>
</dependency>

2.封装工具类

public class RedissonUtil {

  private static RedissonClient client;
  static {
      Config config=new Config();
      config.useSingleServer().setAddress("redis://110.40.192.129:6380").setPassword("123456");
      client=Redisson.create(config);
  }
  
  /**
   * 分布式锁*/
  public static RLock getLock(String key){
      return client.getLock(key);
  }
  

}

3.在需要的地方,加锁

@Transactional //事务
@Override
public R save(UserCouponAdd add) {
    //1.校验
    if(add==null){
        return R.fail("亲,请检查参数信息");
    }
    //2.查询 用户是否已经领过
    UserCoupon userCoupon=dao.selectOne(new LambdaQueryWrapper<UserCoupon>()
            .eq(UserCoupon::getUid,add.getUid()).eq(UserCoupon::getCid,add.getCid()));
    if(userCoupon!=null){
        //之前领取过
        return R.fail("亲,你已经领取过了!");
    }
    //3.获取分布式锁
    RLock lock= RedissonUtil.getLock(RedisKeyConfig.COUPON_LOCK+add.getCid());
    //尝试加锁,同时设置超时的时间,防止出现问题不会自动释放
    try {
        if(lock.tryLock(3, TimeUnit.SECONDS)) {
            //4.查询对应的优惠券
            Coupon coupon = couponDao.selectById(add.getCid());
            if (coupon == null) {
                return R.fail("亲,优惠券不存在!");
            }
            //验证优惠券状态
            if(!"审核通过".equals(coupon.getStatus())){
                return R.fail("亲,优惠券无效");
            }
            //5.验证 优惠券数量
            if (coupon.getNum() > 0) {
                //优惠券,如果不限制数量 num=0,num>0 说明有限制 就不能超领
                if (coupon.getNum() - coupon.getTakenum() <= 0) {
                    return R.fail("亲,来晚了,已被领完!");
                }
            }

            //6.创建对象,新增到数据库
            //获取日历对象 用于计算日期 计算优惠券的失效日期
            Calendar calendar = Calendar.getInstance();
            calendar.add(Calendar.DAY_OF_MONTH, coupon.getDays());
            userCoupon = new UserCoupon(add.getUid(),add.getCid(),coupon.getMoney(),coupon.getUsemoney(),calendar.getTime(),coupon.getType());
           
            if (dao.insert(userCoupon) <= 0) {
                return R.fail("亲,领取失败!");
            }
            //7.修改优惠券领取的数量
            couponDao.updateTakeNum(add.getCid());

            //8.记录优惠券操作日志
            logDao.insert(new CouponLog(add.getUid(), userCoupon.getId(), coupon.getMoney(), "领取优惠券", "领取" + coupon.getTitle() + "成功"));

            //9.释放分布式锁
            lock.unlock();

            return R.ok("");
        }
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    }
    return R.fail("亲,领取失败");
}

标签:实战,优惠券,领取,coupon,线程,须知,支付,重点,分布式
From: https://blog.csdn.net/m0_53369973/article/details/141907121

相关文章

  • 鹏哥C语言自定义笔记重点(44-)
    44.不能给地址复制,strcpy拷贝过去连带着\045.46. 47. 48.strstr   //查找子串的一个函数49.strtok  //切割字符串 50.strerror   //返回错误码,所对应的错误信息 检查的是文件51.如果不正确则返回0  52.memcpy负责拷贝两块独立空间......
  • 数据分析实战第一节随笔
    引言Python,作为一种高级编程语言,以其简洁明了的语法和强大的功能库,赢得了全球开发者的广泛青睐。它不仅适用于数据科学、机器学习、人工智能等领域,而且在Web开发、自动化脚本编写、科学计算等方面也发挥着重要作用。本文将带领读者从Python的基础语法开始,逐步深入到实际应用,探索P......
  • Java并发编程实战 07 | 如何正确停止线程
    什么时候需要停止一个线程?一个线程被创建并启动之后,大部分情况下都会自然运行至结束,但是也有一些情况需要主动停止线程,比如:用户主动取消执行:用户可能会中止一个正在进行的操作,这时需要停止相关线程。运行时错误或超时:线程可能因为运行时错误或超时而需要被停止,以避免长时......
  • Java并发编程实战 08 | 彻底理解Shutdown Hook
    钩子线程(HookThread)简介在一个Java应用程序即将退出时(比如通过正常执行完成或通过用户关闭应用程序),通常需要进行一些清理操作,例如:释放资源(如文件句柄、网络连接)。关闭数据库连接。保存未完成的数据或状态。我们可以通过钩子线程实现这一点,钩子线程是指在程序结束时,JVM......
  • 影刀RPA实战:自动化批量生成条形码完整指南
    今天我们聊聊使用影刀来实现批量生成条形码,条形码在零售行业运用非常广泛,主要作用表现在产品识别,库存管理,销售管理,防伪保护等,这些作用使其成为现代商业和工业环境中不可或缺的工具,它极大地提高了数据处理的速度和准确性,降低了运营成本,并提高了整体的工作效率。影刀批量生成条......
  • 基于django+vue重点实验室通用官方网站设计与实现【开题报告+程序+论文】-计算机毕设
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容研究背景随着科技创新的不断推进,重点实验室作为科研创新体系的核心组成部分,承载着推动学科发展、培养高层次人才、开展前沿技术研究与转化等重要使......
  • 龙芯+FreeRTOS+LVGL实战笔记(新)——03完成驱动的移植
            本专栏是笔者另一个专栏《龙芯+RT-Thread+LVGL实战笔记》的姊妹篇,主要的区别在于实时操作系统的不同,章节的安排和任务的推进保持一致,并对源码做了改进和优化,各位可以先到本人主页下去浏览另一专栏的博客列表(目前已撰写36篇,图1所示),再决定是否订阅。此外,也可以前......
  • WGCLOUD实战使用 - 自动计算磁盘剩余空间的可使用天数
    WGCLOUD是一款免费开源的运维监控软件,性能优秀,部署简单,轻巧使用,支持大部分的Linux和Windows、安卓、MacOS等平台安装部署最近发布的新版本,WGCLOUD新增了可以自动计算每个磁盘剩余空间的可使用天数,主要是根据最近一周磁盘的使用情况,系统自动计算所得,如下图......
  • 软件测试-RobotFramework-实战(清除、输入文本;鼠标点击;下拉框select、li;实战演示视频)
    学习笔记记录在用户信息界面,主要涉及头像上传,输入文本,选择按钮,下拉框选项。一、清除、输入文本 上传前一篇已经完成了,对于输入文本,主要就是一行代码inputtext输入框的地址要输入的文本但是如果输入框内还含有文本,就需要进行清除。\8--表示删除一个字符。 pre......
  • 强调重点元素、弱化辅助元素、去掉无关元素,工控HMI还能好不了
    HMI设计,尤其工控领域的HMI设计,千万不要走极端,把界面搞得花哨,或者所谓的美观,切记实现功能才是第一位的。在人机界面(HMI)设计中,强调重点元素、弱化辅助元素、去掉无关元素是非常重要的,可以提高用户体验和界面的可用性。1.强调重点元素:通过颜色、大小、对比度等方式来突出显......