You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于用户活跃时段通过FCM每日推送高赞帖的高效架构问询

方案评估与优化建议

1. 你提出的方案是否高效?

整体思路可行,但存在几个细节需要优化,避免效率问题或逻辑漏洞:

  • 2小时粒度的cron任务:如果active_times表建有基于活跃时段起始/结束时间的联合索引,查询当前窗口内的用户会很高效;但如果用户的活跃时段跨多个2小时窗口(比如13:00-15:00),会被多个cron任务命中,此时Redis的校验逻辑必须可靠,否则会出现重复推送。
  • 12小时的Redis过期时间:不符合「每日推送一次」的需求——若用户活跃时段在当天的两个12小时窗口内(比如上午10点和晚上10点),Redis过期后会导致同一天内重复推送,应调整为24小时或按天维度维护过期规则。
  • 批量处理优化:若cron任务查询到大量用户,需批量调用FCM接口,避免单条请求循环调用拖慢任务执行效率。

2. Redis是否适用于此类场景?

非常适用,核心原因如下:

  • Redis内存读写速度极快,做「是否已推送」的高频校验,相比每次查询Postgres能大幅降低数据库压力。
  • 内置的过期机制可自动清理旧推送记录,无需手动维护数据生命周期。
  • 支持多种数据结构:哈希表可存储用户推送时间等额外信息;集合(Set)能更高效判断用户是否已在当天被推送;字符串(String)可通过user:{user_id}:pushed:{date}的键名直接存储推送状态,可按需选择。

3. 更优实现方案建议

针对你的需求,可从以下维度优化:

(1)精准控制每日推送次数

将Redis过期策略调整为按天维度:

  • 用集合类型存储每日已推送用户,键名格式为pushed_users:20240520(日期为当天),用户ID作为集合元素。
  • 每日0点自动创建新集合,旧集合设置24小时过期或直接删除,避免占用内存。
  • 推送前先判断用户是否在当天集合中,不在则执行推送并将用户ID加入集合。

(2)优化cron任务与数据库查询

  • 给active_times表添加联合索引(active_start, active_end),确保查询当前窗口活跃用户的SQL能快速过滤数据,示例SQL:
    SELECT user_id FROM active_times 
    WHERE active_start <= CURRENT_TIMESTAMP 
      AND active_end >= CURRENT_TIMESTAMP
    
  • 新增push_logs表到Postgres,持久化推送记录(存储user_id、push_date、post_id等),作为Redis缓存失效后的兜底校验,避免极端情况下的重复推送。

(3)降低Postgres依赖,提升推送效率

  • 预缓存高赞帖子:每小时执行一次任务,从Postgres查询Top N高赞帖子,缓存到Redis的列表或哈希表(比如top_posts:daily),cron任务直接从Redis取帖子,减少对Postgres的查询压力。
  • 批量获取FCM Token:将用户的FCM Token存储在Redis(或Postgres带索引),查询用户后批量获取Token,再调用FCM的批量推送接口,减少HTTP请求次数。

(4)避免多实例任务冲突

若Gin服务为多实例部署,需给cron任务加分布式锁:

  • 用Redis的SETNX命令实现锁,比如SET lock:push_task:20240520_10-12 1 EX 3600 NX,确保同一时间只有一个实例处理当前2小时窗口的推送任务,避免重复处理用户。

内容的提问来源于stack exchange,提问作者Matthew Trent

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 23:02:41