MongoDB中类Instagram社交应用粉丝关注模块Schema设计咨询
社交应用关注关系模块Schema设计方案解答
现有设计可行性判断
你当前采用的独立followers集合存储关注关系的设计,属于典型的多对多关系建模方案,逻辑清晰,增删改查实现简单,在中小流量规模下完全可以正常使用。
你计算的万亿级记录属于极端理论值:现实场景中99%的普通用户粉丝/关注量均在一万以下,仅头部账号会有百万、千万级粉丝,真实业务的记录规模会远低于你计算的数值。但如果确实要对标Instagram的亿级用户体量,单集合存海量记录确实会遇到查询性能下降、存储成本高、分片运维压力大的问题。
优化设计思路
1. 保留现有结构,做性能优化(最低成本方案)
无需修改现有Schema,只需要做两处调整即可支撑千万级用户规模:
- 新增联合唯一索引:分别给
{followeeId: 1, followerId: 1}和{followerId: 1, followeeId: 1}加唯一索引,前者用于快速查询某用户的粉丝列表、判断是否被某用户关注,后者用于快速查询某用户的关注列表、判断是否关注了某用户,同时可以避免重复插入相同的关注关系。
索引创建语句参考:db.followers.createIndex({ followeeId: 1, followerId: 1 }, { unique: true }) db.followers.createIndex({ followerId: 1, followeeId: 1 }, { unique: true }) - 数据量达到千万级以上后,对followers集合做分片存储,分片键选择
followeeId即可,将大集合打散到多个分片节点,解决单集合容量和查询性能瓶颈。
2. 冷热分离存储(中大规模推荐方案)
在users集合中新增两个数组字段,存储普通用户的关注/粉丝ID:
module.exports = mongoose.model('users', new Schema({ // 原有字段保持不变 followings: { type: [ObjectId], default: [], select: false }, // 存储关注的用户ID,上限可设置为5000 followers: { type: [ObjectId], default: [], select: false }, // 存储粉丝ID,上限可设置为5000 hasExtFollowData: { type: Boolean, default: false } // 标记粉丝/关注数是否超过阈值,需要到followers集合查询 }, { versionKey: false, timestamps: true }));
99%的普通用户的粉丝/关注数不会超过阈值,可以直接从用户文档读取数据,无需跨表查询,性能提升非常明显。只有头部账号这类热数据才需要到独立的followers集合查询,冷数据(比如超过2年的历史关注关系)可以归档到廉价存储,进一步降低成本。
3. 分库分表(超大规模方案)
如果用户量达到亿级以上,可以将follow关系集合按用户ID哈希分表,比如拆分为1024张独立的follow表,按followerId的哈希值分配到对应表中,彻底打散海量数据,解决单集合存储上限问题。
选型建议
产品早期阶段直接用你现有的原始方案即可,逻辑简单开发成本低,没有必要提前做过度设计。等用户量突破百万级之后再逐步做索引优化、分片、冷热分离调整完全来得及。
内容的提问来源于stack exchange,提问作者Abhishek Pankar
相关产品推荐
相关产品推荐

