如何实现每秒向所有用户发放货币的经济机器人?
实现每秒给所有用户发放货币的经济机器人方案
嘿,你的思路方向完全没问题——用setInterval定时触发+新增未领取收益字段的方式,既能满足每秒发币的需求,还能减少直接修改余额带来的并发风险。下面是我整理的具体实现方案,亲测好用的那种:
核心思路拆解
- 给用户数据新增
unclaimed字段,专门累计每秒发放的货币(不用每次直接改bal,降低文件写入冲突概率) - 用
setInterval每秒触发批量更新逻辑,遍历所有用户累加未领取收益 - 封装安全的JSON文件读写工具,处理异步操作和异常情况
- 加个简单的锁机制,避免上一次文件操作还没完成就触发下一次,防止数据错乱
具体代码实现
1. 先封装文件读写工具
用Node.js的fs/promises做异步文件操作,比同步操作更适合定时任务场景:
const fs = require('fs').promises; const path = require('path'); // 固定用户数据文件路径 const USER_DB_PATH = path.join(__dirname, './DB/users.json'); // 读取用户数据的工具函数 async function readUsers() { try { const data = await fs.readFile(USER_DB_PATH, 'utf8'); return JSON.parse(data); } catch (err) { // 如果文件不存在,返回空对象 if (err.code === 'ENOENT') return {}; throw err; } } // 写入用户数据的工具函数 async function writeUsers(users) { await fs.writeFile(USER_DB_PATH, JSON.stringify(users, null, 2), 'utf8'); }
2. 实现每秒发币的核心逻辑
这里默认给每个用户每秒发放和workers数量对应的货币(你可以直接改成固定数值,比如1):
// 标记是否正在处理任务,避免并发冲突 let isProcessing = false; // 每秒发放货币的核心函数 async function distributeCurrency() { if (isProcessing) return; // 如果上一次还没处理完,跳过本次触发 isProcessing = true; try { const users = await readUsers(); // 遍历所有用户ID,逐个更新未领取收益 for (const userId of Object.keys(users)) { const user = users[userId]; // 初始化unclaimed字段(老用户数据里可能没有) if (!user.unclaimed) user.unclaimed = 0; // 每秒累加货币,这里和workers挂钩,你可以按需调整规则 user.unclaimed += user.workers || 1; } await writeUsers(users); console.log('本次货币发放完成'); } catch (err) { console.error('发币过程出错:', err); } finally { isProcessing = false; // 处理完成后解锁,允许下一次触发 } } // 启动定时任务,每秒触发一次 setInterval(distributeCurrency, 1000);
3. 可选:用户领取未结算收益的逻辑
如果需要用户主动领取这些累计的收益,可以加个领取函数:
async function claimUnclaimed(userId) { const users = await readUsers(); if (!users[userId] || users[userId].unclaimed <= 0) { return { success: false, message: '没有可领取的收益哦' }; } // 将未领取收益转入余额 users[userId].bal += users[userId].unclaimed; users[userId].unclaimed = 0; // 重置未领取字段 await writeUsers(users); return { success: true, newBalance: users[userId].bal }; }
关键注意事项
- 并发安全:
isProcessing锁是重中之重,因为文件读写是异步的,如果每秒触发太频繁,上一次写入还没完成就开始下一次读取,会直接导致数据覆盖丢失 - 性能优化:如果未来用户量很大,每秒遍历所有用户可能会有性能瓶颈,到时可以考虑分批处理,或者换成数据库(比如SQLite、MongoDB)代替JSON文件
- 错误处理:一定要捕获文件操作的异常,避免单个用户的数据错误导致整个定时任务崩溃
内容的提问来源于stack exchange,提问作者Wilk
相关产品推荐
相关产品推荐

