message-api(WebSocket)消息推送:持久/非持久、已读回写、未读重推全链路解析(含双 Kafka、Redis、TiDB、BloomFilter)

message-api(WebSocket)消息推送:持久/非持久、已读回写、未读重推全链路解析(含双 Kafka、Redis、TiDB、BloomFilter) 本文基于一套真实的message-api(WebSocket)工程实现,拆解持久消息(perss)、非持久消息(nonperss)、已读回写、未读重推(补发)四条链路,并结合代码讲清楚:为什么要区分 perss / nonperssRedis / TiDB / Kafka 各自承担什么角色BloomFilter 在哪里做去重、为什么要分片为什么会出现“读了还被推”“重推风暴”,以及如何优化0. 全景架构(原图)1. 术语与目标1.1 perss vs nonperssperss(持久消息):会落库t_message_record(TiDB),支持离线未读补发、已读回写、审计追溯。nonperss(非持久消息):不落库,不做已读闭环,强调即时体验与低成本(用户离线错过即错过)。1.2 系统目标可靠性:perss 不丢消息,能补发,读回执最终一致。性能:高并发推送不拖垮 DB;重推/补发能控住。可观测:指标(Counter/Latency)能量化吞吐与延迟。2. Topic 与组件分工2.1 入口与下发 Topictopic_message_push_perss:持久消息入口(perss)topic_message_push_nonperss:非持久消息入口(nonperss)topic_websocket_send_push(代码里常量WEB_SOCKET_SEND_PUSH):写给 WebSocket 服务的下发 topic受sendTwo开关控制,可写到Kafka1或Kafka2(双 Kafka)topic_message_readStatus_writeBack(WRITEBACK_TOPIC_NAME):已读回写 topictopic_message_unreadMessageResend_notify:触发未读补发的事件 topic(登录/重连等)2.2 存储TiDB:t_message_record持久化消息实体、未读查询源、审计追溯。Redis:轻量状态层(messageId - 0/1未读/已读)+ BloomFilter(若使用 Redisson RBloomFilter)。2.3 去重(BloomFilter)系统里通常存在三类去重:发送去重:businessId + businessTopic + billNo(避免短窗口重复推送)补发事件去重:loginName + event(避免短窗口重复触发补发)补发消息去重:messageId(避免短窗口重复补发同一消息)3. 持久消息(perss)发送链路(原图 + 代码)3.1 perss 流程图(原图)