分片是指数据拆分 将其分散在不同的机器上的过程,有时候也叫分区来表示这个概念.将数据分散到不同机器上 不需要功能强大的计算机就可以储存更多的数据,处理更大的负载.
几乎所有的数据库都能手动分片 应用程序需要维护与若干不同数据库服务器的连接,每个连接都是独立的 应用程序给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就不再充当均衡器的角色了