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


一、技术选型分析

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

  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存消息历史。
  • 表结构:规范化设计,结合缓存优化查询效率。
  • 扩展性:通过分库分表和微服务架构支持用户增长。
相关推荐
程序员爱钓鱼41 分钟前
Go语言实战案例-创建模型并自动迁移
后端·google·go
javachen__1 小时前
SpringBoot整合P6Spy实现全链路SQL监控
spring boot·后端·sql
uzong6 小时前
技术故障复盘模版
后端
GetcharZp7 小时前
基于 Dify + 通义千问的多模态大模型 搭建发票识别 Agent
后端·llm·agent
桦说编程7 小时前
Java 中如何创建不可变类型
java·后端·函数式编程
IT毕设实战小研7 小时前
基于Spring Boot 4s店车辆管理系统 租车管理系统 停车位管理系统 智慧车辆管理系统
java·开发语言·spring boot·后端·spring·毕业设计·课程设计
wyiyiyi7 小时前
【Web后端】Django、flask及其场景——以构建系统原型为例
前端·数据库·后端·python·django·flask
阿华的代码王国9 小时前
【Android】RecyclerView复用CheckBox的异常状态
android·xml·java·前端·后端
Jimmy9 小时前
AI 代理是什么,其有助于我们实现更智能编程
前端·后端·ai编程
AntBlack9 小时前
不当韭菜V1.1 :增强能力 ,辅助构建自己的交易规则
后端·python·pyqt