Page 1 of 1

如何区分消息的发送者和接收者?

Posted: Tue May 20, 2025 11:00 am
by muskanislam99
在消息传递应用(如 WhatsApp)中,区分消息的**发送者(Sender)和接收者(Receiver)**是数据库设计和业务逻辑的核心。这不仅关系到谁能看到消息,还涉及到消息路由、状态更新和隐私控制。

1. 核心字段定义
要区分发送者和接收者,最直接和有效的方式是在**消息实体(Message)**的数据库表中,明确地定义相关字段。

以下是消息表中用于识别发送者和接收者的主要字段:

sender_id (发送者 ID):

这是一个外键,引用了 Users 表中的 user_id 主键。
它明确标识了发出这条消息的用户。
数据类型通常与 Users 表的主键类型一致(例如,BIGINT 或 UUID)。
receiver_id (接收者 ID):

这同样是一个外键,引用了 Users 表中的 user_id 主键。
它明确标识了这条消息的直接接收用户。
数据类型与 sender_id 相同。
重要说明: 对于一对一聊天,receiver_id 就是对方的 user_id。对于群聊,这个字段可能不存在或有特殊含义,因为群聊消息通常是广播给多个接收者的。
2. 一对一聊天消息的区分
对于一对一聊天,区分发送者和接收者非常直接:

当用户 A 发送消息给用户 B 时:
sender_id = 用户 A 的 user_id
receiver_id = 用户 B 的 user_id
当用户 B 回复用户 A 时:
sender_id = 用户 B 的 user_id
receiver_id = 用户 A 的 user_id
在客户端展示时,应用程序会根据当前登录用户的 user_id 来判断:

如果 sender_id 等于当前登录用户的 user_id,则这条消息是“我”发送的,显示在聊天界面的右侧(或发送气泡)。
如果 receiver_id 等于当前登录用户的 user_id(并且 sender_id 不是我),则这条消息是“我”接收的,显示在聊天界面的左侧(或接收气泡)。
3. 群聊消息的区分(更复杂)
群聊消息的区分略有不同,因为一条消息有一个发送者,但有多个接收者(即群内的所有成员)。

发送者: sender_id 字段仍然指向消息的实际发送者。

接收者: 对于群聊消息,通常不会 巴哈马 whatsapp 数据库 在消息表中存储一个单一的 receiver_id。取而代之的是:

group_id (群组 ID): 消息表中会有一个外键 group_id,引用 Groups 表的主键。这表明这条消息是发送到哪个群组的。
当消息到达服务器时,服务器会根据 group_id 查询 GroupMembers 表来获取群内所有成员的列表,然后将消息分发给这些成员的设备。
在消息的本地存储中,每条群聊消息的接收者都隐式地是该群的当前成员。
客户端展示:

对于群聊消息,客户端依然会根据 sender_id 来判断消息是否由“我”发送。
如果不是“我”发送的,客户端还会显示 sender_id 对应的用户名称或头像,让群成员知道是谁发了这条消息。
4. chat_id 或 conversation_id 的作用
为了更方便地管理和检索特定聊天会话的消息,通常还会引入一个 chat_id 或 conversation_id 字段:

一对一聊天: chat_id 可以由 sender_id 和 receiver_id 组合生成(例如,将两个 ID 排序后拼接或哈希化,确保对于 A-B 聊天和 B-A 聊天生成相同的 chat_id)。这样,通过一个 chat_id 就能查询出这个会话的所有消息。
群聊: chat_id 就是 group_id。
这个 chat_id 通常与 timestamp 一起作为复合索引,用于高效地加载某个聊天会话的消息历史。

5. 存储实践总结
综合来看,WhatsApp 可能会采用如下的消息表核心结构来区分发送者和接收者:

SQL

CREATE TABLE Messages (
message_id BIGINT PRIMARY KEY, -- 消息的唯一ID
chat_id BIGINT, -- 聊天会话ID (一对一或群组ID)
sender_id BIGINT NOT NULL, -- 消息发送者的用户ID (外键 Users.user_id)
-- 对于一对一聊天,receiver_id 存在;对于群聊,可能为 NULL 或指向特定的群组ID
-- 考虑到字段的通用性,可以将其设为可选,并依赖 chat_id 和 group_id 来区分
receiver_id BIGINT, -- 消息接收者的用户ID (外键 Users.user_id,一对一专用)
group_id BIGINT, -- 如果是群聊,则为群组ID (外键 Groups.group_id)
content BLOB, -- 加密后的消息内容或媒体URL
timestamp BIGINT NOT NULL, -- 毫秒级Unix时间戳
message_type VARCHAR(50) NOT NULL, -- 文本、图片、视频等
status VARCHAR(20) NOT NULL, -- SENT, DELIVERED, READ
-- 其他元数据...
-- FOREIGN KEY (sender_id) REFERENCES Users(user_id),
-- FOREIGN KEY (receiver_id) REFERENCES Users(user_id), -- 如果存在
-- FOREIGN KEY (group_id) REFERENCES Groups(group_id), -- 如果存在
INDEX idx_chat_time (chat_id, timestamp) -- 常用索引
);
通过这种设计,可以清晰地识别每条消息的来源(发送者),并根据 chat_id 和 group_id 判断其目的地(一对一聊天对象或群组),从而在数据库层面实现发送者和接收者的有效区分。