MongoDB是一种很不错的NoSQL数据库,数据库存储基于BSON,一种JSON的变种。在使用的时候,有时候我们dump某个单个的collection/db作为备份的时候,往往会连累到整库都访问困难。集群有时候果断是个不错的选择。
MongoDB的存储是Replica,有三种角色如下:
一个cluster中只可以有一个primary,可以有多个secondary,当只有一个primary和一个secondary的时候,需要一个arbiter来帮忙投票哪个才是primary.
目前我们在使用的是tokumx,对外的访问和mongodb是一样的,但内部的配置略有区别。所以若各位使用的是官方mongodb,可能会发现略有不同。
当前,我们已经有一个单个的mongodb node,里面存了一堆数据,我的目标是将此单个node扩展为一个cluster.
首先,我们需要准备一个keyfile.生成方法可以参考这里. 简单说就是两行命令如下:
openssl rand -base64 741 > mongodb-keyfile chmod 600 mongodb-keyfile
然后就得到了一个mongodb-keyfile. 启动的时候加上keyfile参数如下
/path/to/tokumx/bin/mongod -f xxx.cnf --keyFile /path/to/key/mongodb-keyfile
一般配置文件我都是写在cnf中的,唯独这个keyFile貌似很难找到,所以我直接写启动脚本里面了。
对于单个文件我们并不需要这个keyfile,但若要做cluster,这个似乎是最简单的。因为两个node之间的通讯和验证全靠这个了。
在cnf中记得加上
replSet = your_rs_name
本cluster中所有的replSet都要是这个名字,若对不上也是认证不了的。
然后简单配置下其他环境,primary node就可以启动了。无意中找到一个不错的sample(链接),各位若使用tokumx可以考虑参考下.
启动的脚本和配置文件复制两份,路径稍稍修改下,改个端口启动.这样三个node就启动了.此时三者用的keyfile都是同一个文件。
mongodb Replica 的配置中,默认对机器的识别是hostname:port这么玩的.hostname的查看也很容易
uname -n
一般是写在/etc/hostname中的.内网环境下,你还可以自己写/etc/hosts,强行将名字解析到指定IP中.这样做的好处是之后都可以用一些特定的字符串指代某个机器。当然,非要用ip:port也是可以的。
然后我们就可以进入primary node中开始配置节点了
mongo 127.0.0.1:27017/admin -u your_username -p your_password
进入后,就可以看到提示自己已经在primary界面了。若不是,请到此处复习怎样创建user.顺便一提,tokumx1.5貌似是db.addUser()而不是createUser().
your_rs_name:PRIMARY> rs.initiate()
mongo3.0好像又有点区别, 应该先initiate,然后create user.
> rs.initiate() xx:PRIMARY> db.createUser({"user":"your_username","pwd":"your_password","roles":["root","dbAdmin","dbOwner"]})
或者 toku 的是:
> rs.initiate() xx:PRIMARY> db.addUser("your_username","your_password")
初始化结束后,可以查看config
your_rs_name:PRIMARY> rs.conf() { "_id" : "your_rs_name", .... "members" : [ { "_id":0 "host" : "your_hostname:your_first_port", } ] }
初始状态大致如上. 然后添加arbiter和secondary.
your_rs_name:PRIMARY> rs.addArb("your_arbiter_hostname:arbiter_port") { "ok" : 1 } your_rs_name:PRIMARY> rs.add("your_secondary_hostname:secondary_port") { "ok" : 1 }
arbiter节点中并不存储数据,只有一个投票帮助决定primary,而secondary中有完整的备份。 若前面验证都通过了的话,基本应该就加成功了。看log应该可以看到your_hostname:your_first_port正在向your_secondary_hostname:secondary_port同步数据的信息。
这个时候,你的your_hostname:your_first_port这个node和your_secondary_hostname:secondary_port这个node两者的priority是一样的,任何一个都可能是primary node,这可能并不是我们希望的。我们可能希望让某个node为primary node,另一个在第一个node挂了后担当起primary node的作用
your_rs_name:PRIMARY> cfg = rs.config() { "_id" : "your_rs_name", "version" : 326971, "protocolVersion" : 65, "members" : [ { "_id" : 0, "host" : "your_hostname:your_first_port" }, { "_id" : 1, "host" : "your_arbiter_hostname:arbiter_port", "arbiterOnly" : true }, { "_id" : 2, "host" : "your_secondary_hostname:secondary_port" } ] }
我们将当前的config赋值给cfg,然后在cfg上修改一下。
your_rs_name:PRIMARY> cfg.members[0].priority = 1 your_rs_name:PRIMARY> cfg.members[2].priority = 0.5 your_rs_name:PRIMARY> rs.reconfig(cfg, {force: true})
再看config
your_rs_name:PRIMARY> cfg = rs.config() { "_id" : "your_rs_name", "version" : 326971, "protocolVersion" : 65, "members" : [ { "_id" : 0, "host" : "your_hostname:your_first_port", "priority" : 1 }, { "_id" : 1, "host" : "your_arbiter_hostname:arbiter_port", "arbiterOnly" : true }, { "_id" : 2, "host" : "your_secondary_hostname:secondary_port", "priority" : 0.5 } ] }
当然,你还可以有一些更多的操作.比如添加hide=true可以让外部无法访问,priority=0的时候,这个node永远不可能会是primary.
若某个节点不要了,你可以用remove将其删去
your_rs_name:PRIMARY> rs.remove("your_secondary_hostname:secondary_port")
也可以直接修改config后 force reconfig.
最后,查看当前状态可以使用rs.isMaster()
1 Comment