[mongo]MongoDB 文档事物开发最佳实践

MongoDB 文档事物开发最佳实践

连接到 MongoDB

  • 连接到复制集
    • mongodb://节点1,节点2,节点3…/database?[options]
  • 连接到分片集
    • mongodb://mongos1,mongos2,mongos3…/database?[options]

常见连接字符串参数

  • maxPoolSize
    • 连接池大小
  • Max Wait Time
    • 建议设置,自动杀掉太慢的查询
  • Write Concern
    • 建议 majority 保证数据安全
  • Read Concern
    • 对于数据一致性要求高的场景适当使用

连接字符串节点和地址

  • 无论对于复制集或分片集,连接字符串中都应尽可能多地提供节点地址,建议全部
    列出

    • 复制集利用这些地址可以更有效地发现集群成员
    • 分片集利用这些地址可以更有效地分散负载
  • 连接字符串中尽可能使用与复制集内部配置相同的域名或 IP

使用域名连接集群

  • 可以为集群变更时提供一层额外的保护
  • MongoDB 提供的 mongodb+srv:// 协议可以提供额外一层的保护
    • 该协议允许通过域名解析得到所有 mongos 或节点的地址,而不是写在连接字符串中
    mongodb+srv://server.example.com/
Record TTL Class Priority Weight Port Target _mongodb._tcp.server.example.com. 86400
IN SRV 0 5 27317 mongodb1.example.com.
_mongodb._tcp.server.example.com. 86400 IN SRV 0 5 27017 mongodb2.example.com. 
  • Record TTL:该记录的生存时间(Time-To-Live),单位为秒;在这个例子中,记录的生存时间为 86400 秒(即 24 小时)
  • Class:记录的类型,通常为 IN(Internet)
  • Priority:优先级,用于指定备用服务器的顺序。在这个例子中,优先级为 0,表示这些服务器都具有相同的优先级
  • Weight:权重,用于指定备用服务器的比例。在这个例子中,权重为 5,表示这些服务器的比例相同
  • Port:服务器的端口号。在这个例子中,服务器的端口号分别为 27317 和 27017
  • Target:服务器的主机名。在这个例子中,服务器的主机名分别为 mongodb1.example.com 和 mongodb2.example.com
  • _mongodb._tcp.server.example.com.:SRV 记录的名称,格式为 _服务类型._协议.域名。在这个例子中,服务类型为 _mongodb,表示 MongoDB 服务,协议为 _tcp,表示使用 TCP 协议,域名为 server.example.com

不要在 mongos 前面使用负载均衡

  • 如果再mongos前边做了负载均衡会出现如下问题:

    • 驱动会无法探测具体哪个节点存活,从而无法完成自动故障恢复
    • 驱动会无法判断游标是在哪个节点创建的,从而遍历游标时出错
  • 不要在 mongos 或复制集上层放置负载均衡器,让驱动处理负载均衡和自动故障恢复

游标使用

  • 如果一个游标已经遍历完,则会自动关闭
  • 如果没有遍历完,则需要手动调用 close()方法
    • 否则该游标将在服务器上存在 10 分钟(默认值)后超时释放,造成不必要的资源浪费
    • 如果不能遍历完一个游标,通常意味着查询条件太宽泛,更应该考虑的问题是
      如何将条件收紧

关于查询及索引

  • 每一个查询都必须要有对应的索引
  • 尽量使用覆盖索引 Covered Indexes (可以避免读数据文件)
  • 使用 projection 来减少返回到客户端的的文档的内容

关于写入

  • update 语句里只包括需要更新的字段
  • 尽可能使用批量插入来提升写入性能
  • 使用TTL自动过期日志类型的数据

关于文档结构

  • 防止使用太长的字段名(浪费空间)
  • 防止使用太深的数组嵌套(超过2层操作比较复杂)
  • 不使用中文,标点符号等非拉丁字母作为字段名

处理分页问题 – 避免使用 count

  • 尽可能不要计算总页数,特别是数据量大和查询条件不能完整命中索引时
//只需要遍历前 n 条,直到找到 50 条队伍 x=100 的文档即可结束
db.coll.find({x: 100}).limit(50);
//需要遍历完 1000w 条找到所有符合要求的文档才能得到结果
db.coll.count({x: 100});

处理分页问题 – 巧分页

  • 避免使用skip/limit形式的分页,特别是数据量大的时候
  • 替代方案:使用查询条件+唯一排序
第一页:db.posts.find({}).sort({_id: 1}).limit(20);
第二页:db.posts.find({_id: {$gt: <第一页最后一个_id>}}).sort({_id: 1}).limit(20);
第三页:db.posts.find({_id: {$gt: <第二页最后一个_id>}}).sort({_id: 1}).limit(20);

关于事务

  • 原则
    • 无论何时,事务的使用总是能避免则避免
    • 模型设计先于事务,尽可能用模型设计规避事务
    • 不要使用过大的事务(尽量控制在 1000 个文档更新以内)
    • 当必须使用事务时,尽可能让涉及事务的文档分布在同一个分片上,这
      将有效地提高效率
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值