微信读书的书币逻辑是怎样做到独立过期的呢?

214 天前
 zero47
有点好奇微信读书的书币系统是怎么实现的。微信读书每天阅读可以获得书币奖励,基本每天能领取 1 到 2 个,而这些领取的书币都有独立的有效期,貌似一个月。如果每笔领取记录都单独过期,意思是一个月可能会有 30 多笔记录。假设每笔都是 1 个书币,难道买本 30 块的电子书要更新 30 条记录?每次查看余额都要 sum 一下记录?
5708 次点击
所在节点    程序员
46 条回复
zero47
214 天前
@caotian 我也觉得短期过期太复杂了,话费信用卡的积分都一年清算一次
qeqv
214 天前
感觉最简单的方法就是你正文提到的了,别的逻辑都很复杂。
1. 购买时更新 30 条记录也没什么
2. 总额可以做缓存,余额变动时更新
3. 1 个 2 块书币奖励可以设置成两条 1 书币记录
futuretech6
214 天前
感觉是类似 NFT 的实现,每个 token 有自己的 id 和过期时间,然后整体也会维护一个 token 数量信息
runzekk
214 天前
sum 也没什么问题,冗余存也没什么问题,量不大,没有大事物都不是问题
444571840
214 天前
如果要实现的话要挺容易的,数据库一个字段就能解决。
记录的时候 [获得书币 A ,到期时间戳 1 。获得书币 B ,到期时间戳 2 。xxx],每次要写入新数据的时候,先判断是否有已经到期的书币,删除了,再在字段后面添加(新活动书币,新到期时间戳)即可。
客户端每次要展示的时候,根据当前时间戳把数据库未到期的 sum 一遍就好了。
其他查历史的话看 log 就好。
mrgeneral
214 天前
总和可以是单独的数据,过期是定时任务就能解决,流水信息可以定期归档,实际数据量不大。
janus77
214 天前
领取时一条一条更新
使用时只需要更新一下总数字就行了,只有一次啊
hanbin
214 天前
两个表:

CREATE TABLE PointsRecord (
id INT AUTO_INCREMENT PRIMARY KEY COMMENT '自增 ID',
user_id INT NOT NULL COMMENT '用户 ID',
points_amount INT NOT NULL COMMENT '积分数量',
receive_time TIMESTAMP NOT NULL COMMENT '领取时间',
expiration_time TIMESTAMP NOT NULL COMMENT '过期时间',
status VARCHAR(20) NOT NULL COMMENT '状态',
receive_source VARCHAR(50) NOT NULL COMMENT '领取来源',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '记录时间',
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间'
) COMMENT '积分领取记录表';

CREATE TABLE PointsWallet (
id INT AUTO_INCREMENT PRIMARY KEY COMMENT '积分钱包 ID',
user_id INT NOT NULL COMMENT '用户 ID',
points_balance INT NOT NULL DEFAULT 0 COMMENT '积分余额',
total_points INT NOT NULL DEFAULT 0 COMMENT '积分总额',
used_points INT NOT NULL DEFAULT 0 COMMENT '已用积分总额',
expired_points INT NOT NULL DEFAULT 0 COMMENT '已过期积分总额',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间'
) COMMENT '积分钱包表';

领取积分:

PointsRecord 入库一条记录,PointsWallet 更新 total_points & points_balance ,事务处理

过期积分:

PointsRecord 更新一条数据,PointsWallet 更新 total_points & points_balance & expired_points ,事务处理

积分消费:

PointsWallet 更新 used_points & points_balance

过期积分用脚本处理

积分消费时判断余额够就允许消费。
hanbin
214 天前
@hanbin 将积分领取和积分消费解耦,消费时不关心积分的有效期属性,积分的有效属性也不关心消费的具体场景,只关心额度变化即可。
MoYi123
214 天前
@zero47 这点数量算什么? 随便一个网络游戏, 一次就加载几千个装备物品, 还不是大把人能做?
pkoukk
214 天前
两个表,一个当前的 sum ,一个 detail
通过事件系统,detial 表的变动通知到 sum ,sum 改余额就完事了
而且一天才一两条,不用事件系统,搞定时任务扫都绰绰有余
NizumaEiji
214 天前
流水过期
handpr
214 天前
类似物流的.出入库. 入库明细-》 spu,sku,批次,效期次,入库数量
ZnductR0MjHvjRQ3
214 天前
@zero47 有没有一种可能 实际上都是 1
ZnductR0MjHvjRQ3
214 天前
@deltadawn 有道理
kaedea
214 天前
你在查找的是不是:数据库
somebody1
214 天前
@deltadawn
补充思路,可以是 32 个 0-9 ,a-z ,这样每天获取到的就可以非常多了,只需要计算一个 32 的字符串,就可以算出来了。

但是缺点有很明显,微信读书可以做到分钟级别的失效,这个就做不到了。
yanliu
214 天前
以我浅见,这种余额类的大都是事件溯源的,即你看到的余额不是简单的存储了一个数字,而是由交易记录实时计算出来的,然后定期合并一个快照,减少计算量,那么就可以在交易记录上打标记来实现过期。这是最常用,也是最安全的做法。当然,也有简单的方案,比如将这类会过期的书币存入 redis 的 zset 中,然后将过期时间戳作为 score ,就可以使用 ZRANGEBYSCORE 之类的命令来返回当前时间和过期时间之间的数据,求和就行了。
yanliu
214 天前
@yanliu 一切都要看业务。如果你有 15L 说的那样情况,或者其它情况,那么事件溯源,就是这一类问题目前的唯一解,同时兼顾了安全性和灵活性,并且快照设置合适的话,并发性也不差。
cellar
214 天前
又不是严格的金融系统。。要么弄个 job ,过期的全删了,要么 where 条件永远带个时间条件就是了。。
资源有的是的话弄个 redis...

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1033839

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX