共计 3543 个字符,预计需要花费 9 分钟才能阅读完成。
集体博客:无奈何杨(wnhyang)
集体语雀:wnhyang
共享语雀:在线常识共享
Github:wnhyang – Overview
申明
本篇文章纯正抛砖引玉!
需要阐明
单刀直入,业务背景间接跳过。
类比支付宝会员积分,支付宝 APP- 我的 - 支付宝会员。
支付宝会员 -XXX 积分 - 积分规定,能够看到具体的积分规定,本篇文章类比于此积分业务场景,做简略的设计。
积分阐明
积分不具备货币或现金价值,不可兑现,不可转让。用户能够通过领取、账户服务、金融理财和积分处分流动等形式来获取积分。
积分能够兑换各类权利、参加各种积分流动等,具体以权利兑换及流动页面展现为准。
积分支付规定
积分发放后,用户可返回“我的”-“支付宝会员”,点击支付积分球,或者在领取胜利页面、服务音讯揭示、账单点击支付,积分方可到账。积分自产生之时起,支付有效期 7 天(168 小时),逾期不领则作废,不予补发。
积分获取形式
1、领取
2、账户服务
3、金融理财
4、扫一扫
5、等
积分有效期
用户取得的积分有效期为自取得当月起的 12 个天然月,有效期内未应用的积分到期将主动清零,不予补发。
舒适提醒:
1、用户日常应用的积分,将优先应用行将过期的积分。
2、每月,用户可在“我的”-“支付宝会员”-“收支 / 订单 / 规定”页查看当月月底行将过期的积分。
3、已应用的积分若产生退还,积分有效期不变,仍以该笔积分原获取工夫计算有效期。
积分权利兑换
积分能够兑换各类权利、参加各种积分流动等,具体以权利兑换及流动页面展现为准。
积分与成长体系
略
需要剖析
因为下面简直都是粘贴于支付宝对外展现的积分规定,而这篇文章波及范畴并没有那么广,所以这里要申明一下需要范畴。
积分获取形式
领取、账户服务、金融理财、扫一扫等。
同步计划:这个就波及到 AOP
的思维,换言之“狭义AOP
”。这个不是单个零碎能实现的,须要多方零碎独特确认,而本零碎须要提供牢靠的积分累计接口。如:用户领取实现后应该累计积分的,通过什么形式与积分零碎交互减少积分呢?这样的接口如何设计呢?除了用户惟一标识、积分值、交易工夫、交易类型还有什么必要字段呢?需不需要重试?如何做幂等?分布式事务如何思考?等等,还有很多因素要思考。
异步计划:有时咱们对于积分累积的时效性并不高,就能够思考异步计划。异步无非就是音讯队列类的异步工作,或是有数据团队来做数据的剖析解决。异步工作形式不论是音讯队列或是事件驱动都大略可行,当然这两头也有很多中央要留神。数据分析解决有点像是定时工作,形容可能不太精确,就是通过剖析用户理论数据来具体分析解决,如:每天 2 点,数据团队有多个数据模型针对不同的数据表(账户贷款、理财等等)对用户前一天所有交易进行剖析,计算积分而后累计前一天产生的积分。
对于积分获取形式,本次就探讨到这了。其实下面简略剖析曾经蕴含了很多零碎设计的必要思考条件了,而且很多都能够类比的,比方积分累计不就是相似购物产生订单,或是记录操作日志吗。有很多相似之处的,能够类比思考一下。
积分支付规定
从前面积分支付规定能够确定,积分支付波及音讯告诉和过期。
音讯告诉必定是成体系的,可参考其余音讯类零碎设计。过期能够参考上面的积分过期。
积分有效期
这个是本篇文章中我想要突出的重点。积分产生、积分兑换、积分过期还是须要好好思考一下的,如若不然,甚至不单单是产生零碎 bug,甚至会有业务 bug,这是难以承受的。
既然下面需要阐明了积分有效期是 12 个天然月,那么就能够思考设计一张按月存储的表来存储积分。
如 5.1-5.31 的产生的积分存储为一条可用积分记录,过期工夫为 5.31 23:59:59,总积分值为最近 12 个月积分之和。
用户 ID | 累计积分 | 可用积分值 | 过期工夫 |
---|---|---|---|
1 | 300 | 300 | 5.31 23:59:59 |
1 | 500 | 500 | 6.30 23:59:59 |
1 | 800 | 700 | 7.31 23:59:59 |
1 | 500 | 400 | 8.31 23:59:59 |
1 | 300 | 200 | 9.30 23:59:59 |
1 | 300 | 100 | 10.31 23:59:59 |
1 | 500 | 500 | 11.30 23:59:59 |
1 | 600 | 600 | 12.31 23:59:59 |
可能有人在接到积分过期需要时就思考到定时工作扫表的形式,尽管可能也是没问题的,但细节其实挺多的,这里就不做过多探讨了。
积分权利兑换
用户日常应用的积分,将优先应用行将过期的积分。针对于下面的月度积分表,在积分兑奖时从最早的未过期的月开始计算扣减积分。
设计方案
数据表
简略设计如下,月度积分关联多条积分明细记录,这样能够不便查问月度积分获取和耗费明细。
月度积分
- 月度积分 id
- 用户 id
- 年月(参考 2024-01 之类的)
- 累计积分
- 可用积分
- 过期工夫
积分明细
- 月度积分 id
- 明细 id
- 用户 id
- 积分值
- 类型(如:耗费,获取等)
- 操作
- 工夫
兑奖明细
- 兑奖明细 id
- 用户 id
- 奖品耗费积分
- 奖品名称
- 工夫
流程
积分获取
积分由用户操作生成,同时存储于月度积分表和积分明细表。
积分兑奖
其余
除了下面这些,还有
- 总积分查问,最近 12 个月的月度积分 - 可用积分之和
- 积分明细查问,倒序查问月度积分和月度积分明细
- 积分兑奖明细,等,简略的就不多提了
参考代码
积分兑奖
import java.time.LocalDate;
import java.util.*;
class PointRecord {
private int points;
private LocalDate expirationDate;
// 构造方法、getters 和 setters 省略
public boolean canConsume(int requiredPoints) {return this.points >= requiredPoints;}
public void consume(int requiredPoints) {if (canConsume(requiredPoints)) {this.points -= requiredPoints;} else {throw new IllegalArgumentException("Insufficient points to consume.");
}
}
}
public class PointService {public void redeemReward(User user, int rewardPointCost) {List<PointRecord> sortedRecords = getSortedUnexpiredPointRecords(user);
for (PointRecord record : sortedRecords) {if (record.canConsume(rewardPointCost)) {record.consume(rewardPointCost);
rewardPointCost = 0; // 曾经满足耗费条件,跳出循环
break;
} else {rewardPointCost -= record.getPoints();
record.setPoints(0); // 耗费完该记录所有积分
}
}
// 更新数据库中的积分明细表
updateDatabase(sortedRecords);
// 如果 rewardPointCost 依然大于 0,阐明积分有余,须要在此处解决异常情况
if (rewardPointCost > 0) {throw new InsufficientPointsException("Not enough valid points to redeem the reward.");
}
}
// 省略了获取用户未过期且已排序的积分记录列表的办法(getSortedUnexpiredPointRecords)以及更新数据库的办法(updateDatabase)}
在这个示例中,PointRecord
类代表单个积分记录,蕴含积分值和过期日期。PointService
中的 redeemReward
办法首先获取用户的所有未过期且按过期工夫排序的积分记录,而后遍历这些记录,优先扣除最早到期的积分。当所需兑换积分数量减为 0 时进行扣除。如果最初仍有残余的兑换积分需要,则抛出积分有余的异样。
理论利用中,你须要依据数据库查问后果填充 sortedRecords
列表,并在扣除积分后更新数据库以反映新的积分状态。
小结
其实还有很多内容没有细究,这部分就留给认真看的你们了。哈哈哈😂
积分弥补、退货等场景,分布式事务如何思考,留给你们了。
最初的最初,其实在零碎设计之前,需要剖析是重中之重,肯定要讲需要看透,尤其是多思考一些场景。
上面有一张对于积分过期和兑奖的场景草图,是我在思考时画的,不想多解释了,本人看吧😁
最初四个字:跳出工夫。
写在最初
拙作艰苦,字句心血,望诸君垂青,多予反对,不胜感激。
集体博客:无奈何杨(wnhyang)
集体语雀:wnhyang
共享语雀:在线常识共享
Github:wnhyang – Overview