实现Firebase通知:优化调用次数以减少读取量
问题
我正尝试用Firebase/FCM实现通知系统,遇到了性能成本问题:基于时区、由cron触发的通知用户筛选方案会产生大量读取请求。
用户功能需求:允许用户选择每周的日期和固定时间接收提醒通知。
现有实现方案:
后端用JSON对象存储配置,以userid为键,值包含通知的日期、时间及时区:
{ "userid1": { "days": ["Monday","Tuesday","Wednesday"], "time": "20:00", "timezone": "America/New_York" }, "userid2": { "days": ["Sunday","Tuesday","Wednesday"], "time": "21:00", "timezone": "Europe/London" }, ... }
这种存储方式能避免夏令时问题,但我原本计划每15分钟运行一次定时函数,查询符合当前时间窗口的用户并发送通知。
核心问题:由于时间和时区分开存储,每次定时任务都需要遍历所有用户记录。假设有1000名用户,每天会产生96000次(1000424)读取请求,成本过高。
补充说明:每个用户的通知配置包含星期、时区和本地时间,本地时间+时区需转换为UTC时间才能筛选,但受夏令时影响,无法提前完成固定转换。
标准实现方案
1. 反向构建可查询索引
不要以userid为唯一键,而是构建**「UTC时间窗口+星期」为键**的索引结构,示例:
{ "utc_14_00_monday": ["userid1", "userid3"], "utc_20_00_tuesday": ["userid1", "userid2"], ... }
- 每周定时更新(比如周日):遍历所有用户,根据其本地时间+时区+星期,计算对应的15分钟UTC时间窗口,将userid添加到对应索引键下。夏令时变化时,每周更新会自动修正UTC偏移。
- 定时任务触发时,直接查询当前UTC时间窗口+对应星期的索引键,快速获取目标用户列表,无需全量读取。
2. 利用Firebase时区调度能力
Firebase Cloud Functions支持指定时区触发定时任务,无需自行全量筛选:
- 针对常用的「时区+时间+星期」组合,创建对应定时函数。比如针对
America/New_York时区20:00,设置每周一到周三触发的任务。 - 任务触发时,直接查询存储中匹配该时区、时间、对应星期的用户,发送通知。Firebase会自动处理夏令时的触发时间调整。
3. 实时更新索引+缓存优化
- 用户更新通知配置时,实时计算并更新其对应的UTC时间窗口索引,替代每周批量更新,保持索引实时性,减少批量操作的资源消耗。
- 缓存活跃用户的配置:将近期有交互的用户配置缓存到内存或Redis,定时任务优先读取缓存,降低数据库读取次数。
4. 批量查询优化
如果必须全量读取,优化查询方式:
- 使用Firebase批量查询接口,一次请求获取多条记录,减少请求次数。
- 分页读取用户数据,避免单次请求处理过大数据量,降低内存和带宽压力。
内容的提问来源于stack exchange,提问作者udit
相关产品推荐
相关产品推荐

