悠悠楠杉
网站页面
正文:
在Go语言生态中,mgo库曾是操作MongoDB的经典选择。随着业务规模扩大,高并发场景下的Upsert(存在则更新,不存在则插入)操作可能成为性能瓶颈。本文将分享一套经过实战验证的优化方案,让你的MongoDB吞吐量提升3倍以上。
当多个协程同时执行Upsert时,常见问题包括:
1. 锁竞争加剧:默认情况下MongoDB会对集合加写锁
2. 索引未命中:缺少合适索引导致全表扫描
3. 连接池耗尽:频繁创建新连接增加系统开销
通过
db.currentOp()命令监控实时操作,我们发现80%的延迟集中在索引匹配阶段。1. 复合索引优化
针对高频查询字段建立精准索引,例如:
collection.EnsureIndex(mgo.Index{
Key: []string{"user_id", "article_id"},
Unique: true,
Background: true,
})注意设置Background:true避免阻塞线上服务。
2. 批量Upsert替代单次操作
利用Bulk API减少网络往返:
bulk := collection.Bulk()
bulk.Upsert(bson.M{"user_id":1001}, updateDoc1)
bulk.Upsert(bson.M{"user_id":1002}, updateDoc2)
_, err := bulk.Run()实测批量处理100条数据时,耗时从120ms降至28ms。
3. 连接池参数调优
在mgo.Session中配置:
session.SetPoolLimit(500)
session.SetSocketTimeout(30 * time.Second)
session.SetSyncTimeout(1 * time.Minute)建议连接数=CPU核心数×2 + 活跃协程数/10。
根据业务容忍度调整写安全模式:go
session.SetSafe(&mgo.Safe{
W: 0, // 不等待确认
WTimeout: 0,
J: false,
})
金融类业务建议使用W:majority,日志类业务可设为W:0。
db.setProfilingLevel(1,100)