1)机器环境 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安装可以参考:http: //www .cnblogs.com /kevingrace/p/5752382 .html 对以上三台服务器部署Mongodb的副本集功能,定义副本集名称为:hqmongodb 关闭三台服务器的iptables防火墙和selinux 2)确保三台副本集服务器上的配置文件完全相同(即三台机器的mongodb.conf配置一样,除了配置文件中绑定的ip不一样)。下面操作在三台节点机上都要执行: 编写配置文件 [root@master-node ~] # cat /usr/local/mongodb/mongodb.conf 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 #auth=true #keyFile =/usr/local/mongodb/keyfile replSet =hqmongodb 编写启动脚本(各个节点需要将脚本中的ip改为本机自己的ip地址) [root@master-node ~] # cat /usr/local/mongodb/mongodb.conf port=27017 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 #auth=true #keyFile =/usr/local/mongodb/keyfile replSet =hqmongodb [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 启动mongodb [root@master-node ~] # ulimit -SHn 655350 [root@master-node ~] # /etc/init.d/mongodb start about to fork child process, waiting until server is ready for connections. forked process: 28211 child process started successfully, parent exiting [root@master-node ~] # ps -ef|grep mongodb root 28211 1 2 00:30 ? 00:00:00 /usr/local/mongodb/bin/mongod —maxConns 20000 —config /usr/local/mongodb/mongodb .conf root 28237 27994 0 00:30 pts /2 00:00:00 grep mongodb [root@master-node ~] # lsof -i:27017 COMMAND PID USER FD TYPE DEVICE SIZE /OFF NODE NAME mongod 28211 root 7u IPv4 684206 0t0 TCP *:27017 (LISTEN) ------------------------------------------------------------------ 如果启动mongodb的时候报错如下: about to fork child process, waiting until server is ready for connections. forked process: 14229 ERROR: child process failed, exited with error number 100 这算是一个Mongod 启动的一个常见错误,非法关闭的时候,lock 文件没有干掉,第二次启动的时候检查到有lock 文件的时候,就报这个错误了。 解决方法:进入mongod启动时指定的data目录下删除lock文件,然后执行 “./mongod —repair” 就行了。即 # rm -rf /usr/local/mongodb/data/mongod.lock //由于我的测试环境下没有数据,我将data数据目录下的文件全部清空,然后—repair # /usr/local/mongodb/bin/mongod —repair 然后再启动mongodb就ok了! ------------------------------------------------------------------ 3)对master-node主节点进行配置(182.48.115.236) // 其实,刚开始这三个节点中的任何一个都可以用来初始化为开始的主节点。这里选择以master-node为主节点 [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,以此类推。优先级最高的那个 被设置为主节点。 4)分别对两台从节点进行配置 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)设置数据库账号,开启登录验证(这一步可以直接跳过,即不开启登陆验证,只是为了安全着想) 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 6)验证副本集 分别重启三台副本集服务器(三台节点都要重启) [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” ) #添加仲裁节点 |
还没有评论,来说两句吧...