分片是指数据拆分 将其分散在不同的机器上的过程,有时候也叫分区来表示这个概念.将数据分散到不同机器上 不需要功能强大的计算机就可以储存更多的数据,处理更大的负载.
几乎所有的数据库都能手动分片 应用程序需要维护与若干不同数据库服务器的连接,每个连接都是独立的 应用程序给I案例不同服务器上不同数据的存储,还管理在合适的数据库上查询的工作,这种方法能够很好的工作,但是难以维护 不如想集群添加节点 或者从集群删除节点都很困难 调整数据分布和负载模式也不轻松.
MongoDB支持自动分片,可以使用数据库架构对应用程序不可见,可以简化系统管理,对应用程序而言,就像连接的一台但是mongod服务器一样,MongoDB自动处理数据在分布上的分布.也更容易添加和删除分片.
MongoDB的分片机制允许你创建一个包含许多台机器的集群,将数据的子集合分散在集群中,每个分片维护着一个数据集合的子集.与单机服务器和副本集相比,使用集群架构可以使应用程序具有更大的数据处理能力.
首先要准备三台 可以互相通信的的服务器 作为配置服务器 配置服务器是集群的大脑 保存着几区和发呢鬼片的元数据 即个分片包含哪些数据信息. 因此要首先建立配置服务器 鉴于他极端的重要性 必须启用日志功能 并确保其数据保存在非易失性去驱动器上
因为mongos需要从配置服务器获取配置信息 因此配置服务器应该先于任何mongos进程启动 配置服务器是独立的mongod进程 可以想见简单的mongod进程一样 启动
命令
mongod --configsvr -f conf/config.conf
config.conf 文件内容:
dbpath = /home/apps/mongoDB/data/configdb
logpath = /home/apps/mongoDB/logs/configdb.log
fork = true
logpath = /home/apps/mongoDB/logs/configdb.log
fork = true
--configsvr 的作用是把默认端口修改为27019 dbpath 修改为 data/configdb 建议使用这个参数 这样可以直白的告诉我们这个服务器的用处
配置服务器并不需要太多的空间和资源 因此可以将其部署在运行着其他程序的机器上 如应用服务器 分片的mongod服务器 或者mongos进程的服务器
可以在三台配置服务器的任意一台上 启动mongos
mongodb-linux-i686-3.0.2/bin/mongos --configdb 192.168.1.111:27019,192.168.1.116:27019,192.168.1.117:27019 -f conf/mongos.conf
mongos.conf文件内容:
logpath = /home/apps/mongoDB/logs/mongos.log
fork = true
fork = true
默认情况下 mongos运行在27017端口 并不需要指定数据目录 mongos自身并不保存数据 他会在启动时从配置服务器加载数据 确保设置了logpath 以便将mongos日志保存到安全的地方 可以启动任意数量的mongos进程
生产情况下 一般mongos进程回合应用服务器运行在同一台服务器上
连接mongos
mongodb-linux-i686-3.0.2/bin/mongo 127.0.0.1:27017/test
将副本集转换为分片
只要告知mongos副本集的名称和副本集成员类表
sh.addShard("spock/server-1:27017,server-2:27017,server-3:27017")

可以在参数中指定副本集的所有成员 但并非一定要这么做 mongos能够自动检测到没有包含在副本集成员表中的成员 如运行sh.status() 可发现mongoDB已经找到了其他的副本集成员
副本集明朝spock被用作分片名称 如之后希望移除这个分片或是向这个分片迁移数据 可使用spock来表示这个分片 这比使用特定的服务器名称要好 因为副本集成员和状态是不断改变的,将副本集甜椒到分片后 就可以将应用程序连接到副本集改成连接mongos
数据分片
除非明确指定规则 否则MongoDB不会自动对数据进行分片,如有必要 必须明确要告知数据和集合
假如我们希望对test数据库中的music集合按照name键进行分片 首先要对music数据库启动分片
首先我们连接mongos 想test.music 添加10000条数据
然后再连接mongo 对数据库test启动分片

在对集合启动分片之前 要在片键name上建立索引

现在就可以根据name对集合music 进行分片了

因为我们现在只有一个分片 所以数据 全部在spock这个副本集上 minkey-->>maxkey
增加集群容量
可通过增加分片来增加集群容量 为添加一个新的 空的分片 可先创建一个副本集,确保副本集的名字和其他分片不同 副本集初始化并拥有一个主节点后.可以在mongos上运行sh.addShard("test123/192.168.1.122:27017") 将副本集作为分片添加到集群中
如果有现存的很多副本集 只要他们没有同名的数据库 就可以将他们作为新的分片全部添加到集群中.由于内存有限 我就能在做副本集了 演示当的mongod假如集群中 作为分片

因为本机存在一个test数据库 所以报上面图片的错误 所以我去本机删除 test数据库

继续添加分片


可以看见 108机器已经添加成 集群的分片之一了
MongoDB 会均衡的将集合数据分散到集群的分片上 这个过程不是瞬间完成的 对于比较大的集合 可能会话上几个小时才能完成
用mongoVUE 可以看到108分片的数据在增加


副本集 spock的数据在减少


进过了漫长等待 108分片上的数据最后

spock副本集上数据停留在

现在可以看出 数据通过mongos 添加到集群中,然后均衡器会自动帮你做数据均衡 .
MongoDB如何追踪集群数据
理论上说 MongoDB能够追踪到每个文档的位置,但当集合中包含成千上万的文档的时候,就会变得难以操作,因此mongodb将文档分组为快(chunk) 每个快由给定片键特定范围内的文档组成,一个快只能存在一个分片上,所以mongodb用一个比较小的表就能够维护块跟分片的映射
快范围
新分片的几个起初只有一个块,所有文档都位于这个块中,范围是负无穷到正无穷 shell用$minKey $maxKey表示
随着数据的不断增长 mongodb会自动将其分成两个块,范围就变成了 负无穷到 <some value> 和 <some value>到正无穷 两个块中的<some value>是相同的 范围较小的块包含比<some value>小的所有文档(但是不包含<some value>本身) 范围较大的块包含从<some value>一直到正无穷的所有文档(包含<some value>本身)
比如 我们按照age字段进行分片 所有的age的值为3~17的文档都包含在这一个块中:3<=age<17 该快拆分后,我们得到了两个较小的块 3<=age<12 和12<=age<17 这里的 12就叫做拆分点(split point0)
快拆分
mongos会记录在每个块中插入了多少数据 一旦到达阀值,就会检查是否需要对块进行拆分,如果快需要拆分 mongos就会在配置服务器上更新这个块的元信息.快拆分只需要更改快的元数据即可,而无需要进行数据移动,数据拆分时 配置服务器会创建新的块文档 同时会修改旧的快范围 拆分完成后 mongos会重置对原始快的追踪器 同时为新的块创建新的追踪器
拆分点的选取
{"age":13,"username":"wad"}
{"age":13,"username":"斯蒂芬"}
//拆分点
{"age":14,"username":"wads"}
{"age":14,"username":"wadf"}
{"age":14,"username":"wadg"}
//拆分点
{"age":15,"username":"wadh"}
{"age":15"username":"wadm"}
mongos无需在每个可用的拆分点对块进行拆分 但拆分时只能猜这些拆分点钟选择一个
上面例子来说 如果这是初中的学生的信息 那么在14岁的人将会很多 这样如果是用age作为片键就会出现很多大块 所以拥有不同的片键值是非常重要的
注意:集群的搭建必须保证配置服务器都必须可达 否则当mongos不断重复发起拆分请求去无法进行拆分 这个过程叫做拆分风暴 避免拆分风暴的唯一方法就是 尽可能的保证配置服务器的可用和健康.也可以重新启动mongos 重置写入计数器
频繁的让mongos上线和宕机 那么mongos在再次宕机之前可能永远无法收到足矣打到拆分阀值点的写请求 因此快回变得越来越大 所以减少mongos进程的波动,尽可能保证mongos进程可用,而不是需要时开启,不需要是关闭.
均衡器
负责数据的迁移 他会周期性的检查分片间是否存在不均衡 存在就迁移数据打到均衡 每个mongos有时候也会扮演均衡器的角色. 每隔几秒钟 mongos就会尝试变身为均衡器,如果没有其他均衡器可用,mongos就会对整个集群加锁,防止服务器对集群修改 然后做一次均衡,均衡不会影响mongos的正常路由操作 所以对客户端没有影响
不均衡是值:一个分片明显比其他分片拥有更多的快(集合越大越能承受不均衡状态) 如果检测到不均衡 均衡器就会开始对块进行在分布,使每个分片拥有数量相当的快.如果没有集合打到均衡阀值.mongos就不再充当均衡器的角色了