基于Node.js与Heroku的数据存储最优方案及Discord私有公会Bot存储咨询
适合Node.js+Heroku的Discord机器人免费数据存储方案
Hey there! 我刚好在Heroku上部署过几个Discord私有公会机器人,对于存储警告这类小体量数据,有几个亲测好用的免费方案,根据你的需求分情况推荐:
1. Heroku自带PostgreSQL免费层(首推)
这应该是最适配Heroku的方案了,官方集成、稳定靠谱,完全免费的Hobby Dev层足够支撑私有公会的警告数据存储(限制10k行数据,小公会绝对够用)。
怎么用:
- 登录Heroku控制台,找到你的机器人应用,在「Resources」标签里搜索「Heroku Postgres」,选择免费的Hobby Dev层添加。
- Node.js里用
pg包连接数据库,Heroku会自动配置好DATABASE_URL环境变量,无需手动填写密码。 - 简单的警告表操作示例:
const { Pool } = require('pg'); const pool = new Pool({ connectionString: process.env.DATABASE_URL }); // 初始化警告表(首次运行执行) async function initDB() { await pool.query(` CREATE TABLE IF NOT EXISTS warnings ( id SERIAL PRIMARY KEY, user_id VARCHAR(20) NOT NULL, guild_id VARCHAR(20) NOT NULL, reason TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) `); } // 添加一条警告记录 async function addWarning(userId, guildId, reason) { await pool.query( 'INSERT INTO warnings (user_id, guild_id, reason) VALUES ($1, $2, $3)', [userId, guildId, reason] ); } // 查询用户在指定公会的所有警告 async function getUserWarnings(userId, guildId) { const result = await pool.query( 'SELECT * FROM warnings WHERE user_id = $1 AND guild_id = $2', [userId, guildId] ); return result.rows; }
优缺点:
- ✅ 无需额外配置,和Heroku深度集成
- ✅ 支持复杂SQL查询,适合结构化数据存储
- ❌ 免费层每月有休眠时间,唤醒时可能有几秒延迟,但私有公会几乎感知不到
- ❌ 10k行数据限制,超出后需升级付费层
2. JSON文件+免费云存储(极简方案)
如果完全不想碰数据库,只想用最朴素的方式存储,这个方案绝对适合你。把警告数据存在JSON文件里,定时同步到免费云存储(比如Google Drive/OneDrive的免费空间),机器人启动时从云存储下载最新的JSON文件即可。
怎么用:
- 用Node.js的
fs模块读写JSON文件:
const fs = require('fs').promises; const path = require('path'); const WARNINGS_FILE = path.join(__dirname, 'warnings.json'); // 读取警告数据 async function getWarnings() { try { const data = await fs.readFile(WARNINGS_FILE, 'utf8'); return JSON.parse(data); } catch (err) { // 文件不存在时返回空结构 return { guilds: {} }; } } // 添加一条警告 async function addWarning(userId, guildId, reason) { const warnings = await getWarnings(); if (!warnings.guilds[guildId]) warnings.guilds[guildId] = {}; if (!warnings.guilds[guildId][userId]) warnings.guilds[guildId][userId] = []; warnings.guilds[guildId][userId].push({ reason, timestamp: Date.now() }); await fs.writeFile(WARNINGS_FILE, JSON.stringify(warnings, null, 2)); }
- 搭配Google Drive免费API,用
node-schedule写个定时脚本,每天把JSON文件同步到云端,启动时从云端拉取最新文件即可。
优缺点:
- ✅ 零学习成本,代码极简
- ✅ 完全免费,无数据行数/内存限制(只要云存储空间够)
- ❌ 并发能力差,不适合多机器人实例同时读写
- ❌ 同步脚本需额外配置,偶尔可能出现数据不同步的情况
3. Redis免费层(适合键值型高频数据)
如果你的警告数据更偏向键值对(比如统计用户警告次数),Redis免费层是不错的选择——读写速度快,适合高频操作场景。
怎么用:
- 可以用Heroku的Redis Hobby Dev免费层(在Resources里添加),或者Redis Labs的免费云服务(25MB内存)。
- 用
ioredis包连接,示例代码:
const Redis = require('ioredis'); const redis = new Redis(process.env.REDIS_URL); // Heroku自动配置环境变量 // 给用户增加一次警告计数 async function incrementWarning(userId, guildId) { const key = `warning:${guildId}:${userId}`; await redis.incr(key); // 可选:设置过期时间(比如保存30天) await redis.expire(key, 2592000); } // 获取用户在指定公会的警告次数 async function getWarningCount(userId, guildId) { const key = `warning:${guildId}:${userId}`; const count = await redis.get(key); return count ? parseInt(count) : 0; }
优缺点:
- ✅ 读写速度极快,适合高频操作
- ✅ 集成Heroku很方便
- ❌ 免费层内存有限(25MB),不适合存储大量结构化数据
- ❌ 不支持复杂关系查询,仅适合键值型数据
避坑提醒:别用SQLite在Heroku存储持久化数据
很多人一开始会想到SQLite,因为它是文件型数据库无需额外服务,但Heroku的临时文件系统会导致数据丢失——每次dyno重启(比如部署代码、休眠唤醒),所有本地文件都会重置,之前存储的警告数据会全部消失。除非你能接受数据丢失,或者写脚本定时备份到云端,但这样反而不如直接用上面的方案省事。
内容的提问来源于stack exchange,提问作者Chilli
相关产品推荐
相关产品推荐

