使用了mongodb这么长时间,似乎遇到了瓶颈。本文通过几篇博客再次学习mongo,希望有新的认识。温故而知新~
MongoDB的主体认识:
- 高可用
- 分布式
- 灵活模式
- 文档数据库
传统关系模型(SQL)和文档模型的区别
文档模型的优点
- 读写效率高:Data Locality
- 可扩展能力强: 无关联易分库
- 动态模式:灵活应付不同的数据模式
- 模型自然:最接近于对象模型
MongoDB文档模式设计的基本策略
优先考虑内嵌,再去考虑引用
MongoDB设计模式原则
- 为应用程序服务,而不是为了存储优化
- 为实现最佳性能而设计
经典的模式设计案例
电商(ECommerce)
设计考量
- 一个购物车数据项不会太大,一般项数少于100
- 数据自动过期(15-30分钟无交互)
- 用冗余的方式来提供读取性能
参考数据模型
1 | { |
对模型的操作
添加商品到购物车
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16db.cart.update({
"_id": ObjectId("*")
}, {
$push:{
"items":{
"itemid": 2345,
"title": "Bread",
"price": 2.00,
"quantity": 1,
"img_url": "bread.jpg"
}
},
$set:{
"last_activity": ISODate()
}
})更新某个商品的数量
1
2
3
4
5
6
7
8
9
10db.carts.update({
"id": ObjectId("*")
"items.itemid": 4567
},{
$set:{
"item.$.quantity": 5,
"last_activity": ISODate()
}
}
)统计商品总数(聚合运算)
1
2
3
4
5
6
7
8
9
10db.cart.createIndex({"items.itemid": 1})
db.cart.aggregate(
{ $match: {"items.itemid": 8910}}, # 筛选出购物车里id为8910的商品
{ $unwind: "$items" }, # 展开items数组,每个数组的元素变成一个文档
{ $group: {
"_id": "$items.itemid",
"amount": { "$sum" : "$items.quantity" }
}
}#使用聚合运算$sum吧每一件商品的数量求和
)
社交(Social)
设计考量
- 维护朋友关系-关注、被关注
- 朋友圈设计、名人效应
经典文档设计的问题
1 | { |
如果TJ我是一个明星,他们关注我的人可能有千万。一个千万级的数组会有两个问题:
1.有可能超出一个文档最大16M的硬性限制; 2. MongoDB数组太大会严重影响性能。
解决方案是建立一个专门的集合来描述关注关系。
1 | > db.follower.find() |
微博墙的实现
微博墙:列表显示所有关注用户的最新状态
解决方案:
- 扇出读(常规玩法):当你需要去获得所有你关注用户的最新更新的时候,你就去到每一个你关注用户的数据区,把最新的一些数据取回来。[最慢服务器响应时间决定了总体的响应时间]
- 扇出写(土豪玩法):当被关注用户发布微博的时候,一条数据会写多次:直接写到每一个关注你的粉丝的墙上。[写入需求会被放大]
参考资料:
- MongoDB 进阶模式设计:http://www.mongoing.com/mongodb-advanced-pattern-design