Skip to main content

04小节:开发用户优惠券分发功能(一)

作者:程序员马丁

在线博客:https://nageoffer.com

note

热门项目实战社群,收获国内众多知名公司面试青睐,近千名同学面试成功!助力你在校招或社招上拿个offer。

开发用户优惠券分发功能(一),元数据信息:

©版权所有 - 拿个offer-开源&项目实战星球专属学习项目,依据《中华人民共和国著作权法实施条例》《知识星球产权保护》,严禁未经本项目原作者明确书面授权擅自分享至 GitHub、Gitee 等任何开放平台。违者将面临法律追究。


内容摘要:通过基础的优惠券分发逻辑,实现了从 Excel 解析到用户领取优惠券的整个流程。虽然当前版本的性能较低,但将在 v2 版本中引入高性能的优化方案。

课程目录如下所示:

  • 业务背景
  • 数据库表设计
  • Git 分支
  • 优惠券分发逻辑
  • 执行优惠券分发
  • 常见问题答疑

业务背景

在执行消息消费时,应该首先读取 Excel 数据,然后按照用户分发流程进行操作。具体的分发逻辑如下:

  1. 检查优惠券模板的状态是否正常;
  2. 验证优惠券模板的库存余量是否充足;
  3. 确认用户是否已领取相同的优惠券,若已领取则不再分发;
  4. 记录用户的领券信息。

注意,如果前面商家后管服务添加了 vm 参数,分发服务记得也加上,要不然消费不到对应消息队列消息。

Git 分支

20240829_dev_coupon-distribute-v1_easyexcel-cache_ding.ma

数据库表设计

1. 用户优惠券表设计

用户优惠券表设计如下:

CREATE TABLE `t_user_coupon_0` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`user_id` bigint(20) DEFAULT NULL COMMENT '用户ID',
`coupon_template_id` bigint(20) DEFAULT NULL COMMENT '优惠券模板ID',
`receive_time` datetime DEFAULT NULL COMMENT '领取时间',
`receive_count` int(3) DEFAULT NULL COMMENT '领取次数',
`valid_start_time` datetime DEFAULT NULL COMMENT '有效期开始时间',
`valid_end_time` datetime DEFAULT NULL COMMENT '有效期结束时间',
`use_time` datetime DEFAULT NULL COMMENT '使用时间',
`source` tinyint(1) DEFAULT NULL COMMENT '券来源 0:领券中心 1:平台发放 2:店铺领取',
`status` tinyint(1) DEFAULT NULL COMMENT '状态 0:未使用 1:锁定 2:已使用 3:已过期 4:已撤回',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_time` datetime DEFAULT NULL COMMENT '修改时间',
`del_flag` tinyint(1) DEFAULT NULL COMMENT '删除标识 0:未删除 1:已删除',
PRIMARY KEY (`id`),
UNIQUE KEY `idx_user_id_coupon_template_receive_count` (`user_id`,`coupon_template_id`,`receive_count`) USING BTREE,
KEY `idx_user_id` (`user_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1815640588360376337 DEFAULT CHARSET=utf8mb4 COMMENT='用户优惠券表';

其中有一个字段用于记录用户领取优惠券的次数,以标识这是用户第几次领取。通过设置唯一索引来限制用户的领取次数。

2. 用户优惠券分库分表设计

由于用户优惠券记录的数据量非常大,需要对该表进行分库分表处理。不同于优惠券模板数据可以推衍估算,我们将直接分为 32 张表,以确保单表数据量保持在亿级以下,从而避免性能压力。

考虑到大量用户频繁领取优惠券导致写入操作较为频繁,因此也需要进行分库。分片策略与优惠券模板相同,采用 Hash 方式进行分库分表。

# 数据源集合
dataSources:
# 自定义数据源名称,可以是 ds_0 也可以叫 datasource_0 都可以
ds_0:
dataSourceClassName: com.zaxxer.hikari.HikariDataSource
driverClassName: com.mysql.cj.jdbc.Driver
jdbcUrl: jdbc:mysql://127.0.0.1:3306/one_coupon_rebuild_0?useUnicode=true&characterEncoding=UTF-8&rewriteBatchedStatements=true&allowMultiQueries=true&serverTimezone=Asia/Shanghai
username: root
password: root
ds_1:
dataSourceClassName: com.zaxxer.hikari.HikariDataSource
driverClassName: com.mysql.cj.jdbc.Driver
jdbcUrl: jdbc:mysql://127.0.0.1:3306/one_coupon_rebuild_1?useUnicode=true&characterEncoding=UTF-8&rewriteBatchedStatements=true&allowMultiQueries=true&serverTimezone=Asia/Shanghai
username: root
password: root

rules:
- !SHARDING
tables: # 需要分片的数据库表集合
t_coupon_template: # 优惠券模板表
# 真实存在数据库中的物理表
actualDataNodes: ds_${0..1}.t_coupon_template_${0..15}
databaseStrategy: # 分库策略
standard: # 单分片键分库
shardingColumn: shop_number # 分片键
shardingAlgorithmName: coupon_template_database_mod # 库分片算法名称,对应 rules[0].shardingAlgorithms
tableStrategy: # 分表策略
standard: # 单分片键分表
shardingColumn: shop_number # 分片键
shardingAlgorithmName: coupon_template_table_mod # 表分片算法名称,对应 rules[0].shardingAlgorithms
t_user_coupon:
actualDataNodes: ds_${0..1}.t_user_coupon_${0..31}
databaseStrategy:
standard:
shardingColumn: user_id
shardingAlgorithmName: user_coupon_database_mod
tableStrategy:
standard:
shardingColumn: user_id
shardingAlgorithmName: user_coupon_table_mod
shardingAlgorithms: # 分片算法定义集合
coupon_template_database_mod: # 优惠券分库算法定义
type: CLASS_BASED # 根据自定义库分片算法类进行分片
props: # 分片相关属性
# 自定义库分片算法Class
algorithmClassName: com.nageoffer.onecoupon.distribution.dao.sharding.DBHashModShardingAlgorithm
sharding-count: 16 # 分片总数量
strategy: standard # 分片类型,单字段分片
coupon_template_table_mod: # 优惠券分表算法定义
type: CLASS_BASED # 根据自定义库分片算法类进行分片
props: # 分片相关属性
# 自定义表分片算法Class
algorithmClassName: com.nageoffer.onecoupon.distribution.dao.sharding.TableHashModShardingAlgorithm
strategy: standard # 分片类型,单字段分片
user_coupon_database_mod:
type: CLASS_BASED
props:
algorithmClassName: com.nageoffer.onecoupon.distribution.dao.sharding.DBHashModShardingAlgorithm
sharding-count: 32
strategy: standard
user_coupon_table_mod:
type: CLASS_BASED
props:
algorithmClassName: com.nageoffer.onecoupon.distribution.dao.sharding.TableHashModShardingAlgorithm
strategy: standard

props:
# 配置 ShardingSphere 默认打印 SQL 执行语句
sql-show: true

解锁付费内容,👉 戳