前面看MONGODB 的集群配置,但一直没关系客户端是怎么连接的。以为在没有使用分片时,也可以使用mongos 及 config server 来处理。

在测试配置时,看到,并不是这回事。没有share时,config server 是无法配置的。


同时在这次配置时,也遇到访问权限问题,主要还是没理解集群服务器keyfile 的使用。(加了keyfile,必须使用用户/密码登录,功能类似于-- auth)


这里做一个记录。

mongodb 配置2数据节点+1仲裁节点的集群
 



1 建立相关目录: 

     mkdir /opt/mongodb/key 

     mkdir /opt/mongodb/config 

     mkdir /opt/mongodb/db1 

     mkdir /opt/mongodb/db2 

     mkdir /opt/mongodb/db3 



2.建立key 文件 


     2.1 添加文件 

     echo "this is key file" >> r1 

     echo "this is key file" >> r2 

     echo "this is key file" >> r3 


     2.2 配置权限,设置为只读 

     chmod 600 r1 r2 r3 



3.启动进程 


     /opt/mongodb/mongodb-linux-x86_64-2.5.5/bin/mongod --replSet rs1 --keyFile /opt/mongodb/key/r1 -dbpath=/opt/mongodb/db1 -logpath=/opt/mongodb/logs/mongodb_rep1.log --logappend  --directoryperdb --fork  --journal --port 28011 


     /opt/mongodb/mongodb-linux-x86_64-2.5.5/bin/mongod --replSet rs1 --keyFile /opt/mongodb/key/r2 -dbpath=/opt/mongodb/db2 -logpath=/opt/mongodb/logs/mongodb_rep2.log --logappend  --directoryperdb --fork  --journal --port 28012 


     /opt/mongodb/mongodb-linux-x86_64-2.5.5/bin/mongod --replSet rs1 --keyFile /opt/mongodb/key/r3 -dbpath=/opt/mongodb/db3 -logpath=/opt/mongodb/logs/mongodb_rep3.log --logappend  --directoryperdb --fork  --journal --port 28013 


 (注意: 添加了--directoryperdb 参数,如果没有添加此参数不会成功) 


 4.初始化replica set 


     用mongo连接其中一个mongod(例如:./mongo localhost:28011 )执行: 


     > config = {_id:"rs1",members:[{_id:0,host:'localhost:28011'},{_id:1,host:'localhost:28012'}]} 


         --,{_id:2,host:'localhost:28013',"arbiterOnly":true}                                                                                             

     > rs.initiate(config); 


         也可以使用另外加入第三个节点的方式配置 

         因为是在同一台服务器配置集群,为了节省磁盘空间,第3个节点会设置成是一个仲裁节点,(没有数据) 

         rs.add({_id:2,"host":"localhost:28013","arbiterOnly":true}); 




 完成后查看状态: 


     rs1:PRIMARY> rs.status() 

     { 

         "set" : "rs1", 

         "date" : ISODate("2014-06-04T15:24:37Z"), 

         "myState" : 1, 

         "members" : [ 

             { 

                 "_id" : 0, 

                 "name" : "localhost:28011", 

                 "health" : 1, 

                 "state" : 1, 

                 "stateStr" : "PRIMARY", 

                 "uptime" : 454, 

                 "optime" : Timestamp(1401895370, 1), 

                 "optimeDate" : ISODate("2014-06-04T15:22:50Z"), 

                 "self" : true 

             }, 

             { 

                 "_id" : 1, 

                 "name" : "localhost:28012", 

                 "health" : 1, 

                 "state" : 2, 

                 "stateStr" : "SECONDARY", 

                 "uptime" : 140, 

                 "optime" : Timestamp(1401895370, 1), 

                 "optimeDate" : ISODate("2014-06-04T15:22:50Z"), 

                 "lastHeartbeat" : ISODate("2014-06-04T15:24:35Z"), 

                 "lastHeartbeatRecv" : ISODate("2014-06-04T15:24:35Z"), 

                 "pingMs" : 0, 

                 "syncingTo" : "localhost:28011" 

             }, 

             { 

                 "_id" : 3, 

                 "name" : "localhost:28013", 

                 "health" : 1, 

                 "state" : 7, 

                 "stateStr" : "ARBITER", 

                 "uptime" : 107, 

                 "lastHeartbeat" : ISODate("2014-06-04T15:24:36Z"), 

                 "lastHeartbeatRecv" : ISODate("2014-06-04T15:24:35Z"), 

                 "pingMs" : 0 

             } 

         ], 

         "ok" : 1 

     } 





 测试: 

 先在测试表中插入一条记录 

     > db.test.insert(_id:1,userid:1,name:'tang'); 

     2014-06-04T11:35:24.335+0000 SyntaxError: Unexpected token : 

     > db.test.insert({_id:1,userid:1,name:'tang'}); 

     SingleWriteResult({ 

         "writeErrors" : [ ], 

         "writeConcernErrors" : [ ], 

         "nInserted" : 1, 

         "nUpserted" : 0, 

         "nUpdated" : 0, 

         "nModified" : 0, 

         "nRemoved" : 0, 

         "upserted" : [ ] 

     }) 

     > db.test.find() 

     { "_id" : ObjectId("5302c433b5b61e345817fb07"), "userid" : 1, "name" : "maketion ltd", "email" : "admin@maketion.com", "password" : "psd" } 

     { "_id" : ObjectId("53871082ed9422a9e22abc0c"), "company" : "" } 

     { "_id" : ObjectId("53871098ed9422a9e22abc0d"), "company" : { "_mongo" : { "slaveOk" : false, "host" : "localhost:28001", "authStatus" : { "authRequired" : true, "replSetGetStatus" : false, "isMaster" : true }, "_useWriteCommands" : true }, "_db" : { "_mongo" : { "slaveOk" : false, "host" : "localhost:28001", "authStatus" : { "authRequired" : true, "replSetGetStatus" : false, "isMaster" : true }, "_useWriteCommands" : true }, "_name" : "mdsp" }, "_shortName" : "a.name", "_fullName" : "mdsp.a.name" }, "name" : "maketion Ltd" } 

     { "_id" : 1, "userid" : 1, "name" : "tang" } 

     > 



 以下数据文件拷贝是基于参数 (--directoryperdb) 下完成的 


 1.关闭所有节点, 


 2.完成集群配置后,把单机环境下的数据库目录,拷贝到各节点数据库目录下,并保护数据文件的属性。 

 cp -pR  db/mdsp  db1/ 

 cp -pR  db/mdsp  db2/ 



3.重启各节点,进入后检查数据库是否和原单节点一致。 



4.如果 MongoDB 服务器启动时使用了 --auth 或 --keyFile 参数,你就必须在进行任何操作前进行认证。 你可以在连接时进行认证。方法是在链接字符串中指定用户名密码,
 或者在 MongoClient::__construct() 构造函数中指定 "username" 和 "password"。  

 



 上面是一段官方说明。这个以前不知道加了 keyFile 必须使用用户/密码登录。搞了很久。 


 mongo localhost:28011 -u root -p root 登录,看到没有提示错误了。 

 以下是没有使用用户/密码登录的错误信息: 


     ------------------------------遇到的问题描述------------------------ 

     服务器没有添加 --auth 启动, 

     mongo 登录时,也会出没有权限的提示,这可能和上面的授权有关系。联系到上面的话题,大概这命令就是这个功能吧。 


     下面是遇到的错误提示。希望对大家有启发 



     在集群环境下,启动参加中也没加AUTH。但登录时,说没有权限。 错误如下: 

     [mongo@localhost bin]$ ./mongo -port 28011/admin 

     MongoDB shell version: 2.5.5 

     2014-06-05T10:53:18.292+0000 Error: Invalid port number "28011/admin" in connection string "127.0.0.1:28011/admin/test" at src/mongo/shell/mongo.js:135 

     exception: connect failed 

     [mongo@localhost bin]$ ./mongo localhost:28011/admin 

     MongoDB shell version: 2.5.5 

     connecting to: localhost:28011/admin 

     Error while trying to show server startup warnings: not authorized on admin to execute command { getLog: "startupWarnings" } 

     rs1:SECONDARY> exit 

     bye 

     [mongo@localhost bin]$ ./mongo localhost:28012/admin 

     MongoDB shell version: 2.5.5 

     connecting to: localhost:28012/admin 

     Error while trying to show server startup warnings: not authorized on admin to execute command { getLog: "startupWarnings" } 

     rs1:PRIMARY> use admin 

     switched to db admin 

     rs1:PRIMARY> show collections; 

     2014-06-05T10:54:43.063+0000 error: { 

                     "$err" : "not authorized for query on admin.system.namespaces", 

                     "code" : 13 

     } at src/mongo/shell/query.js:131 

     rs1:PRIMARY> 



     看到日志中 有个 user:"__system",key:"xxx" 这是默认的还是什么? 

     2014-06-05T10:57:22.688+0000 [conn14] end connection 127.0.0.1:34299 (3 connections now open) 

     2014-06-05T10:57:22.689+0000 [initandlisten] connection accepted from 127.0.0.1:34301 #15 (4 connections now open) 

     2014-06-05T10:57:22.689+0000 [conn15]  authenticate db: local { authenticate: 1, nonce: "xxx", user: "__system", key: "xxx" } 

     2014-06-05T10:57:52.696+0000 [conn15] end connection 127.0.0.1:34301 (3 connections now open) 

     2014-06-05T10:57:52.696+0000 [initandlisten] connection accepted from 127.0.0.1:34303 #16 (4 connections now open) 

     2014-06-05T10:57:52.698+0000 [conn16]  authenticate db: local { authenticate: 1, nonce: "xxx", user: "__system", key: "xxx" } 

     2014-06-05T10:58:22.704+0000 [conn16] end connection 127.0.0.1:34303 (3 connections now open) 

     2014-06-05T10:58:22.705+0000 [initandlisten] connection accepted from 127.0.0.1:34305 #17 (4 connections now open) 

     2014-06-05T10:58:22.706+0000 [conn17]  authenticate db: local { authenticate: 1, nonce: "xxx", user: "__system", key: "xxx" } 

     2014-06-05T10:58:27.666+0000 [clientcursormon] mem (MB) res:69 virt:9643 

     2014-06-05T10:58:27.666+0000 [clientcursormon]  mapped (incl journal view):8924 


 ---------------- end  ------------------------------- 


 5.php 连接集群服务器示例: ,有点象oracle TNS,把多个服务器地址为列表,让客户端进行访问处理。 


 <?php 

 // Using multiple servers as the seed list (prefered) 

 $m = new MongoClient("mongodb://rs1.example.com:27017,rs2.example.com:27017/?replicaSet=myReplSetName")); 


 // Using one server as the seed list 

 $m = new MongoClient("mongodb://rs1.example.com:27017", array("replicaSet" => "myReplSetName")); 


 // Using multiple servers as the seed list 

 $m = new MongoClient("mongodb://rs1.example.com:27017,rs2.example.com:27017", array("replicaSet" => "myReplSetName")); 

 ?> 



 还可以指定读优化策略:Read Preferences 

  You can specify tag sets with the following read preference modes: 

     MongoClient::RP_PRIMARY_PREFERRED 

     MongoClient::RP_SECONDARY 

     MongoClient::RP_SECONDARY_PREFERRED 

     MongoClient::RP_NEAREST 


 // Prefer the nearest server in the "east" data center also used for reporting, 

 // but fall back to a server in the "west" data center 

 $uri  = 'mongodb://rs1.example.com,rs2.example.com/'; 

 $uri .= '?readPreference=nearest'; 

 $uri .= '&readPreferenceTags=dc:east,use:reporting'; 

 $uri .= '&readPreferenceTags=dc:west'; 

 $m = new MongoClient($uri, array('replicaSet' => 'rs'));