为什么我们选择了MongoDB?( 二 )

为什么我们选择了MongoDB?
文章插图
 
有以下几种情况:

  • 写 Primary 成功,返回客户端写成功,Secondary 还未同步 Primary 的时候,Primary 挂了,数据丢失!
  • 写 Primary 成功,数据同步一个 Secondary 成功,返回客户端写成功 。此时 Primary 挂了,数据不会丢失 。但是恰好 Primary 与同步的 Secondary 同时挂了,数据丢失!
  • 写 Primary 成功,数据同步两个 Secondary 成功,返回客户端写成功 。此时 Primary 挂了,数据不会丢失 。
我们对以上三种情况进行分析:
  • 第一种情况有风险会造成数据丢失 。
  • 第二种情况还是会出现数据丢失,但是数据丢失的概率大大降低 。
  • 第三种情况是最安全的做法,但是节点数目多了,同步非常耗时,用户需要等待的时间过长,一般不考虑 。
MongoDB 在这里推荐折衷方案就是使用 Write Concern---在数据可靠性与效率之间的权衡!
db.products.insert({ item: "envelopes", qty : 100, type: "Clasp" },{ writeConcern: { w: "majority" , wtimeout: 5000 } }// 设置writeConcern为majority,超时时间为5000毫秒 ) MongoDB 分片
①大规模数据是如何影响数据库效率的?
  • 数据库的性能还与数据库本身规模息息相关 。拿关系型数据库举例:
  • 查询百万表和千万表甚至过亿的表效率相差很大,查询性能急剧恶化 。
插入的时候创建索引可能会引起索引树的调整与页分裂 。
②面对海量数据如何提升数据读写效率?
为了在海量数据中提升数据库的效率,我们采用分而治之的思想,将大表拆成小表,大库拆成小库 。
关系型数据库中我们常用分表分库来解决:
  • 例如将订单库分为在线库和离线库,近三个月是在线库,远期的订单数据放入离线库,这样在线库的数据就大大减少,数据库性能就得到了提升 。
  • 又例如当我们的用户量过多超过千万行记录,单表查询效率下降,我们将一张用户表拆成多张用户表,这个就是水平拆分 。
MongoDB 中我们是如何做的呢?
③MongoDBSharding
为什么我们选择了MongoDB?

文章插图
 
MongoDB 的分片
通过将同一个集合(Collection1)的数据按片键(shard keys)分到不同的分片(shard)上面,减少同一个数据文件上的数据量,已达到拆分数据规模的目的 。
为什么我们选择了MongoDB?

文章插图
 
Shard 优势:在线扩容,动态扩容
Shard:用于存储实际的数据块,实际生产环境中一个 shard server 角色可由几台机器组个一个 replica set 承担,防止主机单点故障 。
Config Server:配置服务器 mongodb 实例,存储了整个集群的元数据与配置,其中包括 chunk 信息,在 MongoDB 3.4 中,配置服务器必须部署为一个副本集 。
Mongos:mongos 充当查询路由器,提供客户端应用程序和切分集群之间的接口 。
服务器插入的数据通过 Mongos 路由到具体地址,这也是 MongoDB 的便利之处,不需要自己关注路由,也不需要使用第三方提供的中间件辅助路由,可靠,放心 。
为什么我们选择了MongoDB?

文章插图
 
分片的负载均衡
当我们的 MongoDB 副本集变成分片集群后,随着数据量的增长,各个分片也会越来越大 。
这里就会出现两种情况:
  • 冷热数据,某个分片数据量过大 。
  • 数据总量大,分片集群的分片过大 。
当出现问题(1)的时候,MongoDB 的负载均衡器(Balancer)会自动将大分片中的数据迁往小分片 。
注意这并不意味我们可以高枕无忧了,恰恰相反,我们应该反思是不是自己片键选择失误而造成的数据不均匀!
因为对分片迁移也是消耗性能的,应用服务器写一次到 Shard B,然后 Shard B 重写到 Shard C 无形之中数据被写了两次,这是极大的浪费!
当出现问题(2)的时候,当然是给过大的分片集合添加新的分片以此分摊分片集群的压力 。
注意:MongoDB 分片虽然是可在线的,但是多少都会对正常的读写操作性能有一定的影响,建议在非繁忙时间段进行分片部署!
MongoDB 文档模型介绍
数据库建模的挑战在于平衡应用的需要,适合该数据库引擎发挥的结构以及数据的检索模式 。
当我们设计数据模型的时候,需要考虑应用使用数据的情况(查询,更新,和数据处理)以及该数据本身的结构 。


推荐阅读