WhatsApp 在数据库中标记消息的已读/未读状态是一个结合了客户端本地存储和服务器端同步的复杂机制,旨在提供高效的用户体验和准确的“已读回执”(即著名的蓝色双勾)。
1. 客户端本地数据库标记 (Client-Side Database Marking)
每位用户的 WhatsApp 客户端(Android 上的 msgstore.db 或 iOS 上的 ChatStorage.sqlite)都维护着一个本地数据库,这是消息已读/未读状态的主要存储地。
chats 或 chat_list 表:
这个表记录了用户所有的个人聊天和群组聊天的基本信息。
unread_count 字段: 这是最直观的未读标记。对于每个聊天,这个字段会存储当前有多少条未读消息。当有新消息抵达且用户未查看时,此计数会增加;当用户查看聊天时,此计数会清零。
last_read_message_id 或 last_seen_message_id 字段: 这个字段存储的是用户在该聊天中“最后已读”或“最后已查看”的消息的 ID。客户端通过比较这个 ID 与聊天中最新消息的 ID 来判断是否存在未读消息。所有 ID 小于等于 last_read_message_id 的消息都被视为已读。
messages 表:
这个表存储了所有消息的详细内容。每条消息可能有一个 status 字段(或类似的,如 read_status),但这个 status 主要反映的是消息对于发送方来说的状态(例如,是否已送达对方设备,是否已被对方读取),而不是接收方设备本身的未读状态。对于接收方而言,判断消息是否未读主要依赖 chat_list 表中的 unread_count 和 last_read_message_id。
本地工作机制:
当用户打开一个聊天窗口时,WhatsApp 客户端会执行以下操作:
更新 last_read_message_id: 将当前 挪威 whatsapp 数据库 聊天中可见的最新消息的 ID 更新到 chat_list 表的 last_read_message_id 字段。
清零 unread_count: 将 chat_list 表中该聊天的 unread_count 字段设置为 0。
发送已读回执: 客户端会生成一个“已读”事件(Read Receipt),并通过 WhatsApp 服务器发送给消息的发送方。
WhatsApp 服务器(如其基于 Cassandra 的分布式数据库)不存储消息的明文内容,但它会存储与消息投递和阅读状态相关的元数据,以实现跨设备同步和向发送方提供已读回执。
概念性表/机制:
user_chat_states 或 user_read_pointers 表:
主键: 通常是 (user_id, chat_id)。
字段: last_read_message_id。这个表存储了每个用户在每个聊天中服务器已知的最后已读消息 ID。这是实现多设备同步的关键。
message_delivery_status 表:
主键: 可能是 (message_id, recipient_user_id) 或 (message_id, group_id, recipient_user_id)。
字段: status (例如,SENT - 已发送到服务器,DELIVERED_TO_DEVICE - 已送达接收方设备,READ_BY_RECIPIENT - 已被接收方读取)。这个表为每条消息针对每个接收方维护精确的状态,支持“消息详情”功能(显示消息何时被谁送达/读取)。
服务器端工作机制:
客户端发送已读事件: 当接收方的客户端将消息标记为已读(更新本地 last_read_message_id 和 unread_count)时,它会向 WhatsApp 服务器发送一个“已读回执”事件,其中包含聊天 ID 和已读到的最新消息 ID。
服务器更新状态: 服务器接收到这个事件后,会更新其 user_chat_states 表中该用户在该聊天中的 last_read_message_id。
通知发送方: 服务器随后会向消息的发送方发送一个“已读通知”。
发送方客户端更新: 发送方的 WhatsApp 客户端收到这个通知后,会更新其本地 messages 表中对应消息的 status 字段。
从“已送达”(两个灰勾)更新为“已读”(两个蓝勾)。
对于群聊,服务器会根据每个成员的阅读状态单独发送通知,允许发送方查看哪些群成员已读了消息。
多设备同步: 如果用户在手机上阅读了消息,服务器上的 user_chat_states 会更新。当用户在 WhatsApp Web 或桌面版上打开相同的聊天时,这些客户端会从服务器获取最新的 last_read_message_id,并相应地更新其本地视图,使得所有设备上的已读状态保持同步。
特殊情况和考量:
“关闭已读回执”功能: 如果用户在隐私设置中关闭了“已读回执”,其客户端仍然会更新本地已读状态,但不会向服务器发送已读回执事件。因此,消息的发送方永远不会看到蓝勾。
离线状态: 如果用户离线,已读状态更新会被服务器暂时缓存,直到用户上线后进行同步。
群聊的复杂性: 在群聊中,已读状态更加复杂,因为一条消息有多个接收者。WhatsApp 允许发送者查看群组中每个成员的详细阅读状态(通过长按消息选择“消息详情”)。这要求服务器端精确追踪每条消息对每个接收者的状态。
通过这种客户端-服务器协同的机制,WhatsApp 实现了消息的准确已读/未读状态管理和全球范围内的实时同步。
WhatsApp 是如何在数据库中标记已读/未读状态的?
-
- Posts: 270
- Joined: Thu Dec 26, 2024 5:46 am