
1) 【一句话结论】社交平台用户关系数据通过关系表存储,主键设计为用户ID、目标用户ID、关系类型三字段组合,支持动态变更(如拉黑)时仅更新状态字段,结合联合索引优化查询,并需通过分库分表和事务机制保障高并发下的数据一致性与性能。
2) 【原理/概念讲解】用户关系属于多对多关系(如A关注B、A好友B),关系表需存储关系类型(关注/好友)和状态(正常/拉黑)。主键设计为(user_id, target_id, type),确保唯一性,避免数据冲突。状态字段用于动态变更,如拉黑时更新status为blocked,无需删除再插入,减少锁竞争。索引方面,为快速查询某用户的关系,建立(user_id, type, status)联合索引;为查询关注者/被关注者,建立(target_id, type)索引。分库分表时,按user_id哈希分片,避免热点分片(如热门用户数据集中一个分片),提高查询效率。事务层面,采用乐观锁(如版本号)或分布式事务(Saga模式),确保拉黑操作与数据一致性。
3) 【对比与适用场景】
| 模型 | 定义 | 特性 | 使用场景 | 注意点 |
|---|---|---|---|---|
| 关系型数据库(关系表存储) | 用关系表存储用户关系,主键为用户ID+目标ID+类型 | 支持ACID事务,索引高效,适合高并发写和复杂查询(如好友推荐) | 用户量较大(百万级以上),关系查询频繁(如实时好友列表) | 需设计合理索引,避免表过大导致查询慢;动态变更时需优化操作(如状态更新而非删除插入) |
| 图数据库(如Neo4j) | 用节点(用户)和边(关系)表示用户和关系 | 查询灵活,适合复杂路径分析(如共同好友、社交圈路径) | 社交网络分析、推荐算法(如基于路径的推荐) | 写性能可能低于关系型,成本较高;不适合高并发写场景;查询复杂但效率高 |
4) 【示例】
id (PK), username, ...id (PK), user_id (FK), target_id (FK), type (ENUM: follow/friend), status (ENUM: normal/blocked), create_time (TIMESTAMP), version (INT) [用于乐观锁]SELECT target_id FROM relations WHERE user_id = ? AND type = 'friend' AND status = 'normal'UPDATE relations SET status = 'blocked', version = version + 1 WHERE user_id = ? AND target_id = ? AND type = 'friend' AND version = ? (检查版本号是否一致,确保原子性)5) 【面试口播版答案】面试官您好,用户关系是典型的多对多关系,通常用关系表存储。比如设计用户表和关系表,关系表包含用户ID、目标用户ID、关系类型(关注/好友)、状态(正常/拉黑)。为了支持动态变更,比如拉黑,只需更新状态字段,避免删除再插入,减少锁竞争。查询优化方面,为快速查询某用户的关系,建立(user_id, type, status)联合索引;为查询关注者或被关注者,建立(target_id, type)索引。这样,拉黑好友后,通过状态过滤即可快速获取正常好友列表,同时通过分库分表(按user_id哈希分片)和乐观锁保证数据一致性与高并发性能。
6) 【追问清单】
7) 【常见坑/雷区】