1)分片是Mongodb中的一种集群技术,用于应对数据量大规模增长的场景;
2)sharding方案将整个数据集拆分成多个更小的 chunk块,并分布在集群中多个 mongod 节点上,最终达到存储和负载能力扩容、压力分流的作用。
3)在 sharding架构中,每个负责存储一部分数据的 mongod 节点称为 shard(分片),shard 上分布的数据块称为 chunk,collections 可以根据“shard key”(称为分片键)将数据集拆分为多个 chunks,并相对均衡的分布在多 个 shards 上。
用于存储实际的数据块,生产环境中一个 shard server 角色可由几台机器组个一个 replica set 承担,防止主机单点故障;
mongod 实例,存储了整个 ClusterMetadata,包括 chunk 信息;
路由服务,承接客户端连接;
1)数据的分区根据“shard key”,对于每个需要 sharding 的 collection,都需要指定“shard key” (分片键);
2)分片键必须是索引字段或者为组合索引的左前缀;
3)mongodb 根据分片键将数据 分成多个 chunks,并将它们均匀分布在多个 shards 节点上。
4)mongodb 支持两种分区算法:区间分区(Range)和哈希(Hash)分区。
首先 shard key 必须是数字类型或字符串类型(字符串类型根据索引排序作为分裂依 据),整个区间的上下边界分别为“正无穷大”、“负无穷大”,每个 chunk 覆盖一段子区间, 即整体而言,任何 shard key 均会被某个特定的 chunk 所覆盖。区间均为左闭右开。每个区 间均不会有重叠覆盖,且互相临近。当然 chunk 并不是预先创建的,而是随着 chunk 数据的 增大而不断 split。
计算 shard key 的 hash 值(64 位数字),并以此作为 Range 来分区,基本方式同 1.4.1; Hash 值具有很强的散列能力,通常不同的 shard key 具有不同的 hash 值(冲突是有限的), 这种分区方式可以将 document 更加随机的分散在不同的 chunks 上。
分片 0 的 3 个节点的数据目录, RS 复制集, 1 主 1 备 1 仲裁
mkdir -p data/sh0/db0
mkdir -p data/sh0/db1
mkdir -p data/sh0/db2
分片 1 的 3 个节点的数据目录, RS 复制集, 1 主 1 备 1 仲裁
mkdir -p data/sh1/db0
mkdir -p data/sh1/db1
mkdir -p data/sh1/db2
配置服务器的 3 个节点的数据目录, RS 复制集, 1 主 2 备
mkdir -p data/cf/db0
mkdir -p data/cf/db1
mkdir -p data/cf/db2
路由节点
mkdir -p data/rt/db0
配置
mkdir etc
日志
mkdir log
进程描述文件
mkdir pids
搭建 2 个 Shard,每个 Shard 提供 3 个节点,1 主 1 备 1 仲裁
sh0/db0 配置
vi etc/sh0-db0.conf
dbpath=/usr/local/mongo/data/sh0/db0
logpath=/usr/local/mongo/log/sh0-db0.log
pidfilepath=/usr/local/mongo/pids/sh0-db0.pid
shardsvr=true
logappend=true r
eplSet=sh0
port=27010
oplogSize=10000
fork=true
bind_ip=0.0.0.0
sh0/db1 配置
vi etc/sh0-db1.conf
dbpath=/usr/local/mongo/data/sh0/db1
logpath=/usr/local/mongo/log/sh0-db1.log
pidfilepath=/usr/local/mongo/pids/sh0-db1.pid
shardsvr=true
logappend=true
replSet=sh0
port=27011
oplogSize=10000
fork=true
bind_ip=0.0.0.0
sh0/db2 配置
vi etc/sh0-db2.conf
dbpath=/usr/local/mongo/data/sh0/db2
logpath=/usr/local/mongo/log/sh0-db2.log
pidfilepath=/usr/local/mongo/pids/sh0-db2.pid
shardsvr=true
logappend=true
replSet=sh0
port=27012
oplogSize=10000
fork=true
bind_ip=0.0.0.0
sh1/db0 配置
vi etc/sh1-db0.conf
dbpath=/usr/local/mongo/data/sh1/db0
logpath=/usr/local/mongo/log/sh1-db0.log
pidfilepath=/usr/local/mongo/pids/sh1-db0.pid
shardsvr=true
logappend=true
replSet=sh1
port=27020
oplogSize=10000
fork=true
bind_ip=0.0.0.0
sh1/db1 配置
vi etc/sh1-db1.conf
dbpath=/usr/local/mongo/data/sh1/db1
logpath=/usr/local/mongo/log/sh1-db1.log
pidfilepath=/usr/local/mongo/pids/sh1-db1.pid
shardsvr=true
logappend=true
replSet=sh1
port=27021
oplogSize=10000
fork=true
bind_ip=0.0.0.0
sh1/db2 配置
vi etc/sh1-db2.conf
dbpath=/usr/local/mongo/data/sh1/db2
logpath=/usr/local/mongo/log/sh1-db2.log
pidfilepath=/usr/local/mongo/pids/sh1-db2.pid
shardsvr=true
logappend=true
replSet=sh1
port=27022
oplogSize=10000
fork=true
bind_ip=0.0.0.0
./mongod --config /usr/local/mongo/etc/sh0-db0.conf
./mongod --config /usr/local/mongo/etc/sh0-db1.conf
./mongod --config /usr/local/mongo/etc/sh0-db2.conf
./mongod --config /usr/local/mongo/etc/sh1-db0.conf
./mongod --config /usr/local/mongo/etc/sh1-db1.conf
./mongod --config /usr/local/mongo/etc/sh1-db2.conf
./mongo --port 27010 rs.initiate({ _id:"sh0", members:[ {_id:0,host:"127.0.0.1:27010",priority:2}, {_id:1,host:"127.0.0.1:27011",priority:1}, {_id:3,host:"127.0.0.1:27012",arbiterOnly:true} ] });
./mongo --port 27020 rs.initiate({ _id:"sh1", members:[ {_id:0,host:"127.0.0.1:27020",priority:2}, {_id:1,host:"127.0.0.1:27021",priority:1}, {_id:3,host:"127.0.0.1:27022",arbiterOnly:true} ] });
1 主 2 备,config server 的复制集中不允许有单仲 裁节点。复制集初始化命令中,不允许设置 arbiterOnly:true 参数。
vi etc/cf-db0.conf
dbpath=/usr/local/mongo/data/cf/db0
logpath=/usr/local/mongo/log/cf-db0.log
pidfilepath=/usr/local/mongo/pids/cf-db0.pid
logappend=true
replSet=cf
port=27030
oplogSize=10000
fork=true
bind_ip=0.0.0.0
configsvr=true
vi etc/cf-db1.conf
dbpath=/usr/local/mongo/data/cf/db1
logpath=/usr/local/mongo/log/cf-db1.log
pidfilepath=/usr/local/mongo/pids/cf-db1.pid
logappend=true
replSet=cf
port=27031
oplogSize=10000
fork=true
bind_ip=0.0.0.0
configsvr=true
vi etc/cf-db2.conf
dbpath=/usr/local/mongo/data/cf/db2
logpath=/usr/local/mongo/log/cf-db2.log
pidfilepath=/usr/local/mongo/pids/cf-db2.pid
logappend=true
replSet=cf
port=27032
oplogSize=10000
fork=true
bind_ip=0.0.0.0
configsvr=true
./mongod --config /usr/local/mongo/etc/cf-db0.conf
./mongod --config /usr/local/mongo/etc/cf-db1.conf
./mongod --config /usr/local/mongo/etc/cf-db2.conf
./mongo --port 27030 rs.initiate({ _id:"cf", members:[ {_id:0,host:"127.0.0.1:27030",priority:2}, {_id:1,host:"127.0.0.1:27031",priority:1}, {_id:3,host:"127.0.0.1:27032",priority:1} ] });
router 不需要数据库目录,需要提供配置服务(config server)信息,configdb=配置服务复制集名称/ 配置服务 IP:端口,配置服务 IP:端口
vi etc/rt-db0.conf
configdb=cf/127.0.0.1:27030,127.0.0.1:27031,127.0.0.1:27032 logpath=/usr/local/mongo/log/rt-db0.log
pidfilepath=/usr/local/mongo/pids/rt-db0.pid
port=27040
fork=true
bind_ip=0.0.0.0
./mongos --config /usr/local/mongo/etc/rt-db0.conf
分片集群搭建后,只是代表当前的集群可以实现分片,而不是集群中的每个集合默认分 片。
1)连接 Router 节点 bin/mongo --port 27040
2)进入 admin 库 use admin
3)加入分片信息: db.runCommand({‘addShard’:‘sh0/127.0.0.1:27010,127.0.0.1:27011,127.0.0.1:27012’}); db.runCommand({‘addShard’:‘sh1/127.0.0.1:27020,127.0.0.1:27021,127.0.0.1:27022’}); sh.addShard(‘sh0/127.0.0.1:27010,127.0.0.1:27011,127.0.0.1:27012’);
1)首先需要将 Database 开启 sharding,否则数据仍然无法在集群中分布,即数据库、 collection 默认为 non-sharding。对于 non-sharding 的 database 或者 collection 均会保存在 primary shard 上,直到开启 sharding 才会在集群中分布。
2) 创建测试库
use test
3)开启 Shard,开启分片命令必须在 admin 库下运行。
db.runCommand({ enablesharding: ‘test’})
4)此后我们可以对 collection 开启 sharding,在此之前需要先指定 shard key 和建立“shard key 索引”,我们根据 application 对数据访问的模式,来设定 shard key。
db.users.ensureIndex({‘alias’:‘hashed’});
设置集合为可分片集合的命令,必须在 admin 库中执行。
db.runCommand({ shardcollection: ‘test.users’, key: {‘alias’: ‘hashed’}})
5)那么 users 集合将使用“alias”作为第一维 shard key,采用 hashed 分区模式,将此 chunk 分裂成 2 个,我们可以通过 sh.status()查看每个 chunk 的分裂区间。