优惠券兑换码生成需求——批量生成任务全局限制唯一

前段时间收到一个优惠券兑换码的需求:管理后台针对一个优惠券发起批量生成兑换码,这些兑换码可以导出分发到各个合作渠道(比如:抖音、京东等),用户通过这些渠道获取到兑换码之后,再登录到我司研发的商城,使用兑换码兑换获得对应的优惠券。

整个需求大致分为两个部分:(1)批量生成兑换码;(2)使用兑换码兑换优惠券。接下来的几篇文章将针对批量生成兑换码功能实现过程中碰到的一系列问题进行分析描述,以便读者再碰到类似问题,可以快速解决。

文章系列如下:

《事务失效问题分析》

《事务同步回调问题分析》

《批量生成任务全局限制唯一》

在此之前,先简单介绍商城技术架构:商城后端服务均采用SpringCloud框架开发,数据库主备,商城所有服务共用一个数据库,数据库持久化框架为MybatisPlus,所有服务采用K8s技术进行部署和治理。


一、问题描述

在《事务同步回调问题》一文末尾,笔者抛出了一个问题:由于兑换码生成过程比较占用资源,所以全平台保证同时只能有一个生成任务在执行。根据生成业务流程图如何保证插入兑换生成记录的并发安全?

二、问题分析

根据上述流程图可知,如果两个用户同时对两个优惠券发起兑换码生成请求,按照通常编码方式,可能会出现两个任务同时执行的情况。通常编码编码方式如下:

java 复制代码
if(dhCodeService.listDoingStatus().size() > 0) {
    dbCodeBatchService.insert(dbCodeBatch);    
}

上述代码存在线程安全问题,有读者可能会建议这段代码加一个synchronized即可,但大家不要忘了,咱们的系统是分布式系统,多服务实例,synchronized只能解决单进程(非分布式)场景中的并发问题。

针对上述问题,有以下解决方案:

(1)分布式锁:如果公司有久经考验相当靠谱的分布式锁方案,并且公司有非常熟悉分布式锁使用的老司机,否则一旦在并发场景出现问题,很难分析并发问题出现的原因;

(2)数据库行级锁:由于我司电商平台只有一个数据库,所以可以放心使用该方案。行级锁有两种使用方式:

    • select * for update:查询时使用for update可以锁住对应的数据行
    • 更新时直接使用条件语句,如果条件满足则更新

笔者将使用条件更新的方式来保证兑换码执行中记录的唯一性,从而保证兑换码生成任务的唯一性。

三、解决方案

具体方案:编写一条根据条件进行插入的sql语句,如下:

sql 复制代码
# 兑换码记录表dh_code_batch中如果不存在状态为DOING的记录,则写入一条生成记录(状态为DOING)
<insert id="saveIfNotExistDoing" parameterType="com.xxx.DhCodeBatch">
    INSERT INTO dh_code_batch (`coupon_id`, `num`, `status`)
    SELECT #{batch.couponId}, #{batch.num}, 'DOING' FROM DUAL
    WHERE NOT EXISTS (SELECT id FROM dh_code_batch WHERE `status` = 'DOING');
</insert>

那么check()方法中对执行中任务记录的唯一校验代码如下:

java 复制代码
if(!dhCodeBatchService.saveIfNotExistDoing(dhCodeBatch)) throw new BusinessException("当前有兑换码生成任务正在执行,请稍后再试!");

至此,兑换码生成记录写入并发问题已解决,兑换码生成任务全局串行得到保证。感谢大家的持续关注!

附带兑换码生成工具类下载

相关推荐
Java探秘者14 分钟前
Maven下载、安装与环境配置详解:从零开始搭建高效Java开发环境
java·开发语言·数据库·spring boot·spring cloud·maven·idea
攸攸太上15 分钟前
Spring Gateway学习
java·后端·学习·spring·微服务·gateway
2301_7869643620 分钟前
3、练习常用的HBase Shell命令+HBase 常用的Java API 及应用实例
java·大数据·数据库·分布式·hbase
2303_8120444623 分钟前
Bean,看到P188没看了与maven
java·开发语言
苹果醋324 分钟前
大模型实战--FastChat一行代码实现部署和各个组件详解
java·运维·spring boot·mysql·nginx
秋夫人26 分钟前
idea 同一个项目不同模块如何设置不同的jdk版本
java·开发语言·intellij-idea
m0_6640470231 分钟前
数字化采购管理革新:全过程数字化采购管理平台的架构与实施
java·招投标系统源码
aqua35357423581 小时前
蓝桥杯-财务管理
java·c语言·数据结构·算法
Deryck_德瑞克1 小时前
Java网络通信—TCP
java·网络·tcp/ip
砥砺code1 小时前
【2024版本】Mac/Windows IDEA安装教程
java