【进阶篇】用户关系链存储方案:MySQL够用吗?图数据库何时引入

2 阅读5分钟

用户关系链是社交App的核心资产。关注、好友、粉丝、屏蔽,这些关系数据的设计直接影响用户体验和系统性能。什么时候用MySQL?什么时候需要图数据库?这篇文章帮你理清决策逻辑。

一、关系链的业务场景

1.1 常见关系类型

关系类型说明特点
单向关注A关注B,B不一定关注A微博模式
双向好友A和B互为好友微信模式
粉丝关系单向关注的特殊命名博主模式
黑名单/屏蔽单向阻止负向关系
分组关系好友分到不同组朋友圈分组可见

1.2 核心查询场景

查询说明频率
我关注了谁A的following列表
谁关注了我A的followers列表
我和TA是什么关系A是否关注B极高
共同关注A和B都关注了谁
二度关系我关注的人关注了谁
好友推荐可能认识的人

二、MySQL方案:适合大多数场景

2.1 表结构设计

基础方案:关系表

CREATE TABLE user_relation (  
    id BIGINT PRIMARY KEY AUTO_INCREMENT,  
    user_id BIGINT NOT NULL COMMENT '用户ID',  
    target_id BIGINT NOT NULL COMMENT '目标用户ID',  
    relation_type TINYINT NOT NULL COMMENT '关系类型:1-关注 2-好友 3-屏蔽',  
    status TINYINT DEFAULT 1 COMMENT '状态:1-正常 0-删除',  
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,  
    INDEX idx_user_target (user_id, target_id),  
    INDEX idx_target_user (target_id, user_id)  
) ENGINE=InnoDB;

优化方案:分表存储

-- 关注表(我关注的人)  
CREATE TABLE user_following (  
    user_id BIGINT NOT NULL,  
    target_id BIGINT NOT NULL,  
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,  
    PRIMARY KEY (user_id, target_id),  
    INDEX idx_target (target_id)  
);  
  
-- 粉丝表(关注我的人)  
CREATE TABLE user_follower (  
    user_id BIGINT NOT NULL,  
    target_id BIGINT NOT NULL COMMENT '粉丝ID',  
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,  
    PRIMARY KEY (user_id, target_id),  
    INDEX idx_target (target_id)  
);

2.2 查询优化

场景1:查询关注列表

-- 查询A关注的人  
SELECT target_id FROM user_following  
WHERE user_id = ?  
ORDER BY created_at DESC  
LIMIT 20;

场景2:查询粉丝列表

-- 查询A的粉丝  
SELECT target_id FROM user_follower  
WHERE user_id = ?  
ORDER BY created_at DESC  
LIMIT 20;

场景3:判断A是否关注B

-- 高频查询,走主键索引,性能极快  
SELECT 1 FROM user_following  
WHERE user_id = ? AND target_id = ?;

场景4:查询共同关注

SELECT a.target_id  
FROM user_following a  
INNER JOIN user_following b ON a.target_id = b.target_id  
WHERE a.user_id = ? AND b.user_id = ?;

2.3 MySQL方案的适用范围

指标MySQL表现
单用户关系数<10000条,无压力
查询「是否关注」极快(主键查询)
查询关注列表快(索引覆盖)
查询共同关注较慢(JOIN操作)
查询二度关系很慢(多层JOIN)
关系链分析不适合

结论:  用户关系数<1万、查询场景简单时,MySQL足够用。

三、什么时候需要图数据库

3.1 图数据库的优势

图数据库天生适合处理「关系」:

特性MySQL图数据库
数据模型表 → 行节点 → 边
关系查询JOIN,多层JOIN性能差遍历,原生支持
路径查询复杂SQL,性能差简单查询,性能好
实时推荐不擅长擅长

3.2 什么时候该用图数据库

判断标准: 是否需要以下场景?

1、关系查询(朋友的朋友)  
是 → 考虑图数据库  

2、实时好友推荐  
是 → 考虑图数据库  

3、关系链分析(影响力计算、社区发现)  
是 → 必须图数据库  

4、共同好友查询频繁  
是 → 考虑图数据库  

5、用户关系数>10万  
是 → 考虑图数据库

3.3 主流图数据库对比

数据库特点适用场景
Neo4j成熟稳定,社区活跃,Cypher查询语言企业级应用
JanusGraph开源,可扩展,基于HBase/Cassandra大规模图数据
TigerGraph高性能,分布式实时分析
Nebula Graph国产开源,分布式,高性能大规模社交网络
ArangoDB多模型(文档+图)灵活需求

四、图数据库实战:Neo4j示例

4.1 数据模型

(User)-[:FOLLOWS]->(User)

4.2 创建关系

// 创建用户节点  
CREATE (u1:User {id: 1, name: 'Alice'})  
CREATE (u2:User {id: 2, name: 'Bob'})  
CREATE (u3:User {id: 3, name: 'Charlie'})  
  
// 创建关注关系  
MATCH (u1:User {id: 1}), (u2:User {id: 2})  
CREATE (u1)-[:FOLLOWS]->(u2)

4.3 查询示例

查询A关注的人:

MATCH (u:User {id: 1})-[:FOLLOWS]->(target)  
RETURN target.id, target.name

查询共同关注:

MATCH (u1:User {id: 1})-[:FOLLOWS]->(common)<-[:FOLLOWS]-(u2:User {id: 2})  
RETURN common.id, common.name

查询二度关系(朋友的朋友):

MATCH (u:User {id: 1})-[:FOLLOWS]->()-[:FOLLOWS]->(fof)  
WHERE NOT (u)-[:FOLLOWS]->(fof)  
RETURN fof.id, fof.name, count(*) AS mutual_friends  
ORDER BY mutual_friends DESC  
LIMIT 10

好友推荐(基于共同好友数):

MATCH (u:User {id: 1})-[:FOLLOWS]->()-[:FOLLOWS]->(recommend)  
WHERE NOT (u)-[:FOLLOWS]->(recommend)  
RETURN recommend.id, recommend.name, count(*) AS score  
ORDER BY score DESC  
LIMIT 10

五、混合方案:MySQL + 图数据库

5.1 架构设计

写入流程:
用户A关注B

├── 写入MySQL(主数据源)

└── 同步到图数据库(异步)

查询流程:
├── 简单查询(关注列表、是否关注)→ MySQL
└── 复杂查询(推荐、共同好友)→ 图数据库

5.2 数据同步方案

方案1:双写

写入时同时写MySQL和图数据库
优势:实时性好
劣势:一致性难保证,任一失败需要补偿

方案2:消息队列异步同步

写入MySQL → 发送消息到MQ → 消费者写入图数据库
优势:解耦,可靠
劣势:有一定延迟

方案3:CDC同步

MySQL binlog → Debezium → 图数据库
优势:对业务无侵入
劣势:技术复杂度高

六、性能对比实测

测试环境:

· 用户数:100万

· 平均关注数:200

· 最大关注数:5000

查询:「共同关注」

方案耗时
MySQL(JOIN)500ms
MySQL(子查询)300ms
Neo4j50ms
Nebula Graph30ms

查询:「好友推荐」(二度关系)

方案耗时
MySQL2000ms+
Neo4j100ms
Nebula Graph50ms

七、选型决策总结

你的需求场景是?  
1、简单社交(<1万关系/用户)  
   MySQL足够,没必要上图数据库  

2、中等规模(1万-10万关系/用户)  
   > 需要推荐功能 → MySQL + 图数据库  
   > 不需要推荐 → MySQL  

3、大规模社交(>10万关系/用户)  
   MySQL + 图数据库(混合方案)  

4、关系链分析需求  
   必须图数据库

下篇预告:  《社交App的离线消息、消息漫游、多端同步设计》——用户体验的关键细节,一个都不能少。

持续输出社交App开发实战经验,关注我,一起成长。