红包系统说明文档
简介
某商城想运营一个消费红包赠礼的活动引流,需要构建一个功能相对完善的活动平台。
该平台有五个功能:
- 红包上架功能
- 红包活动剩余领取额度的查询
- 客户一键领取红包
- 客户消费使用红包
- 客户领取红包明细的查询
系统流程图
需求说明:
- 本次只发行一款红包,设有总额上限,每成功领取一次,总额即时减少。在一个活动期间,所有客户领取的红包总值不超过预设上限。
- 每次客户领取的红包金额将随机落在 0.01元 至 1元,每个客户在每个活动中只能领取10次红包。每次领取都会生成详细的领取记录,并同步减少红包活动的金额。
- 客户消费支付时一次最多可以使用5个红包。使用时,活动系统需要检查红包的状态并即时更新,以防止重复使用。
- 红包活动的领取明细查询是整个活动下所有客户的红包领取明细,由于领取明细条数较多,需要进行多包续传查询,即使用上次请求标识结尾位置的键值,作为下次查询的起始键值,不返回续传键值视为查询结束,不需要再次续传查询。多次通讯的总返回数据为全量符合条件的数据。
- 红包活动结束后,红包活动初始的总额度=剩余可领取的红包额度+客户已领取红包明细汇总。
红包系统表设计思路
我们从简设计,从红包系统流程来看,设计的表能覆盖整个流程即可。针对红包系统来说,我们需要一个活动表,客户红包记录表,红包领取明细表。所以总共三个表就够了。(PS:因为系统足够简单,所以不需要分解的很细)
红包上架活动表:
-- 创建活动上架红包表
CREATE TABLE `activity_red_packet` (
`id` INT NOT NULL AUTO_INCREMENT COMMENT '主键',
`activity_id` VARCHAR ( 50 ) NOT NULL COMMENT '活动id',
`total_pool_amount` DECIMAL ( 10, 2 ) DEFAULT NULL COMMENT '活动奖池总金额',
`pool_left_amount` DECIMAL ( 10, 2 ) DEFAULT NULL COMMENT '奖池剩余金额',
`create_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY ( `id` ),
UNIQUE KEY `activity_id` ( `activity_id` )
) ENGINE = INNODB AUTO_INCREMENT = 92 DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = COMPACT;
客户红包记录表:
-- 客户红包记录表
CREATE TABLE `user_red_packet` (
`id` INT NOT NULL AUTO_INCREMENT COMMENT '主键',
`user_id` VARCHAR ( 50 ) DEFAULT NULL COMMENT '用户id',
`activity_id` VARCHAR ( 50 ) DEFAULT NULL COMMENT '活动id',
`number` INT DEFAULT NULL COMMENT '红包个数',
`create_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY ( `id` )
) ENGINE = INNODB AUTO_INCREMENT = 8867 DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = COMPACT;
客户领取红包明细表:
-- 创建用户领取红包明细表
CREATE TABLE `user_red_packet_detail` (
`id` INT NOT NULL AUTO_INCREMENT COMMENT '主键',
`user_id` VARCHAR ( 50 ) DEFAULT NULL COMMENT '用户id',
`activity_id` VARCHAR ( 20 ) CHARACTER
SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '活动id',
`red_packet_id` VARCHAR ( 50 ) DEFAULT NULL COMMENT '红包id',
`received_amount` DECIMAL ( 10, 2 ) DEFAULT NULL COMMENT '用户领取红包金额',
`use_status` INT DEFAULT NULL COMMENT '使用状态。默认是0,未使用',
`create_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY ( `id` ),
UNIQUE KEY `unique_red_packet_activity` ( `red_packet_id`, `activity_id` ),
KEY `use_id` ( `user_id` ) USING BTREE
) ENGINE = INNODB AUTO_INCREMENT = 11505 DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = COMPACT;
活动上架红包功能
请求报文:
{
"activityId":"test",
"amount":1000.12,
"leftamount:":1000.12
}
响应报文:
{
"code": 200,
"data": {
"insertNum": 1
},
"message": ""
}
效果图:
红包活动剩余领取额度的查询功能
请求报文:
http://localhost:8088/activity/query-amount-left/1
响应报文:
{
"code": 200,
"data": {
"amountLeft": 1000.12
},
"message": ""
}
客户一键领取红包功能
请求报文:这里可以自己该代码,然后上传用户id
,然后自己指定一个redPacketId
即可。但是该功能我用了压测,所以就只是上传了活动id
。
{
"activityId":"test"
}
响应报文:(压测情况下无)
{
"code": 200,
"data": {
"receiveRedPacket": 0.12
},
"message": ""
}
效果图:
假如说,你压测完后,你的奖池还有余额,那么可以进行再压测,毕竟我进行了全局异常的捕获,所以不会抛出异常的;当然也不会出现超卖情况。
客户消费使用红包功能
请求报文:这里的请求报文你就看你的数据库的数据进行自己改造即可。
{
"userId":"user_343",
"redPacketList":["redPacket_6573","redPacket_6589","redPacket_5914"]
}
响应报文:
{
"code": 200,
"data": {
"useFlag": "SUCCESS"
},
"message": ""
}
客户领取红包明细的查询功能
请求报文:其中 key
就是 id
,0 就是代表从零开始进行传值,如果是一个具体的值就从这个具体的值 + 1进行传值,如果是continuesFlag
是 false
证明是最后一页。
{
"activityId":"test",
"PageSize":5,
"key":0,
"continuesFlag":true
}
响应报文:
{
"code": 200,
"data": {
"redPacketDetailPageQryDTO": {
"activityId": "test",
"key": 0,
"continuesFlag": true,
"pageSize": 5
},
"RedPacketDetailPageRsp": [
{
"activityId": "redPacket_0",
"userId": "user_82",
"orderType": 1,
"redPacketId": "test",
"amount": 1,
"id": 1
},
{
"activityId": "redPacket_3",
"userId": "user_252",
"orderType": 0,
"redPacketId": "test",
"amount": 0.64,
"id": 2
},
{
"activityId": "redPacket_2",
"userId": "user_402",
"orderType": 0,
"redPacketId": "test",
"amount": 0.87,
"id": 3
},
{
"activityId": "redPacket_1",
"userId": "user_179",
"orderType": 0,
"redPacketId": "test",
"amount": 0.68,
"id": 4
},
{
"activityId": "redPacket_5",
"userId": "user_7",
"orderType": 0,
"redPacketId": "test",
"amount": 0.13,
"id": 5
}
]
},
"message": ""
}
全局异常捕获图
AOP 生效
课外之音
- 这虽然是一个
toy
项目,但是麻雀虽小,五脏俱全。项目涉及到的技术栈包括:Java
、MySQL
、SpringBoot
、Mybatis
。虽然简单,但是内容却足够丰富:Java8
编程、异常使用、AOP
切面编程、MySQL
索引、行级锁、事务使用、续传查询、如何解决“超卖”问题、流量分散思想、如何保证数据的一致性、核心功能的性能压测等等。 - 但,这毕竟只是一个 toy,其功能还是很不完善的,在代码方面:缺少了抽象,比如说可以使用泛型,使用设计模式来进行改造。还有很多的不完善的地方,大家拉取代码后自行去发挥你们的想象力来对这个项目添加你们自己的想法吧!
- 本人觉得该项目很适合没有合适的项目练手的同学,这个项目代码量不多,核心代码量应该只是500行左右。但是里面蕴含的思想正是你们面试中的所谓的“亮点”,可以作为简历的第一个项目写进去的。
- 原本我自己也记录了一些写代码的时候踩的坑,但是想想还是算了,这些问题无一例外都可以通过
GPT
或者百度搜到答案,那么这些坑无非就是耗点时间罢了。所以各位,把代码拉下来好好去改造吧(拉master
代码即可,其他的可能不全,或者后期有改造没有同步),改完了就是你们简历的东西啦!PS:大家不需要往我的项目提交issue
,我大概率不会改(狗头)。
Java 实用知识 文章被收录于专栏
该栏目主要是分享一些实用的编码技巧、编程知识以及个人认为有大用的八股知识。