第38章:MongoDB-集群--Replica Sets(副本集)---多机的搭建
182.48.115.236 master-node(主节点)
182.48.115.237 slave-node1(从节点)
182.48.115.238 slave-node2(从节点)
MongoDB 安装目录:/usr/local/mongodb
MongoDB 数据库目录:/usr/local/mongodb/data
MongoDB 日志目录:/usr/local/mongodb/log/mongo.log
MongoDB 配置文件:/usr/local/mongodb/mongodb.conf
对以上三台服务器部署Mongodb的副本集功能,定义副本集名称为:hqmongodb
关闭三台服务器的iptables防火墙和selinux
确保三台副本集服务器上的配置文件完全相同(即三台机器的mongodb.conf配置一样,除了配置文件中绑定的ip不一样)。
下面操作在三台节点机上都要执行:
port=27017
bind_ip = 182.48.115.236 //这个最好配置成本机的ip地址。否则后面进行副本集初始化的时候可能会失败!
dbpath=/usr/local/mongodb/data
logpath=/usr/local/mongodb/log/mongo.log
pidfilepath=/usr/local/mongodb/mongo.pid
fork=true
logappend=true
shardsvr=true
directoryperdb=true
replSet=hqmongodb //副本集名称为:hqmongodb
[root@master-node ~]# ./mongod --config=mongodb.conf
[root@master-node ~]# ./mongo 182.48.115.236:27017 //登陆到mongodb数据库中执行下面命令操作。由于配置文件中绑定了ip,所以要用这个绑定的ip登陆
3.1)初始化副本集,设置本机为主节点 PRIMARY
> rs.initiate()
{
"info2" : "no configuration specified. Using a default configuration for the set",
"me" : "182.48.115.236:27017",
"ok" : 1
}
hqmongodb:OTHER> rs.conf()
{
"_id" : "hqmongodb",
"version" : 1,
"protocolVersion" : NumberLong(1),
"members" : [
{
"_id" : 0,
"host" : "182.48.115.236:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
}
],
"settings" : {
"chainingAllowed" : true,
"heartbeatIntervalMillis" : 2000,
"heartbeatTimeoutSecs" : 10,
"electionTimeoutMillis" : 10000,
"catchUpTimeoutMillis" : 2000,
"getLastErrorModes" : {
},
"getLastErrorDefaults" : {
"w" : 1,
"wtimeout" : 0
},
"replicaSetId" : ObjectId("5932f142a55dc83eca86ea86")
}
}
3.2)添加副本集从节点。(发现在执行上面的两个命令后,前缀已经改成"hqmongodb:PRIMARY"了,即已经将其自己设置为主节点 PRIMARY了)
hqmongodb:PRIMARY> rs.add("182.48.115.237:27017")
{ "ok" : 1 }
hqmongodb:PRIMARY> rs.add("182.48.115.238:27017")
{ "ok" : 1 }
3.3)设置节点优先级
hqmongodb:PRIMARY> cfg = rs.conf() //查看节点顺序
{
"_id" : "hqmongodb",
"version" : 3,
"protocolVersion" : NumberLong(1),
"members" : [
{
"_id" : 0,
"host" : "182.48.115.236:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
},
{
"_id" : 1,
"host" : "182.48.115.237:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
},
{
"_id" : 2,
"host" : "182.48.115.238:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
}
],
"settings" : {
"chainingAllowed" : true,
"heartbeatIntervalMillis" : 2000,
"heartbeatTimeoutSecs" : 10,
"electionTimeoutMillis" : 10000,
"catchUpTimeoutMillis" : 2000,
"getLastErrorModes" : {
},
"getLastErrorDefaults" : {
"w" : 1,
"wtimeout" : 0
},
"replicaSetId" : ObjectId("5932f142a55dc83eca86ea86")
}
}
hqmongodb:PRIMARY> cfg.members[0].priority = 1
1
hqmongodb:PRIMARY> cfg.members[1].priority = 1
1
hqmongodb:PRIMARY> cfg.members[2].priority = 2 //设置_ID 为 2 的节点为主节点。即当当前主节点发生故障时,该节点就会转变为主节点接管服务
2
hqmongodb:PRIMARY> rs.reconfig(cfg) //使配置生效
{ "ok" : 1 }
说明:
MongoDB副本集通过设置priority 决定优先级,默认优先级为1,priority值是0到100之间的数字,数字越大优先级越高,priority=0,则此节点永远不能成为主节点 primay。
cfg.members[0].priority =1 参数,中括号里的数字是执行rs.conf()查看到的节点顺序, 第一个节点是0,第二个节点是 1,第三个节点是 2,以此类推。优先级最高的那个
被设置为主节点。
slave-node1节点操作(182.48.115.237)
[root@slave-node1 ~]# ./mongo 182.48.115.237:27017
.....
hqmongodb:SECONDARY> db.getMongo().setSlaveOk() //设置从节点为只读.注意从节点的前缀现在是SECONDARY。看清楚才设置
slave-node2节点操作(182.48.115.238)
[root@slave-node2 ~]# ./mongo 182.48.115.238:27017
......
hqmongodb:SECONDARY> db.getMongo().setSlaveOk() //从节点的前缀是SECONDARY,看清楚才设置。执行这个,否则后续从节点同步数据时会报错:"errmsg" : "not master and slaveOk=false"
5.1)设置数据库账号
在master-node主节点服务器182.48.115.236上面操作
[root@master-node ]# ./mongo 182.48.115.236:27017
......
-------------------------------------------------
如果执行命令后出现报错: "errmsg" : "not master and slaveOk=false",
这是正常的,因为SECONDARY是不允许读写的,如果非要解决,方法如下:
> rs.slaveOk(); //执行这个命令然后,再执行其它命令就不会出现这个报错了
-------------------------------------------------
hqmongodb:PRIMARY> show dbs
local 0.000GB
hqmongodb:PRIMARY> use admin //mongodb3.0没有admin数据库了,需要手动创建。admin库下添加的账号才是管理员账号
switched to db admin
hqmongodb:PRIMARY> show collections
#添加两个管理员账号,一个系统管理员:system 一个数据库管理员:administrator
#先添加系统管理员账号,用来管理用户
hqmongodb:PRIMARY> db.createUser({user:"system",pwd:"123456",roles:[{role:"root",db:"admin"}]})
Successfully added user: {
"user" : "system",
"roles" : [
{
"role" : "root",
"db" : "admin"
}
]
}
hqmongodb:PRIMARY> db.auth('system','123456') //添加管理员用户认证,认证之后才能管理所有数据库
1
#添加数据库管理员,用来管理所有数据库
hqmongodb:PRIMARY> db.createUser({user:'administrator', pwd:'123456', roles:[{ role: "userAdminAnyDatabase", db: "admin"}]});
Successfully added user: {
"user" : "administrator",
"roles" : [
{
"role" : "userAdminAnyDatabase",
"db" : "admin"
}
]
}
hqmongodb:PRIMARY> db.auth('administrator','123456') //添加管理员用户认证,认证之后才能管理所有数据库
1
hqmongodb:PRIMARY> db
admin
hqmongodb:PRIMARY> show collections
system.users
system.version
hqmongodb:PRIMARY> db.system.users.find()
{ "_id" : "admin.system", "user" : "system", "db" : "admin", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "uTGH9NI6fVUFXd2u7vu3Pw==", "storedKey" : "qJBR7dlqj3IgnWpVbbqBsqo6ECs=", "serverKey" : "pTQhfZohNh760BED7Zn1Vbety4k=" } }, "roles" : [ { "role" : "root", "db" : "admin" } ] }
{ "_id" : "admin.administrator", "user" : "administrator", "db" : "admin", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "zJ3IIgYCe4IjZm0twWnK2Q==", "storedKey" : "2UCFc7KK1k5e4BgWbkTKGeuOVB4=", "serverKey" : "eYHK/pBpf8ntrER1A8fiI+GikBY=" } }, "roles" : [ { "role" : "userAdminAnyDatabase", "db" : "admin" } ] }
退出,用刚才创建的账号进行登录
[root@master-node ~]# mongo 182.48.115.236:27017 -u system -p 123456 --authenticationDatabase admin
[root@master-node ~]# mongo 182.48.115.236:27017 -u administrator -p 123456 --authenticationDatabase admin
5.2)开启登录验证
在master-node主节点服务器182.48.115.236上面操作
[root@master-node ~]# cd /usr/local/mongodb/ //切换到mongodb主目录
[root@master-node mongodb]# openssl rand -base64 21 > keyfile //创建一个 keyfile(使用 openssl 生成 21 位 base64 加密的字符串)
[root@master-node mongodb]# chmod 600 /usr/local/mongodb/keyfile
[root@master-node mongodb]# cat /usr/local/mongodb/keyfile //查看刚才生成的字符串,做记录,后面要用到
RavtXslz/WTDwwW2JiNvK4OBVKxU
注意:上面的数字 21,最好是 3 的倍数,否则生成的字符串可能含有非法字符,认证失败。
5.3)设置配置文件
分别在所有节点上面操作(即三个节点的配置文件上都要修改)
[root@master-node ~]# vim /usr/local/mongodb/mongodb.conf //添加下面两行内容
......
auth=true
keyFile =/usr/local/mongodb/keyfile
启动脚本使用下面的代码(注释原来的,启用之前注释掉的)
[root@master-node ~]# cat /etc/init.d/mongodb
#!/bin/sh
# chkconfig: - 64 36
# description:mongod
case $1 in
start)
/usr/local/mongodb/bin/mongod --maxConns 20000 --config /usr/local/mongodb/mongodb.conf
;;
stop)
#/usr/local/mongodb/bin/mongo 182.48.115.236:27017/admin --eval "db.shutdownServer()"
/usr/local/mongodb/bin/mongo 182.48.115.236:27017/admin --eval "db.auth('system', '123456');db.shutdownServer()"
;;
status)
#/usr/local/mongodb/bin/mongo 182.48.115.236:27017/admin --eval "db.stats()"
/usr/local/mongodb/bin/mongo 182.48.115.236:27017/admin --eval "db.auth('system', '123456');db.stats()"
;; esac
5.4)设置权限验证文件
先进入master-node主节点服务器182.48.115.236,查看
[root@master-node ~]# cat /usr/local/mongodb/keyfile
RavtXslz/WTDwwW2JiNvK4OBVKxU //查看刚才生成的字符串,做记录
再分别进入两台从节点服务器182.48.115.237/238
[root@slave-node1 ~]# vim /usr/local/mongodb/keyfile //将主节点生成的权限验证字符码复制到从节点的权限验证文件里
RavtXslz/WTDwwW2JiNvK4OBVKxU
[root@slave-node1 ~]# chmod 600 /usr/local/mongodb/keyfile
[root@slave-node2 ~]# vim /usr/local/mongodb/keyfile
[root@slave-node2 ~]# cat /usr/local/mongodb/keyfile
RavtXslz/WTDwwW2JiNvK4OBVKxU
[root@slave-node2 ~]# chmod 600 /usr/local/mongodb/keyfile
分别重启三台副本集服务器(三台节点都要重启)
[root@master-node ~]# ps -ef|grep mongodb
root 28964 1 1 02:22 ? 00:00:31 /usr/local/mongodb/bin/mongod --maxConns 20000 --config /usr/local/mongodb/mongodb.conf
root 29453 28911 0 03:04 pts/0 00:00:00 grep mongodb
[root@master-node ~]# kill -9 28964
[root@master-node ~]# /etc/init.d/mongodb start
about to fork child process, waiting until server is ready for connections.
forked process: 29457
child process started successfully, parent exiting
[root@master-node ~]# lsof -i:27017
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
mongod 29457 root 7u IPv4 701471 0t0 TCP slave-node1:27017 (LISTEN)
mongod 29457 root 29u IPv4 701526 0t0 TCP slave-node1:27017->master-node:39819 (ESTABLISHED)
mongod 29457 root 30u IPv4 701573 0t0 TCP slave-node1:27017->master-node:39837 (ESTABLISHED)
mongod 29457 root 31u IPv4 701530 0t0 TCP slave-node1:36768->master-node:27017 (ESTABLISHED)
mongod 29457 root 32u IPv4 701549 0t0 TCP slave-node1:36786->master-node:27017 (ESTABLISHED)
mongod 29457 root 33u IPv4 701574 0t0 TCP slave-node1:27017->master-node:39838 (ESTABLISHED)
然后登陆mongodb
[root@master-node ~]# mongo 182.48.115.236:27017 -u system -p 123456 --authenticationDatabase admin
.......
hqmongodb:PRIMARY> rs.status() //副本集状态查看.也可以省略上面添加登陆验证的步骤,不做验证,直接查看集群状态。集群状态中可以看出哪个节点目前是主节点
{
"set" : "hqmongodb",
"date" : ISODate("2017-06-03T19:06:59.708Z"),
"myState" : 1,
"term" : NumberLong(2),
"heartbeatIntervalMillis" : NumberLong(2000),
"optimes" : {
"lastCommittedOpTime" : {
"ts" : Timestamp(1496516810, 1),
"t" : NumberLong(2)
},
"appliedOpTime" : {
"ts" : Timestamp(1496516810, 1),
"t" : NumberLong(2)
},
"durableOpTime" : {
"ts" : Timestamp(1496516810, 1),
"t" : NumberLong(2)
}
},
"members" : [
{
"_id" : 0,
"name" : "182.48.115.236:27017",
"health" : 1,
"state" : 1, //state的值为1的节点就是主节点
"stateStr" : "PRIMARY", //主节点PRIMARY标记
"uptime" : 138,
"optime" : {
"ts" : Timestamp(1496516810, 1),
"t" : NumberLong(2)
},
"optimeDate" : ISODate("2017-06-03T19:06:50Z"),
"infoMessage" : "could not find member to sync from",
"electionTime" : Timestamp(1496516709, 1),
"electionDate" : ISODate("2017-06-03T19:05:09Z"),
"configVersion" : 4,
"self" : true
},
{
"_id" : 1,
"name" : "182.48.115.237:27017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 116,
"optime" : {
"ts" : Timestamp(1496516810, 1),
"t" : NumberLong(2)
},
"optimeDurable" : {
"ts" : Timestamp(1496516810, 1),
"t" : NumberLong(2)
},
"optimeDate" : ISODate("2017-06-03T19:06:50Z"),
"optimeDurableDate" : ISODate("2017-06-03T19:06:50Z"),
"lastHeartbeat" : ISODate("2017-06-03T19:06:59.533Z"),
"lastHeartbeatRecv" : ISODate("2017-06-03T19:06:59.013Z"),
"pingMs" : NumberLong(0),
"syncingTo" : "182.48.115.236:27017",
"configVersion" : 4
},
{
"_id" : 2,
"name" : "182.48.115.238:27017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 189,
"optime" : {
"ts" : Timestamp(1496516810, 1),
"t" : NumberLong(2)
},
"optimeDurable" : {
"ts" : Timestamp(1496516810, 1),
"t" : NumberLong(2)
},
"optimeDate" : ISODate("2017-06-03T19:06:50Z"),
"optimeDurableDate" : ISODate("2017-06-03T19:06:50Z"),
"lastHeartbeat" : ISODate("2017-06-03T19:06:59.533Z"),
"lastHeartbeatRecv" : ISODate("2017-06-03T19:06:59.013Z"),
"pingMs" : NumberLong(0),
"syncingTo" : "182.48.115.236:27017",
"configVersion" : 4
},
],
"ok" : 1
}
注意上面命令结果中的state,如果这个值为 1,说明是主控节点(master);如果是2,说明是从属节点slave。在上面显示的当前主节点写入数据,到从节点上查看发现数据会同步。
当主节点出现故障的时候,在两个从节点上会选举出一个新的主节点,故障恢复之后,之前的主节点会变为从节点。从上面集群状态中开看出,当前主节点是master-node,那么关闭它的mongodb,再次查看集群状态,就会发现主节点变为之前设置的slave-node2,即182.48.115.238了!
至此,Linux 下 MongoDB 副本集部署完成。
1)主从服务器数据是否同步,从服务器没有读写权限
a:向主服务器写入数据 ok 后台自动同步到从服务器,从服务器有数据
b:向从服务器写入数据 false 从服务器不能写
c:主服务器读取数据 ok
d:从服务器读取数据 false 从服务器不能读
2)关闭主服务器,从服务器是否能顶替
mongo 的命令行执行 rs.status() 发现 PRIMARY 替换了主机了
3)关闭的服务器,再恢复,以及主从切换
a:直接启动关闭的服务,rs.status()中会发现,原来挂掉的主服务器重启后变成从服务器了
b:额外删除新的服务器 rs.remove("localhost:9933"); rs.status()
c:额外增加新的服务器 rs.add({_id:0,host:"localhost:9933",priority:1});
d:让新增的成为主服务器 rs.stepDown(),注意之前的 priority 投票
4)从服务器读写
db.getMongo().setSlaveOk();
db.getMongo().slaveOk();//从库只读,没有写权限,这个方法 java 里面不推荐了
db.setReadPreference(ReadPreference.secondaryPreferred());// 在 复 制 集 中 优 先 读secondary,如果 secondary 访问不了的时候就从 master 中读
db.setReadPreference(ReadPreference.secondary());// 只 从 secondary 中 读 , 如 果secondary 访问不了的时候就不能进行查询
MongoDB 的 Replica Set 架构是通过一个日志来存储写操作的,这个日志就叫做”oplog”,它存在于”local”数据库中,oplog 的大小是可以通过 mongod 的参数”—oplogSize”来改变oplog 的日志大小。
> use local
switched to db local
> db.oplog.rs.find()
{ "ts" : { "t" : 1342511269000, "i" : 1 }, "h" : NumberLong(0), "op" : "n", "ns" : "", "o" :
{ "msg" : "initiating set" } }
字段说明:
ts: 某个操作的时间戳
op: 操作类型,如下:
i: insert
d: delete
u: update
ns: 命名空间,也就是操作的 collection name
rs.remove("ip:port"); //删除副本
单服务器,启动时添加--auth 参数开启验证。
副本集服务器,开启--auth 参数的同时,必须指定 keyfile 参数,节点之间的通讯基于该 keyfile,key 长度必须在 6 到 1024 个字符之间,最好为 3 的倍数,不能含有非法字符。
重新设置副本集
rs.stepDown()
cfg = rs.conf()
cfg.members[n].host= 'new_host_name:prot'
rs.reconfig(cfg)
副本集所有节点服务器总数必须为奇数,服务器数量为偶数的时候,需要添加一个仲裁节 点,仲裁节点不参与数副本集,只有选举权。
rs.addArb("182.48.115.239:27017") #添加仲裁节点
第38章:MongoDB-集群--Replica Sets(副本集)---多机的搭建的更多相关文章
- 第39章:MongoDB-集群--Replica Sets(副本集)---副本集基本原理
①操作日志oplog Oplog是主节点的local数据库中的一个固定集合,按顺序记录了主节点的每一次写操作,MongoDB的复制功能是使用oplog来实现的,备份节点通过查询这个集合就可以知道需要进 ...
- 第36章:MongoDB-集群--Replica Sets(副本集)
①副本集 副本集是一种在多台机器同步数据的进程,副本集体提供了数据冗余,扩展了数据可用性.在多台服务器保存数据可以避免因为一台服务器导致的数据丢失.也可以从硬件故障或服务中断解脱出来,利用额外的数据副 ...
- 第37章:MongoDB-集群--Replica Sets(副本集)---单机的搭建
①创建副本集 1:先创建几个存放数据的文件夹,比如在前面的dbs下面创建db1,db2,db3: 同理在前面的logs下面创建logs1,logs2,logs3 2:在启动MongoDB服务器的时候, ...
- 第40章:MongoDB-集群--Replica Sets(副本集)---副本集的管理
①以单机模式启动成员 由于很多维护的工作需要写入操作,所以不合适在副本集中操作,可以以单机模式启动成员,也就是不要使用副本的选项,就跟以前启动单独的服务器一样.一般使用一个跟副本集配置中不一样的端口号 ...
- mongodb 搭建集群(分片+副本集)
mongodb 搭建集群(分片+副本集) 一.搭建结构图: 二.搭建步骤:
- MongoDB学习笔记——Replica Set副本集
副本集 可以将MongoDB中的副本集看作一组服务器集群由一个主节点和多个副本节点等组成,相对于之前讲到的主从复制提供了故障自动转移的功能 副本集实现数据同步的方式依赖于local数据库中的oplog ...
- mongodb的分布式集群(2、副本集)
概述 副本集是主从复制的一种,是一种自带故障转移功能的主从复制.攻克了上述主从复制的缺点.实现主server发生问题后.不需人为介入.系统自己主动从新选举一个新的主server的功能. ...
- mongodb分片集群(无副本集)搭建
数据分片节点#192.168.114.26#mongo.cnfport=2001dbpath=/data/mongodb/datalogpath=/data/mongodb/log/mongodb.l ...
- Mongo的Replica Sets (复制集)的配置全过程和心得体会
http://blog.csdn.net/bloggongchang/article/details/7272403 一.MongoDB Replica Sets(副本集)简单的说就是有自动故障恢复功 ...
随机推荐
- ORACLE重装之后恢复数据库,相当于sqlserver的附加数据库
在开发机器上经常会遇到重装系统的问题,重装之前如果ORACLE没有及时备份的话重装之后就纠结了,数据还原很头疼. 各种娘中只能找到一些ORACLE安装与重装系统前目录相同的解决办法,目录不同就没招了. ...
- Xeon Phi 《协处理器高性能编程指南》随书代码整理 part 1
▶ 第三章,逐步优化了一个二维卷积计算的过程 ● 基准代码 #include <stdio.h> #include <stdlib.h> #include <string ...
- C#设计模式(2)——简单工厂模式(Factory )
我们通过 Factory 创建对象不同的对象. 例如:如果创建一个汽车的接口,通过 工厂Factory 创建实现接口的对象,根据我们的选择来创建不同的对象. 创建汽车接口 /// <summar ...
- ActiveMQ(2)---ActiveMQ原理分析之消息发送
持久化消息和非持久化消息的发送策略 消息同步发送和异步发送 ActiveMQ支持同步.异步两种发送模式将消息发送到broker上.同步发送过程中,发送者发送一条消息会阻塞直到broker反馈一个确认消 ...
- java 调用 python 的几种方法整理
参考: https://blog.csdn.net/secondlieutenant/article/details/79000265
- leetcode139
class Solution { public: bool wordBreak(string s, vector<string> wordDict) { vector<, false ...
- JS StartMove源码-简单运动框架
这几天学习js运动应用课程时,开始接触一个小例子:“仿Flash的图片轮换播放器”,其中使用的StartMove简单运动框架我觉得挺好用的.这个源码也简单,理解其原理,自己敲即便也就熟悉了. 用的时候 ...
- 6.Python enumerate 特性
enumerate()可参考: list1 = ["这", "是", "一个", "测试"] for index,ite ...
- kubectl-常用命令
出处https://cloud.tencent.com/developer/article/1140076 kubectl apply -f kubernetes-dashboard.yaml -n ...
- vue.js建立一个简单的表格
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding= ...