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

React Native移动端通知系统开发技术咨询

解决方案与疑问解答

一、Kafka核心疑问解答

1. 消费者消费后消息是否会被删除?

不会。Kafka的消息删除逻辑和消费行为完全无关:

  • 消息只会在达到主题保留策略(比如保留7天、或达到指定存储大小)时才会被清理;
  • 消费者消费消息后,只是提交自己所在消费者组的偏移量(offset),标记该组已经读到这个位置,消息本身依然存在于主题中,其他消费者组可以继续读取。

2. 同一主题下如何筛选特定用户消息且不影响其他用户?

你当前“所有用户的通知发同一个主题”的思路是合理的,不需要为每个用户单独建主题,推荐以下实现方式:

  • 生产者端:发送消息时,在消息内容里明确带上recipient_user_id(接收者ID),示例消息结构:
    {
      "recipient_user_id": 123,
      "notification_type": "answer",
      "content": "3人已回复你的问题",
      "meta": {
        "last_commenter_name": "张三",
        "last_commenter_avatar": "xxx.jpg",
        "discussion_id": 456
      }
    }
    
  • 消费者端:
    • 每个在线用户的WebSocket连接对应一个独立的消费者实例,且每个消费者的消费者组名唯一(比如notification-consumer-${user_id});
    • 用户上线时,启动该消费者,订阅answers/views主题,从自己消费者组的最后偏移量开始消费;
    • 消费者每收到一条消息,先判断recipient_user_id是否等于当前连接的用户ID:
      • 是:推送到对应的WebSocket连接,然后提交偏移量;
      • 否:直接跳过并提交偏移量——因为你的消费者组是唯一的,这条消息不属于当前用户,但其他用户的消费者组会维护自己的偏移量,不会被影响。

这样既保证了每个用户能获取到自己的所有离线消息,又不会因为同一主题的消息互相干扰。

二、通知聚合实现

针对「多条回复更新为X人已回复」的需求,需要在后端做通知状态维护:

  1. 在PostgreSQL中新建notifications表,核心字段:
    • id(主键)
    • user_id(接收用户ID)
    • target_type(关联类型,比如discussion)
    • target_id(关联ID,比如讨论ID)
    • unread_count(未读回复数)
    • last_commenter_id(最后评论者ID)
    • last_commenter_avatar(最后评论者头像)
    • content(通知内容,比如「X人已回复你的问题」)
    • read_at(已读时间,null表示未读)
    • created_at/updated_at
  2. 当有新回复时:
    • 先查询是否存在该用户对应此讨论的未聚合通知(user_id+target_id+read_at is null);
    • 存在:更新unread_count +=1,更新last_commenter相关字段,更新updated_at;
    • 不存在:创建新通知,unread_count=1,填充评论者信息;
  3. 将这条聚合后的通知发送到Kafka的answers主题。

三、实时推送与离线存储

  1. 前台在线时:Node.js后端维护WebSocket连接池,记录每个连接对应的user_id;当Kafka消费者收到属于在线用户的通知时,直接从连接池中找到对应连接推送消息,同时可按需更新PostgreSQL的notifications表(比如实时标记已读)。
  2. 用户离线时:消息存储在Kafka主题中,只要在主题保留期内,用户下次上线启动消费者时,就能读取到所有未消费的自己的通知,推送到应用内。

四、持久化存储选择:PostgreSQL vs MongoDB

推荐沿用现有的PostgreSQL,不需要换MongoDB:

  • 通知是结构化数据,需要和现有用户、讨论系统做关联查询,PostgreSQL的关系型特性更适配;
  • PostgreSQL的JSONB类型可以灵活存储通知的元数据(比如评论者头像、用户名等),兼顾结构化和灵活性;
  • 你现有技术栈已经熟悉PostgreSQL,切换MongoDB会增加学习和维护成本,没必要。

五、Redis vs Kafka的补充说明

你放弃Redis选Kafka是正确的:

  • Redis Pub/Sub是无持久化的,用户离线时消息直接丢失,无法满足离线存储需求;
  • Redis的List做消息队列的话,当用户量(12000)增大时,维护每个用户的队列会非常繁琐,且Redis的持久化不如Kafka可靠;
  • Kafka的主题-分区模型天生适合处理大量用户的通知消息,且持久化、可扩展性更强。

内容的提问来源于stack exchange,提问作者Sam Leurs

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 06:45:06