Page 1 of 1

用户状态(在线、离线、正在输入)如何存储和更新?

Posted: Tue May 20, 2025 11:12 am
by muskanislam99
在消息传递应用中,用户状态(在线、离线、正在输入)的管理是实现实时互动体验的关键。这些状态通常不会像消息内容那样持久化存储在主数据库中,因为它们是瞬态的(Ephemeral)且高度实时的。相反,它们依赖于高性能的内存数据库、发布/订阅系统和实时推送服务。

1. 用户在线/离线状态 (Online/Offline/Last Seen)
a. 存储方式:内存数据库或分布式缓存
中央状态存储: 一个专用的、高性能的内存数据库(如 Redis 或 Memcached)或分布式缓存集群是存储用户在线状态的理想选择。

键-值存储: 键可以是 user_id,值可以是 status(例如,"online", "offline")和 last_seen_timestamp。
优点: 极快的读写速度,能够处理高并发的查询和更新,非常适合实时性要求高的场景。
数据模型示例:
Key: user:<user_id>:presence
Value: { "status": "online", "timestamp": 1716183600000 }

Key: user:<user_id>:last_seen
Value: 1716183600000 (Unix timestamp in milliseconds)
持久化: 尽管在线状态是瞬态的,但 last_seen_timestamp 通常需要一定程度的持久化(例如,每隔一段时间批量写入到关系型数据库或更持久的 NoSQL 存储中),以应对内存数据库重启或故障的情况,并提供“最后上线时间”功能。

b. 更新机制:心跳与连接管理
在线 (Online):
当用户打开 WhatsApp 应用程序并成功连接到消息服务器时,客户端会发送一个“在线”状态通知。
服务器接收到此通知后,立即更新内存数据库中 巴西 whatsapp 数据库 该用户的状态为 online,并更新 last_seen_timestamp 为当前时间。
客户端会定期发送**心跳(Heartbeat)**信号给服务器(例如,每隔几秒到几十秒),以维持其在线状态。如果服务器在预设时间内未收到心跳,则认为该用户已离线。
离线 (Offline):
主动离线: 当用户关闭应用程序或断开网络连接时,客户端会尝试发送一个“离线”状态通知给服务器。
被动离线: 如果服务器长时间未收到某个用户的心跳信号(例如,超过 30-60 秒),服务器会主动将该用户的状态更新为 offline。
Last Seen: last_seen_timestamp 会在用户从“在线”变为“离线”时被记录下来,并用于显示“最后上线时间”。
c. 通知与隐私设置
发布/订阅 (Pub/Sub): 当某个用户的在线状态发生变化时,服务器会通过一个发布/订阅系统(如 Apache Kafka、RabbitMQ 或 Redis Pub/Sub)向所有关注该用户的客户端(例如,聊天列表中的联系人、正在与该用户聊天的客户端)发布状态更新事件。
客户端接收与显示: 客户端订阅了其联系人的状态更新。当收到更新时,它会相应地更新 UI。
隐私控制: WhatsApp 允许用户设置“谁可以看到我的最后上线时间”和“谁可以看到我在线”。服务器在推送状态更新时,会根据这些隐私设置进行过滤,只将状态信息发送给被允许查看的用户。
2. 正在输入状态 (Typing...)
“正在输入”状态比在线/离线状态更加瞬态和上下文相关。

a. 存储方式:几乎不存储,通过实时消息传递
瞬时性: “正在输入”状态通常不会持久化存储在数据库中,甚至在内存数据库中也只是短暂存在。它是一个非常即时的信号。
实现方式: 依赖于实时消息传递协议(如 XMPP 或 MQTT)。
b. 更新机制:事件驱动
发送方触发:
当用户 A 在聊天输入框中开始输入第一个字符时,用户 A 的客户端会立即向服务器发送一个“正在输入”事件,并附带 chat_id(一对一或群聊)。
如果用户停止输入超过几秒(例如 5 秒),或者发送了消息,客户端会发送一个“停止输入”事件。
服务器中转:
服务器接收到用户 A 的“正在输入”事件。
服务器立即识别出 chat_id 对应的聊天会话。
对于一对一聊天:服务器将“用户 A 正在输入”事件直接推送给用户 B 的设备。
对于群聊:服务器将“用户 A 正在输入”事件广播给群组 G 的所有其他活跃成员的设备。
服务器通常不会持久化存储这个状态,因为它只有非常短的有效期。
接收方显示:
接收方客户端收到“正在输入”事件后,会在聊天界面的顶部(或消息输入框附近)显示“XXX 正在输入…”或“多人正在输入…”的提示。
当收到“停止输入”事件,或在一定时间(例如 10 秒)内未收到新的“正在输入”事件,客户端会自动清除该提示。
3. 系统架构概览
客户端: 监听用户输入事件,发送状态更新;订阅联系人状态更新,更新 UI。
消息服务器/Presence Server: 接收、处理和转发状态更新。维持客户端连接和心跳。
内存数据库/缓存 (Redis/Memcached): 存储用户在线/离线状态及其时间戳,用于快速查找和持久化 last_seen。
发布/订阅系统 (Kafka/Redis Pub/Sub): 用于高效广播状态变化事件给相关订阅者。
关系型数据库 (Optional): 周期性地将 last_seen_timestamp 等非实时状态持久化,以确保数据完整性。
这种组合方案实现了用户状态的实时、可扩展和隐私控制下的管理,为 WhatsApp 提供了流畅的即时通信体验。