场景题:设计微信的双向好友添加/建群逻辑


一、技术选型分析

在设计类似微信的社交软件时,技术选型需要考虑以下几个关键点:

  1. 高并发支持:微信类应用用户量大,消息收发和群聊操作频繁,需要支持高并发读写。
  2. 实时性:好友状态更新、消息推送等需要低延迟。
  3. 扩展性:随着用户增长,系统需要水平扩展。
  4. 数据一致性与可靠性:好友关系和群聊数据需要保证一致性和持久化。

1. 后端技术栈

  • 语言与框架
    • Java + Spring Boot:Java生态成熟,Spring Boot提供快速开发能力,适合企业级应用。
    • Netty:用于实现高性能的实时通信(如消息推送),支持WebSocket协议。
  • 消息队列
    • KafkaRabbitMQ:用于异步处理消息发送、通知等高吞吐量任务。
  • 缓存
    • Redis:用于存储热点数据(如好友在线状态、群成员列表),提升查询性能。
  • 分布式架构
    • 微服务:将好友管理、群聊管理、消息服务拆分为独立模块,通过Spring Cloud或Dubbo实现服务间通信。

2. 数据库选择

  • 关系型数据库(如MySQL)
    • 适合存储结构化数据,如用户信息、好友关系表。
    • 优点:支持事务,数据一致性强,SQL查询灵活。
    • 缺点:高并发下性能可能成为瓶颈。
  • NoSQL数据库(如MongoDB或Cassandra)
    • 适合存储非结构化或半结构化数据,如群聊消息记录。
    • 优点:水平扩展能力强,适合高写吞吐量场景。
    • 缺点:一致性较弱,复杂查询支持有限。
  • 图数据库(如Neo4j)
    • 适合处理好友关系这种高度关联的数据。
    • 优点:查询关系链(如共同好友)效率高。
    • 缺点:不适合存储大量非关系数据,扩展性有限。
  • 综合选择
    • MySQL + Redis:MySQL作为主数据库存储核心数据,Redis作为缓存加速查询。
    • MongoDB:用于存储群聊消息历史记录。
    • Neo4j(可选):如果需要复杂的好友关系推荐功能,可以引入。

3. 其他组件

  • 负载均衡:Nginx或F5,用于分发请求。
  • 存储:对象存储(如AWS S3或MinIO)用于头像、群文件等。
  • 推送服务:基于WebSocket或第三方(如极光推送)实现实时通知。

二、功能需求分析

  1. 好友功能
    • 添加好友(双向验证)、删除好友、查看好友列表、好友状态(在线/离线)。
  2. 拉群功能
    • 创建群聊、邀请好友加入、退出群聊、查看群成员。

三、数据库表结构设计

以下基于MySQL设计表结构,结合Redis优化查询。

1. 用户表(users)

存储用户基本信息。

sql 复制代码
CREATE TABLE users (
    user_id BIGINT PRIMARY KEY AUTO_INCREMENT,  -- 用户ID
    username VARCHAR(50) NOT NULL UNIQUE,      -- 用户名
    nickname VARCHAR(50),                      -- 昵称
    avatar_url VARCHAR(255),                   -- 头像URL
    status TINYINT DEFAULT 0,                  -- 状态(0:离线, 1:在线)
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

2. 好友关系表(friends)

存储双向好友关系,采用双向记录以简化查询。

sql 复制代码
CREATE TABLE friends (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    user_id BIGINT NOT NULL,                   -- 用户ID
    friend_id BIGINT NOT NULL,                 -- 好友ID
    status TINYINT DEFAULT 0,                  -- 关系状态(0:待验证, 1:已通过)
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (user_id) REFERENCES users(user_id),
    FOREIGN KEY (friend_id) REFERENCES users(user_id),
    UNIQUE KEY (user_id, friend_id)            -- 避免重复关系
);
  • 优化 :在Redis中缓存用户的好友列表,如friends:user_id(Set结构)。

3. 群聊表(groups)

存储群聊基本信息。

sql 复制代码
CREATE TABLE groups (
    group_id BIGINT PRIMARY KEY AUTO_INCREMENT, -- 群ID
    group_name VARCHAR(100) NOT NULL,          -- 群名称
    owner_id BIGINT NOT NULL,                  -- 群主ID
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (owner_id) REFERENCES users(user_id)
);

4. 群成员表(group_members)

存储群成员关系。

sql 复制代码
CREATE TABLE group_members (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    group_id BIGINT NOT NULL,                  -- 群ID
    user_id BIGINT NOT NULL,                   -- 用户ID
    role TINYINT DEFAULT 0,                    -- 角色(0:普通成员, 1:管理员, 2:群主)
    joined_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (group_id) REFERENCES groups(group_id),
    FOREIGN KEY (user_id) REFERENCES users(user_id),
    UNIQUE KEY (group_id, user_id)             -- 避免重复加入
);
  • 优化 :在Redis中缓存群成员列表,如group_members:group_id(Set结构)。

5. 消息表(messages)

存储群聊消息(好友私聊类似,可单独建表)。

sql 复制代码
CREATE TABLE messages (
    message_id BIGINT PRIMARY KEY AUTO_INCREMENT,
    group_id BIGINT,                           -- 群ID(私聊可为空)
    sender_id BIGINT NOT NULL,                 -- 发送者ID
    content TEXT NOT NULL,                     -- 消息内容
    type TINYINT DEFAULT 0,                    -- 消息类型(0:文本, 1:图片, 2:文件等)
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (group_id) REFERENCES groups(group_id),
    FOREIGN KEY (sender_id) REFERENCES users(user_id)
);
  • 优化:历史消息迁移至MongoDB,按群ID分片存储,Redis存储最新N条消息。

四、核心功能实现逻辑

1. 添加好友

  • 流程

    1. 用户A发送好友请求给用户B,插入friends表(status=0)。
    2. 用户B同意后,更新status=1,并插入反向记录(B->A)。
    3. 更新Redis缓存。
  • SQL示例

    sql 复制代码
    INSERT INTO friends (user_id, friend_id, status) VALUES (1, 2, 0);
    UPDATE friends SET status = 1 WHERE user_id = 1 AND friend_id = 2;
    INSERT INTO friends (user_id, friend_id, status) VALUES (2, 1, 1);

2. 创建群聊并拉人

  • 流程

    1. 创建群:插入groups表,群主加入group_members(role=2)。
    2. 拉人:批量插入group_members表。
    3. 更新Redis缓存。
  • SQL示例

    sql 复制代码
    INSERT INTO groups (group_name, owner_id) VALUES ('群聊1', 1);
    INSERT INTO group_members (group_id, user_id, role) VALUES (1, 1, 2);
    INSERT INTO group_members (group_id, user_id) VALUES (1, 2), (1, 3);

3. 查询好友列表

  • 从Redis读取friends:user_id,若无则查MySQL并回写Redis。

  • SQL

    sql 复制代码
    SELECT friend_id FROM friends WHERE user_id = 1 AND status = 1;

4. 查询群成员

  • 从Redis读取group_members:group_id,若无则查MySQL。

  • SQL

    sql 复制代码
    SELECT user_id, role FROM group_members WHERE group_id = 1;

五、性能优化与扩展

  1. 分库分表
    • 用户表按user_id哈希分片。
    • 群聊表按group_id分片。
  2. 索引优化
    • friends表加(user_id, status)复合索引。
    • group_members表加(group_id, user_id)索引。
  3. 缓存策略
    • 热点数据(如在线状态、群成员)存Redis,设置TTL。
    • 冷数据定期归档至MongoDB。
  4. 分布式锁
    • 用Redis实现添加好友、拉群时的并发控制。

六、总结

  • 技术选型:Java + Spring Boot + MySQL + Redis + MongoDB,兼顾性能与扩展性。
  • 数据库:MySQL存储核心关系数据,Redis加速查询,MongoDB存消息历史。
  • 表结构:规范化设计,结合缓存优化查询效率。
  • 扩展性:通过分库分表和微服务架构支持用户增长。
相关推荐
uhakadotcom17 分钟前
快速构建交互式数据应用:Streamlit入门指南
后端·面试·github
无名之逆43 分钟前
hyperlane:Rust HTTP 服务器开发的不二之选
服务器·开发语言·前端·后端·安全·http·rust
机构师1 小时前
<iced><rust><GUI>基于rust的GUI库iced的学习(02):svg图片转png
后端·rust
老赵骑摩托1 小时前
Go语言nil原理深度解析:底层实现与比较规则
开发语言·后端·golang
卑微小文1 小时前
惊!代理 IP 竟成社交媒体营销破局“神助攻”!
后端
程序员爱钓鱼1 小时前
Go 语言邮件发送完全指南:轻松实现邮件通知功能
后端·go·排序算法
Cloud_.1 小时前
Spring Boot整合Redis
java·spring boot·redis·后端·缓存
海狸鼠2 小时前
几行代码实现MCP服务端/客户端(接入DeepSeek)
前端·后端
37手游后端团队2 小时前
10分钟读懂RAG技术
人工智能·后端
Moment2 小时前
岗位急招,算法实习、音乐生成、全栈、flutter 都有,早十晚六 😍😍😍
前端·后端·面试