展开菜单
首页 精品内容 本月促销 装机必备 Windows PDF教程 macOS软件 IOS软件 Android AI 专题
全部分类

当前位置:

首页 > 编程开发 > Java+MySQL如何实现设计优惠券系统

Java+MySQL如何实现设计优惠券系统

1Scenario场景电商系统的促销手段(ElectronicCommerceSystems):优惠券拼团砍价老带新优惠券的种类:满减券直减券折扣券优惠券系统的核心流程:发券发券的方式:同步发送or异步发送领券谁能领?所有用户or指定的用户领取上限一个优惠券最多能领取多少张?领取方式用户主动领取or自动发放被动领取用券作用范围商品、商户、类目计算方式是否互斥、是否达到门槛等需求拆解商家侧:创建优惠券发送优惠券用户侧:领取优惠券下单使用优惠券支付2Service服务2.1服务结构设计2.2优惠券系统难点券的

本文目录

    1 Scenario 场景

    电商系统的促销手段(Electronic Commerce Systems):

    • 优惠券

    • 拼团

    • 砍价

    • 老带新

    优惠券的种类:

    • 满减券

    • 直减券

    • 折扣券

    优惠券系统的核心流程:

    发券

    发券的方式: 同步发送 or 异步发送

    领券

    • 谁能领?

    • 所有用户 or 指定的用户

    • 领取上限

    • 一个优惠券最多能领取多少张?

    • 领取方式

    • 用户主动领取 or 自动发放被动领取

    用券

    • 作用范围

    • 商品、商户、类目

    • 计算方式

    • 是否互斥、是否达到门槛等

    需求拆解

    商家侧:

    • 创建优惠券

    • 发送优惠券

    用户侧:

    • 领取优惠券

    • 下单

    • 使用优惠券

    • 支付

    2 Service 服务

    2.1 服务结构设计

    Java+MySQL如何实现设计优惠券系统

    2.2 优惠券系统难点

    券的分布式事务,使用券的过程会出现的分布式问题分析

    如何防止超发

    如何大批量给用户发券

    如何限制券的使用条件

    如何防止用户重复领券

    3 Storage存储

    模型的设计

    优惠券系统 Coupon System 模型定义

    优惠券系统的难点

    3.1 表单设计

    券批次(券模板),coupon_batch

    指一批优惠券的抽象、模板,包含优惠券的大部分属性。

    如商家创建了一批优惠券,共1000张,使用时间为2022-11-11 00:00:00 ~ 2022-11-11 23:59:59,规定只有数码类目商品才能使用,满100减50。

    券

    发放到用户的一个实体,已与用户绑定。

    如将某批次的优惠券中的一张发送给某个用户,此时优惠券属于用户。

    规则

    优惠券的使用有规则和条件限制,比如满100减50券,需要达到门槛金额100元才能使用。

    Java+MySQL如何实现设计优惠券系统

    券批次表 coupon_batch

    Java+MySQL如何实现设计优惠券系统

    规则表 rule:

    Java+MySQL如何实现设计优惠券系统

    规则内容:

     {
       threshold: 5.01 // 使用门槛
       amount: 5 // 优惠金额
       use_range: 3 // 使用范围,0—全场,1—商家,2—类别,3—商品 
       commodity_id: 10 // 商品 id
       receive_count: 1 // 每个用户可以领取的数量
       is_mutex: true // 是否互斥,true 表示互斥,false 表示不互斥
       receive_started_at: 2020-11-1 00:08:00 // 领取开始时间
       receive_ended_at: 2020-11-6 00:08:00 // 领取结束时间
       use_started_at: 2020-11-1 00:00:00 // 使用开始时间
       use_ended_at: 2020-11-11 11:59:59 // 使用结束时间
     }

    优惠券表 coupon:

     create table t_coupon
     (
         coupon_id     int          null comment '券ID,主键',
         user_id       int          null comment '用户ID',
         batch_id      int          null comment '批次ID',
         status        int          null comment '0-未使用、1-已使用、2-已过期、3-冻结',
         order_id      varchar(255) null comment '对应订单ID',
         received_time datetime     null comment '领取时间',
         validat_time  datetime     null comment '有效日期',
         used_time     datetime     null comment '使用时间'
     );

    3.2 优惠券系统

    建券:

    1、新建规则

     INSERT INTO rule (name, type, rule_content)
     VALUES(“满减规则”, 0, '{
                             threshold: 100
                             amount: 10
                             ......
                           }');

    2、新建优惠券批次

     INSERT INTO coupon_batch (coupon_name, rule_id, total_count ) 
     VALUES(“劳斯莱斯5元代金券”, 1010, 10000);

    发券:

    Java+MySQL如何实现设计优惠券系统

    Java+MySQL如何实现设计优惠券系统

    如何给大量用户发券?

    异步发送

    触达系统
    • 短信、邮件

    • 可通过调用第三方接口的方式实现

    • 站内信

    • 通过数据库插入记录来实现

    信息表 message

     create table t_message
     (
         id         int null comment '信息ID',
         send_id    int null comment '发送者id',
         rec_id     int null comment '接受者id',
         content    vachar(255) comment '站内信内容',
         is_read    int null comment '是否已读',
         send_time  datetime comment '发送时间'
     )
     comment '信息表';

    先考虑用户量很少的情况,商家要给所有人发站内信,则先遍历用户表,再按照用户表中的所有用户依次将站内信插入到 message 表中。这样,如果有100个用户,则群发一条站内信要执行100个插入操作。

    系统用户数增加到万级

    发一条站内信,就得重复插入上万条数据。而且这上万条数据的 content 一样!假设一条站内信占100K,发一次站内信就要消耗十几M。对此,可将原来的表拆成两个表:

    信息表 message

    Java+MySQL如何实现设计优惠券系统

    信息内容表 message_content

    Java+MySQL如何实现设计优惠券系统

    发一封站内信的步骤
    • 往 message_content 插入站内信的内容

    • 在 message 表中,给所有用户插入一条记录,标识有一封站内信

    千w级用户数

    这就有【非活跃用户】的问题,假设注册用户一千万,根据二八原则,其中活跃用户占20%。若采用上面拆成两个表的情况,发一封“站内信”,得执行一千万个插入操作。可能剩下80%用户基本都不会再登录,其实只需对其中20%用户插入数据。

    信息表 message:

     create table t_message
     (
         id         int null comment '信息 ID',
         # send_id    int null comment '发送者 id', 去除该字段
         rec_id     int null comment '接受者 id',
         message_id int null comment '外键,信息内容',
         is_read    int null comment '是否已读'
     )
         comment '信息表';
     create table t_message_content
     (
         id        int          null comment '信息内容id',
         send_id    int         null comment '发送者id',
         content   varchar(255) null comment '内容',
         send_time datetime     null comment '发送时间'
     );
    用户侧操作

    登录后,首先查询 message_content 中的那些没有在 message 中有记录的数据,表示是未读的站内信。在查阅站内信的内容时,再将相关的记录插入 message。

    系统侧操作

    发站内信时:

    • 只在 message_content 插入站内信的主体内容

    • message 不插入记录

    假设商家要给 10W 用户发券:

    Java+MySQL如何实现设计优惠券系统

    有什么问题?重复消费,导致超发!

    • 运营提供满足条件的用户文件,上传到发券管理后台并选择要发送的优惠券

    • 管理服务器根据【用户ID】、【券批次ID】生成消息,发送到MQ

    • 优惠券服务器消费消息

     # 记住使用事务哦!
     INSERT INTO coupon (user_id, coupon_id,batch_id)
       VALUES(1001, 66889, 1111);
     
     UPDATE coupon_batch SET total_count = total_count - 1,
                               assign_count = assign_count + 1
                           WHERE batch_id = 1111 AND total_count > 0;
    领券

    步骤:

    • 校验优惠券余量

     SELECT total_count FROM coupon_batch 
       WHERE batch_id = 1111;
    • 新增优惠券用户表,扣减余量

     # 注意事务!
     INSERT INTO coupon (user_id, coupon_id,batch_id)
       VALUES(1001, 66889, 1111); 
     
     UPDATE coupon_batch SET total_count = total_count - 1,
                               assign_count = assign_count + 1
                           WHERE batch_id = 1111 AND total_count > 0;

    用户领券过程中,其实也会出现类似秒杀场景。秒杀场景下会有哪些问题,如何解决?

    Java+MySQL如何实现设计优惠券系统

    解决用户重复领取或多领:

    Redis 数据校验!

    • 领券前,先查缓存

     # 判断成员元素是否是集合的成员
     SISMEMBER KEY VALUE
     SISMEMBER batch_id:1111:user_id 1001
    • 领券

    • 领券后,更新缓存

     # 将一或多个成员元素加入到集合中,已经存在于集合的成员元素将被忽略 
     SADD KEY VALUE1......VALUEN
     SADD batch_id:1111:user_id 1001
    用券

    何时校验优惠券使用规则?

    • 确认订单(√)

    • 提交订单

    • 立即付款

    确认订单页,对优惠券进行校验:

    • 判断是否过期

    • 判断适用范围

    • 判断是否达到门槛

    • 判断是否互斥

    返回可用券

    Java+MySQL如何实现设计优惠券系统

     SELECT batch_id FROM coupon WHERE user_id = 1001 AND status = 0;
     
     SELECT rule_id FROM coupon_batch WHERE batch_id = 1111;
     
     SELECT name, type, rule_content FROM rule WHERE rule_id = 1010;
    选择可用券,并返回结果

    Java+MySQL如何实现设计优惠券系统

    同时操作多个服务,如何保证一致性?

    Java+MySQL如何实现设计优惠券系统

    表设计

    优惠券操作记录表 Coupon_opt_record

     create table t_coupon_opt_record
     (
         user_id     int      null comment '用户id',
         coupon_id   int      null comment '优惠券id',
         operating   int      null comment '操作,0-锁定、1-核销、2-解锁',
         operated_at datetime null comment '操作时间'
     );

    TCC,Try-Confirm-Cancel,目前分布式事务主流解决方案。

    阶段一:Try

    对资源进行冻结,预留业务资源

    创建订单时,将优惠券状态改为 “冻结”

    阶段二:Confirm

    确认执行业务操作,做真正提交,将第一步Try中冻结的资源,真正扣减

    订单支付成功,将优惠券状态改为 “已使用”

    阶段三:Cancel

    取消执行业务操作,取消Try阶段预留的业务资源

    支付失败/超时或订单关闭情况,将优惠券状态改为 “未使用”

    Java+MySQL如何实现设计优惠券系统

    Scale扩展

    快过期券提醒:

    定时扫券表:

    缺点:扫描数据量太大,随着历史数据越来越多,会影响线上主业务,最终导致慢SQL。

    延时消息:

    缺点:有些券的有效时间太长了(30天)以上,有可能造成大量 MQ 积压

    新增通知表:

    优点:扫描的数据量小,效率高。删除无用的已通知的数据记录

    通知信息表(notify_msg)设计
     create table t_notify_msg
     (
         id          bigint auto_increment comment '自增主键',
         coupon_id   bigint       null comment '券id',
         user_id     bigint       null comment '用户id',
         notify_day  varchar(255) null comment '需要执行通知的日期',
         notify_type int          null comment '通知类型,1-过期提醒',
         notif_time  timestamp    null comment '通知的时间,在该时间戳所在天内通知',
         status      int          null comment '通知状态,0-初始状态、1-成功、2-失败',
         constraint t_notify_msg_id_uindex
             unique (id)
     );
     alter table t_notify_msg
         add primary key (id);

    过期券提醒:

    • 在创建优惠券的时候就将需要提醒的记录插入提醒表中notify_msg

    • 把用户ID+批次ID+通知日期作为唯一索引,防止同一个批次有重复的记录通知,保证每天只会被通知一次

    • 建立notify_time,通知时间索引,每日的通知扫描通过该索引列查询,通过索引列来提高查询效率

    • 通知完成后该表中的数据变失去了意义,通过定时任务将该数据删除

    数据库层面优化 - 索引

    Java+MySQL如何实现设计优惠券系统

    Java+MySQL如何实现设计优惠券系统

    发券接口,限流保护

    前端限流:

    点击一次后,按钮短时间内置灰

    Java+MySQL如何实现设计优惠券系统

    后端限流:

    部分请求直接跳转到【繁忙页】

    本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
    作者最新文章
    编程开发 Java MySQL
    相关文章 更多
    精品专题 更多
    装机必备

    正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

    Windows

    正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

    PDF教程

    正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

    macOS软件

    正软商城macOS软件专区,精选适用于Mac电脑的办公、设计、影音、效率、开发和系统工具,提供软件功能介绍、macOS兼容版本、正版授权及购买下载服务。

    IOS软件

    正软商城iOS软件专区,精选适用于iPhone和iPad的办公、学习、影音、设计、效率及AI应用,提供功能介绍、适用设备、系统要求和正版获取方式等信息。

    AI

    正软商城AI软件专区,汇集AI写作、AI绘画、AI视频、AI办公、AI编程、AI翻译、智能客服和数据分析等人工智能工具,提供功能介绍、适用平台、收费方式及正版购买信息。

    Mac软件 更多
    Aperty macOS版
    Aperty macOS版

    Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

    火山引擎 网页版
    火山引擎 网页版

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    立刻MV 网页版
    立刻MV 网页版

    立刻MV 面向音乐人、内容创作者和品牌团队,帮助用户低成本完成歌曲 MV、歌词视频、AI 分镜、图生视频与最终合成。

    蛙蛙写作 网页版
    蛙蛙写作 网页版

    蛙蛙写作 AI 创作工具,覆盖小说、剧本、文案,一键生成文稿,打通文字转视频全流程,高效解决创作难题。

    讯飞智作 网页版
    讯飞智作 网页版

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    超级简历WonderCV 网页版
    超级简历WonderCV 网页版

    超级简历WonderCV是面向应届生和AI小白的智能求职平台,覆盖简历、面试与职业规划。

    音述AI 网页版
    音述AI 网页版

    音述AI,是一个以“用声音述说故事”为核心的 AI 音乐创作与声音分享社区。

    AionClaw macOS版
    AionClaw macOS版

    AionClaw 是可在桌面端运行的任务型 AI 助手,通过数字专家与技能市场组合办公、创作、数据和开发能力。

    Loomy macOS版
    Loomy macOS版

    Loomy 是科大讯飞推出的桌面 AI 助手,可通过对话、任务与工作目录协助处理办公、内容创作和资料整理。

    AirBuddy 3 macOS版
    AirBuddy 3 macOS版

    AirBuddy 3 是面向 macOS 的蓝牙外设增强工具,可集中查看 AirPods、Beats 与苹果设备电量,提供快速连接、播放控制、电量提醒、桌面小组件和多台 Mac 外设接力等功能。

    AirServer macOS版
    AirServer macOS版

    AirServer macOS版可把 Mac 转换为无线投屏接收端,通过 AirPlay 或 Google Cast 接收手机、平板和电脑画面,并支持多设备同时连接、高清镜像及会话录制,适合家庭娱乐、课堂教学、会议演示和应用展示。

    AnyDesk macOS版
    AnyDesk macOS版

    AnyDesk macOS版是一款适用于远程办公、设备维护和客户支持的远程桌面工具,可连接并操作异地计算机,支持文件传输、无人值守访问、会话权限控制及跨平台协作。

    WINDOWS 更多
    讯飞绘文 网页版
    讯飞绘文 网页版

    讯飞绘文网页版是科大讯飞推出的AI图文创作与内容运营工具,覆盖热点选题、文章生成、稿件校对、智能配图、排版发布和数据复盘等环节,适合自媒体创作者及内容团队在线使用。

    Maya(Autodesk Maya) Windows版
    Maya(Autodesk Maya) Windows版

    Autodesk Maya 是面向影视、电视、动画和游戏行业的专业三维制作软件,集多边形与 NURBS 建模、角色绑定、关键帧和动作捕捉动画、Bifrost 特效模拟、材质开发及 Arnold 渲染于一体,

    Aperty Windows版
    Aperty Windows版

    Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

    火山引擎 网页版
    火山引擎 网页版

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    立刻MV 网页版
    立刻MV 网页版

    立刻MV 面向音乐人、内容创作者和品牌团队,帮助用户低成本完成歌曲 MV、歌词视频、AI 分镜、图生视频与最终合成。

    蛙蛙写作 网页版
    蛙蛙写作 网页版

    蛙蛙写作 AI 创作工具,覆盖小说、剧本、文案,一键生成文稿,打通文字转视频全流程,高效解决创作难题。

    讯飞智作 网页版
    讯飞智作 网页版

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    超级简历WonderCV 网页版
    超级简历WonderCV 网页版

    超级简历WonderCV是面向应届生和AI小白的智能求职平台,覆盖简历、面试与职业规划。

    音述AI 网页版
    音述AI 网页版

    音述AI,是一个以“用声音述说故事”为核心的 AI 音乐创作与声音分享社区。

    AionClaw Windows版
    AionClaw Windows版

    AionClaw 是可在桌面端运行的任务型 AI 助手,通过数字专家与技能市场组合办公、创作、数据和开发能力。

    Loomy Windows版
    Loomy Windows版

    Loomy 是科大讯飞推出的桌面 AI 助手,可通过对话、任务与工作目录协助处理办公、内容创作和资料整理。

    AirServer Windows版
    AirServer Windows版

    AirServer Windows版可把电脑变成AirPlay、Google Cast和Miracast无线投屏接收端,适合会议演示、课堂教学及家庭大屏分享。发送设备通常无需另装客户端,并可同时接收和智能排列多个镜像会话。