深入理解MongoDB

这是在我看完《深入理解MongoDB》后,按照自己的理解记录下来的笔记,初次接触,若有错误,敬请指出,感谢!


一.概述

MongoDB 是一个基于分布式文件存储的数据库。由 C++ 语言编写。旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。
MongoDB操作模式:
应用程序<=>mongos<=>集群

二.理解分片

1.什么是分片(sharding)?

分片(sharding)是MongoDB用来将大型集合分割到不同服务器上采用的方法。这样做是为实现3个目标:

让集群“不可见”

让应用程序知道要执行任何“增删改查”操作只需要发送请求给MongoDB这一个对象就行了,剩下的事就交给它了,不需要区分交给那个服务器,简化了应用程序端操作指令。在MongoDB中具体连接客户端与服务器端的就是叫做mongos的专有路由进程,mongos可以比喻为一个秘书,转发客户端的请求,和服务器端的响应。

保证集群总是可以读写

一个大的集合分为多个分片(shard),当其中一个进程/服务器出现问题,由运行在其他分区的其他副本接替换掉的部分继续工作。

使集群易于扩展

将大的集群分割为多个小的分区,当需要资源的时候,只需要添加小的空间。

2.分配数据

sharding操作后得到分片(shard)是集群中负责数据某一子集的一台或多台服务器。换言之,一个分片包含数据的某个子集。例如一个集群包含1000份代表网站注册用户文档,其中一个分片就可能包含200份。
若一个分片包含多个服务器,则每个服务器拥有一份完整的数据副本。

一分片一区间

分配数据最简单的方法就是让一分片负责一区间的数据。假设有四个分片,依次对应["a","f"),["f","n"),["n","t"),["t","{")区间,{是ASCII码表中字母z后面的字符。许多用户用首字母在范围["a","f")中的名字来注册,就导致分片1较大,我们可以调整区间使分片1对应的区间缩小,从而让分片均衡。但当分片1和分片2过载时,就不太好处理。假设分片1和分片2各有500G数据,分片3和分片4各有300G数据,此时就需要分片1转移100G数据到分片2,接着从分片2转移200G数据到分片3,最后分片3转移100G数据到分片4,从而使每个分片都具有400G数据,达到均衡。这还只是4个分片,执行这个操作一共移动了400G数据。当考虑到所有分片,可想需要移动的数据量是很大的。

一分片多区间

重新来考虑上面的情况,此时是一分片多区间。我们可以把分片1和分片2都划分为两个区间,分片1分别对应包含400G数据的["a","d")区间和包含100G数据的["d","f")区间,分片2分别对应包含400G数据["f","j")区间和100G数据["j","n")区间。我们就可以把分片1中的["d","f")区间的数据直接移动到分片3,把分片2中的[",j","n")区间的数据直接移动到分片4,相比上一种情况,只需要移动200G数据。添加新的分片也具有同样的优势——减少数据转移量。

创建块

一个区间的数据成为一个数据块(也叫块,chunk),块默认大小为200MB(兼顾可移动性和最小开销),当一个块的区间一分为二是,就变成两个块了。当提到块出不得不说片键了,如下所示
{"username":"gala","age":21}
{"username":"pinocchio","age":25}
{"username":"zaizizaizai","age":16}
如果我们选择age字段作为片键病得到一个块区间[20,30),则得到的块为:
{"username":"gala","age":21}
{"username":"pinocchio","age":25}
可以把片键理解为一个选择器(标签),也可理解为属性,即挑选符合条件的数据,在这里不仅局限于把age作为片键,username也可以作为片键,且片键值不可修改。
随着数据的增加,当一个块变大,MongoDB会自动将其分割为2个小块。若分片间数据比例失衡,MongoDB会迁移块其他分片(由叫做平衡器的进程执行),以达到分片间数据比例总是平衡的状态。同时平衡器会忽略微小的不平衡,否则会导致恶性循环。

三.建立集群

选择片键

片键的选择很重要,因为这关系到读操作的速度。以下介绍集中片键的几个常见反例,以便更好理解片键选择。

小基数片键

假设我们有3个分片,我们需要选择片键。前后端编程开发常见的建站就需要对数据分类,有用户的数据、管理员的数据、网页参数的数据,那为了方便理解和区分,就选择用户、管理员、网页参数3个片键。虽然管理员数据比较小,但用户的数据会一直增加,增加到一定程度后,MongoDB也不能分割分片里的块了,最终磁盘空间被耗尽。由于片键值数量有限,后来,就会得到一个又大又无法移动,还不能分割的块,这对数据管理造成极大的不方便。

升序片键

对大部分应用程序而言,新数据被访问的次数总是多于老数据,所以人们会尝试诸如时间戳或者objectID一类的字段作为片键。比如,社交软件上的发动态,每条动态包含消息、地点、时间,我们以时间段来分片。从一个数据块开始,随着时间推移,一个块满了,裂变为两个块,时间点继续增加,这个片键创造了一个单一且不可分散的热点。动态被发出,该时间点MongoDB需要对该时间点对应的块进行写操作,而当大量的动态在同一时间发出,MongoDB来不及对块进行写操作,就会造成堵塞,使应用程序瘫痪。

随机片键

为了避免以上的热点片键,有人选择取随机的字段来分片。采用这种字段开始还不错,但随着数据量的增加,它会变得越来越慢。现在采用随机片键,已经得到一组均匀分布于各分片的数据块。假设分片上的一个块填满并分裂了,配置服务器注意到分片2比分片1多10个块,为了抹平差距,MongoDB就将分片2中的随机5个块(块的数据量的大小不确定)经由内存发送给分片1。随着数据量的增加,这5个随机的块的数据量会很大,应发大量的磁盘IO,致使数据库变慢。

好片键

准升序键加搜索键

快速起步

若想尽快上手,可用Github上的mongos-snippets,其中有个simple-setup.py能自动地启动、配置和生成一个集群,它需要MongoDB的Python驱动。

安装MongoDB的Python驱动

sudo easy_install pymongo

下载mongos-snippets库并执行以下操作

python sharding/simple-setup.py --path=绝对路径


simple-setup.py会启动一个mongos进程,地址为localhost://27017


2017.10.29       pinocchio


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值