1. 复制
1.1. 复制简介
MongoDB复制是将数据同步在多个服务器的过程。
复制提供了数据的冗余备份,并在多个服务器上存储数据副本,提高了数据的可用性, 并可以保证数据的安全性。
复制还允许您从硬件故障和服务中断中恢复数据。
1.2. 什么是复制
l 保障数据的安全性
l 数据高可用性 (24*7)
l 灾难恢复
l 无需停机维护(如备份,重建索引,压缩)
l 分布式读取数据
1.3. MongoDB复制原理
mongodb的复制至少需要两个节点。其中一个是主节点,负责处理客户端请求,其余的都是从节点,负责复制主节点上的数据。
mongodb各个节点常见的搭配方式为:一主一从、一主多从。
主节点记录在其上的所有操作oplog,从节点定期轮询主节点获取这些操作,然后对自己的数据副本执行这些操作,从而保证从节点的数据与主节点一致。
1.4. 复制架构
以上结构图总,客户端总主节点读取数据,在客户端写入数据到主节点是, 主节点与从节点进行数据交互保障数据的一致性。
1.5. 复制特征
- N 个节点的集群
- 任何节点可作为主节点
- 所有写入操作都在主节点上
- 自动故障转移
- 自动恢复
2. 分片
2.1. 分片简介
在Mongodb里面存在另一种集群,就是分片技术,可以满足MongoDB数据量大量增长的需求。
当MongoDB存储海量的数据时,一台机器可能不足以存储数据,也可能不足以提供可接受的读写吞吐量。这时,我们就可以通过在多台机器上分割数据,使得数据库系统能存储和处理更多的数据。
2.2. 为什么使用分片
- 复制所有的写入操作到主节点
- 延迟的敏感数据会在主节点查询
- 单个副本集限制在12个节点
- 当请求量巨大时会出现内存不足。
- 本地磁盘不足
- 垂直扩展价格昂贵
2.3. 分片架构
上图中主要有如下所述三个主要组件:
Shard:
用于存储实际的数据块,实际生产环境中一个shard server角色可由几台机器组个一个replica set承担,防止主机单点故障
Config Server:
mongod实例,存储了整个 ClusterMetadata,其中包括 chunk信息。
Query Routers:
前端路由,客户端由此接入,且让整个集群看上去像单一数据库,前端应用可以透明使用
3. 复制+分片配置
3.1. 基础组件
操作系统: CentOS6.5 x64
Mongodb版本: 3.4.4
https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel62-3.4.4.tgz
集群 | IP | 端口号 |
rs0 | 192.168.1.90 | 26001 |
rs0 | 192.168.1.9 | 26001 |
rs1 | 192.168.1.90 | 26002 |
rs1 | 192.168.1.9 | 26002 |
rs2 | 192.168.1.90 | 26003 |
rs2 | 192.168.1.9 | 26003 |
Configure server: 192.168.1.90:26007、192.168.1.9:26007
Router : 192.168.1.90:26010、192.168.1.9:26010
3.2. 复制配置
下载软件并解压到指定目录
解压软件
tar xvf mongodb-linux-x86_64-rhel62-3.4.4.tgz
创建安装目录
mkdir –p /data/usr/local/mongodb/
复制可执行文件到安装目录
cp -a mongodb-linux-x86_64-rhel62-3.4.4/bin /data/usr/local/mongodb/
创建mongodb存储目录
mkdir –p /data/mongodb26001
mkdir –p /data/mongodb26002
mkdir –p /data/mongodb26003
mkdir –p /data/mongodb26007
mkdir –p /data/mongodb26010
配置文件配置
cat /etc/mongodb26001.conf
port=26001
logpath=/data/mongodb26001/mongod26001.log
logappend=true
pidfilepath=/data/mongodb26001/26001.pid
dbpath=/data/mongodb26001
#bind_ip=mongodb1.example.net,127.0.0.1
maxConns=500
replSet=rs0
shardsvr=true
#auth=true
#keyFile=/data/usr/local/mongodb/mongodbkey.cert
#fork=true
#cpu=true
#noauth=true
启动
nohup mongod -f /etc/mongodb26001.conf &
初始化
mongo 192.168.1.90:26001
rs.initiate()
rs.conf()
以上配置在192.168.1.9上重复执行
启动备用实例(192.168.1.9上执行)
nohup mongod -f /etc/mongodb26001.conf &
切换到192.168.1.90上
执行mongo 192.168.1.90:26001
rs.add("192.168.1.9:26001")
验证
rs.status()
集群rs1、rs2同上
3.3. 分片配置
添加Config Server
cat /etc/mongodb26007.conf
port=26007
logpath=/data/mongodb26007/mongod26007.log
logappend=true
pidfilepath=/data/mongodb26007/26007.pid
dbpath=/data/mongodb26007
#bind_ip=mongodb7.example.net,127.0.0.1
maxConns=500
replSet=configReplSet
configsvr=true
#auth=true
#keyFile=/data/usr/local/mongodb/mongodbkey.cert
#fork=true
#cpu=true
#noauth=true
192.168.1.9上配置文件相同
启动(两个都启动)
nohup mongod -f /etc/mongodb26002.conf &
初始化配置
rs.initiate({
_id: "configReplSet",
configsvr: true,
members: [
{ _id: 0, host: "192.168.1.90:26007" },
{ _id: 1, host: "192.168.1.9:26007" }
]
})
验证
rs.statau()
添加route节点(mongos)
[root@oracle ~]# cat /etc/mongodb26010.conf
port=26010
logpath=/data/mongodb26010/mongod26010.log
logappend=true
pidfilepath=/data/mongodb26010/26010.pid
#dbpath=/data/mongodb26010
#bind_ip=mongodb10.example.net,127.0.0.1
maxConns=500
configdb=configReplSet/192.168.1.90:26007,192.168.1.9:26007
#configdb=configReplSet/mongodb7.example.net:26007,mongodb8.example.net:26008,mongodb9.example.net:26009
#chunkSize=1
fork=true
#auth=true
#keyFile=/data/usr/local/mongodb/mongodbkey.cert
#fork=true
#cpu=true
#noauth=true
启动router
nohup mongos -f /etc/mongodb26010.conf &
添加分片节点
mongo mongodb10.example.net:26010进入mongodb
sh.addShard( "rs0/192.168.1.90:26001,192.168.1.9:26001" )
sh.addShard( "rs1/192.168.1.90:26002,192.168.1.9:26002" )
sh.addShard( "rs2/192.168.1.90:26003,192.168.1.9:26003" )
use test
sh.enableSharding('test');
sh.shardCollection('test.user',{uid:1})
for(i=-100;i<1000;i++){db.user.insert({uid:i,username:'test-'+i});}
验证分片
sh.status()
不明显;
for(i=10000;i<1000000;i++){db.user.insert({uid:i,username:'test-'+i});}
4. 添加分片
1, 复制集配置完毕
2, 配置服务器不用动
3, 往路由服务器里添加分片即可
sh.addShard( "rs3/192.168.1.90:26004,192.168.1.91:26004,192.168.1.9:26004" )
for(i=1000001;i<2000000;i++){db.user.insert({uid:i,username:'test-'+i});}
哈希分片
初始值:
移除分片
use admin;
db.adminCommand( { listShards: 1 } )
(或者运行 sh.status() 或者 db.printShardingStatus() .)
shards._id 字段列出了每个分片的名字.
db.runCommand({removeShard: "rs0"});
5. 错误处理
5.1. 错误一
"infoMessage" : "could not find member to sync from",
解决办法:
等待,知道复制集同步完成即可