在做社区旧物互换平台时,用户注册和登录都需要验证码。最开始我也考虑过几种常见方案:把验证码存进数据库表、引入 Redis,或者直接调用第三方验证码服务。
但这个项目目前主要是本地开发和小范围演示,如果为了验证码专门引入 Redis,会增加部署复杂度;如果建一张verification_code表,又会产生大量短生命周期数据。于是最终我选择了一个更轻量的方案:在code_service.py中用一个进程内存字典_STORE来存储验证码。
为什么不用 Redis?
Redis 确实很适合做验证码缓存,支持过期时间、分布式共享、高并发访问。但对于当前阶段的项目来说,它有几个成本:
- 需要额外安装和运行 Redis 服务;
- 本地开发环境配置会变复杂;
- 如果只是单实例、小规模使用,收益并不明显。
所以我的思路是:先把核心业务跑通,用进程内存字典降低开发成本。如果后续项目部署到多实例服务器,再考虑切换到 Redis。
为什么不用数据库表?
验证码本身有这几个特点:
- 有效期很短,通常 5 分钟左右;
- 校验通过后就应该失效;
- 写入和读取都非常频繁;
- 不需要长期保存。
如果把这些数据都写入数据库,会增加不必要的 IO 开销。而且验证码校验通过后还要删除或标记失效,表结构也会变得比较臃肿。
所以最后我决定:验证码只存在于内存中,不依赖 Redis,也不落库。
最终方案:code_service.py中的_STORE
我在code_service.py里定义了一个字典_STORE,用来保存验证码和发送时间。
当前平台的验证码规则是:
- 验证码有效期:5 分钟
- 发送间隔限制:60 秒内不能重复发送
- 校验成功后:立即删除
- 存储方式:进程内存字典
_STORE
核心代码大致是这样的:
这里没有用第三方缓存库,而是直接在字典里存验证码和过期时间。每次校验时,先判断是否存在,再判断是否超过 5 分钟,最后比较验证码是否正确。
在 FastAPI 中怎么接入?
在 FastAPI 路由里,可以把验证码发送和校验逻辑封装成工具函数:
这样前端只需要传入邮箱或手机号,后端负责生成验证码、写入 _STORE、校验和删除。
这个方案的优点
- 轻量:不需要安装 Redis,也不需要建表。
- 开发快:本地启动 FastAPI 就能直接测试。
- 适合短生命周期数据:验证码本来就不需要持久化。
- 结构简单:一个字典就能完成存储、校验和清理。
需要注意的限制
这个方案也有明显边界:
- 重启服务后验证码会丢失,因为数据只存在进程内存里;
- 多实例部署时无法共享,每个进程有独立
_STORE; - 需要手动清理过期数据,字典不会自动删除过期项;
- 生产环境建议加监控,避免内存字典异常导致用户无法登录。
所以它更适合开发、测试、演示或单实例部署场景。如果项目后续用户量变大,或者需要多节点部署,我会考虑把验证码迁移到 Redis。
后续改进方向
目前这个验证码模块已经接入了平台的邮箱和手机号验证流程。后续可以继续完善:
接入真实 SMTP 邮箱服务;
接入短信服务商;
增加图形验证码,防止机器批量请求;
把验证码发送次数写入日志,方便排查异常;
在多实例部署时替换为 Redis 后端。
小结
这个验证码方案并不复杂,但它解决了一个很实际的问题:在没有 Redis、不想建表的情况下,如何快速实现一个可用的验证码系统。
对于学生项目、个人项目或早期原型来说,轻量方案往往更合适。先把核心流程跑通,再根据实际部署需求逐步升级,会比一开始追求“完美架构”更高效。
如果你也在做类似的全栈项目,欢迎交流你的验证码方案。下一篇我会继续分享这个平台的物品管理与数据库设计。