找回密码
 立即注册
搜索
查看: 1790|回复: 15

[网络] 网站后端代码咨询(PHP)

[复制链接]
发表于 2021-11-22 20:56 | 显示全部楼层 |阅读模式
非科班出生的非程序员。兴趣使然地写了个匿名版,现在想加个功能。


环境:PHP后端,或者说Laravel框架。

一个用户间的小游戏,
A用户发帖发起调整,预扣N个代币。
如果B用户应战,则投骰子定胜负。
A胜利获得2N个代币,B胜利获得N个代币。

问题出在:如果10分钟无人应战则A用户的预扣代币退回。

这个“10分钟后执行”应该如何实现好?
用任务调度,每分钟检查一次数据库,把超时的小游戏强制结束?
但这样的话会有时间差,而且每分钟都轮询一次感觉不优雅……


回复

使用道具 举报

     
发表于 2021-11-22 21:05 来自手机 | 显示全部楼层
搜 Redis 定时任务

—— 来自 Xiaomi Mi 10, Android 11上的 S1Next-鹅版 v2.4.3
回复

使用道具 举报

     
发表于 2021-11-22 21:11 | 显示全部楼层
A预先扣除的币不要动主数据库的余额,写进redis然后设置10分钟过期。

有B迎战时检查redis还在不在。存在redis键时两边的余额数据写进主数据库。

界面上显示A的余额时用当前余额减去redis里的暂扣额度。
回复

使用道具 举报

 楼主| 发表于 2021-11-22 21:16 | 显示全部楼层
系统杀手 发表于 2021-11-22 21:11
A预先扣除的币不要动主数据库的余额,写进redis然后设置10分钟过期。

有B迎战时检查redis还在不在。存在re ...

如果预扣的代币不写进主数据库的话,可能因为用户同时进行其他消费代币操作,导致代币变成负数……

虽然也可以每个消费代币的操作也检查redis,但是有点麻烦……
回复

使用道具 举报

     
发表于 2021-11-22 21:18 | 显示全部楼层
你这游戏玩的是论坛积分,又不是实时汇款,没必要为了一分钟的延迟增加系统复杂度。

就用你熟悉的“定时任务”机制先做出来就行。

—— 来自 S1Fun
回复

使用道具 举报

     
发表于 2021-11-22 23:09 来自手机 | 显示全部楼层
本帖最后由 super_uni 于 2021-11-22 23:11 编辑

按你需求来说的话,
1.建张历史交易表,有字段
用户
代币扣除额度
过期时间
应战人

2.每次发起挑战往里面加一条数据,过期时间为十分钟后,应战人为空

3.每次用户查看自己剩余代币,发起新挑战或者应战别人时是不是都要先看一下数据库里的自己的当前额度?这时候就在查数据库的操作之前加一个逻辑,查找历史交易表里a用户的所有交易数据,过滤出应战人为空且过期时间在现在之前的数据,把这些代币加回用户个人信息表里去,再把加完后的实际代币数返回回去就行了。
细节自己调整就行。

这种设计模式一般称作less is more



— from OPPO PEGM00, Android 11 of S1 Next Goose v2.5.2
回复

使用道具 举报

     
发表于 2021-11-22 23:10 | 显示全部楼层
php 的话, 一般是用 crontab 写个定时任务。 或者你搜索一下定时任务实现
回复

使用道具 举报

     
发表于 2021-11-22 23:10 | 显示全部楼层
Laravel这么成熟的框架应该有crontab的组件吧。我曾经接触过thinkphp项目,用的是Linux自带的crontab服务调用,当时震惊了我一下
回复

使用道具 举报

     
发表于 2021-11-23 01:09 | 显示全部楼层
php弄定时任务先天缺陷,传统做法就是设置任务时间,推到一个任务队列表里,请求进来后去查一下任务表有没有到时间需要执行的,对于处理时间短的任务,这方案比依赖外部执行器稳定,泥潭discuz自带的定时任务就这么干的
回复

使用道具 举报

头像被屏蔽
     
发表于 2021-11-23 01:40 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回复

使用道具 举报

     
发表于 2021-11-23 09:56 | 显示全部楼层
定时任务其实没太大问题 复杂度也比较低

想设计的优雅一点 这个场景下应该比较适合用延迟消息
1. a用户预扣款, 创建订单1, 状态为匹配中
2. 创建延迟消息, 10分钟后检查订单1是否完成
(3). 用户b应战, 更新订单1状态为完成
4. 延迟消息到期, 检查订单1状态, 未完成则取消订单, 预扣款回退.

延迟消息有很多做法, redis+定时任务也是一种方式 不依赖外部组件可以直接起个异步线程(php里怎么做没研究, 反正肯定行得通)
可靠性高一点的话 可以用消息队列(mq)
常用的mq都支持这种延迟消息模式
回复

使用道具 举报

 楼主| 发表于 2021-11-23 11:02 | 显示全部楼层
紧那罗 发表于 2021-11-23 09:56
定时任务其实没太大问题 复杂度也比较低

想设计的优雅一点 这个场景下应该比较适合用延迟消息

谢谢!我用redis定时消息试试看,感觉比较优雅。反正现在已经有在用redis了。

反正只是自己做着玩,还是要自己写得舒服
回复

使用道具 举报

 楼主| 发表于 2021-11-23 11:06 来自手机 | 显示全部楼层
pyjq 发表于 2021-11-22 23:10
Laravel这么成熟的框架应该有crontab的组件吧。我曾经接触过thinkphp项目,用的是Linux自带的crontab服务调 ...

昨晚看了下,laravel是有crontab组件,虽然限制也很多。和主楼说的方案一样应该是可以实现的。
只是想看看有无好的方案。
回复

使用道具 举报

     
发表于 2021-11-26 14:53 | 显示全部楼层
能用mq嘛 延时队列 到时check下数据没有应答就退还
回复

使用道具 举报

     
发表于 2021-11-26 15:25 来自手机 | 显示全部楼层
建议从帖子上入手,挑战帖子发出时候添加一个600s后的时间戳,超过这个时间的就无法发起挑战,至于积分你是1分钟后计算还是10分钟后计算都可以,而且这些功能应该是论坛都有类似的(过时锁定,限时置顶),改改就可以用
回复

使用道具 举报

     
发表于 2021-11-26 16:07 | 显示全部楼层
把问题分离开来,游戏状态和代币回退分成两个操作。发起时存好时间戳(或记录游戏结束时间戳),游戏的逻辑加入时间戳的判断。代币回退用定时任务,有60秒内的延时也比较正常。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|上海互联网违法和不良信息举报中心|网上有害信息举报专区|962110 反电信诈骗|举报电话 021-62035905|Stage1st ( 沪ICP备13020230号-1|沪公网安备 31010702007642号 )

GMT+8, 2024-9-23 11:28 , Processed in 0.058197 second(s), 5 queries , Gzip On, Redis On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表