主从复制是sql server 最常用的复制方式,这种方式很灵活.可用于备份,故障恢复,读扩展等.
最基本的设置方式就是建立一个主节点和一个或多个从节点,每个从节点要知道主节点的地址.
这里我们用一主一从实现mongodb的复制
网易蜂巢的容器已经安装好了mongoDB,直接就可以运行mongo Client,我们要创建自己的mongod实例,
首先把容器自行运行的先停止
mongod --shutdown
mongod --master --port=27081 --dbpath=/data/masterdb --logpath=/data/masterlog --fork
mongod --slave --port=27083 --dbpath=/data/slavedb --logpath=/data/slavelog --source=27081 --fork
root@mongodb-671984-3837ac52-ky93c:~# ps -ef|grep mongod
root 116 1 0 13:09 ? 00:00:05 mongod --master --port=27081 --dbpath=/data/masterdb --logpath=/data/masterlog --fork
root 173 1 0 13:20 ? 00:00:01 mongod --slave --port=27083 --dbpath=/data/slavedb --logpath=/data/slavelog --source=27081 --fork
root 279 64 0 13:24 pts/0 00:00:00 grep mongod
连接master
mongo --port 27081
在mongo client 执行下列命令
> rs.isMaster()
{
"ismaster" : true,
"maxBsonObjectSize" : 16777216,
"maxMessageSizeBytes" : 48000000,
"maxWriteBatchSize" : 1000,
"localTime" : ISODate("2016-09-13T05:29:37.302Z"),
"maxWireVersion" : 4,
"minWireVersion" : 0,
"ok" : 1
}
> use blogs
switched to db blogs
> db.blog.insert({BlogName:"ike's Blog",writer:"ike" })
WriteResult({ "nInserted" : 1 })
连接slave
mongo --port 27083
在mongo client 执行下列命令
> rs.isMaster()
> use blogs
switched to db blogs
> db.blog.find()
Error: error: { "ok" : 0, "errmsg" : "not master and slaveOk=false", "code" : 13435 }
Error的原因是从机默认不支持读写 ,解决办法:
> rs.slaveOk()
mongoDB官方已经不建议大家使用这种主从复制的架构了,这种架构无法避免主机宕机后服务中断.
1.副本集具有2个或者多个节点(一般最少3个)
2.副本集具有一个主节点,其他都是从节点
3.所有数据都是从主节点到从节点的.
4.当主节点故障,从节点会自行推举一个新的主节点
5.当失败节点恢复后,连接副本集后,重新作为从节点
mongod --dbpath=/data/node1 --logpath=/data/node1log/nodelog.log --port=27073 --keyFile=/data/node/mongokey --clusterAuthMode=keyFile --replSet=nodeset --fork
mongod --dbpath=/data/node2 --logpath=/data/node2log/nodelog.log --port=27075 --keyFile=/data/node/mongokey --clusterAuthMode=keyFile --replSet=nodeset --fork
mongod --dbpath=/data/node3 --logpath=/data/node3log/nodelog.log --port=27077 --keyFile=/data/node/mongokey --clusterAuthMode=keyFile --replSet=nodeset --fork
> conf={_id:"nodeset",members:[{_id:1 ,host:"localhost:27073"}]} ##_id:副本集名称
{
"_id" : "nodeset",
"members" : [
{
"_id" : 1,
"host" : "localhost:27073"
}
]
}
> rs.initiate(conf) ##初始化副本集
{ "ok" : 1 }
> use admin
switched to db admin
nodeset:PRIMARY> db.createUser({user:"root",pwd:"root",roles:["root"]}) ## PRIMARY 说明连接的是主节点,在admin下创建管理员
nodeset:PRIMARY> db.auth("root","root") ##登入管理员账号
nodeset:PRIMARY> rs.add("127.0.0.1:27075") ##将其他两个实例添加进副本集
nodeset:PRIMARY> rs.add("127.0.0.1 :27077")
nodeset:PRIMARY> rs.status() ##副本集状态,节点查询
到此,拥有3个节点的副本集就创建完了 ,更多操作执行rs.help()查询
另外一个副本集:
# mongod --port 27011 --dbpath /data/smail_data1 --logpath /var/smail_log1/mongodb.log --keyFile /var/key/mongodb.key --shardsvr --replSet rs_1 --clusterAut
hMode keyFile --fork --logappend
# mongod --port 27012 --dbpath /data/smail_data2 --logpath /var/smail_log2/mongodb.log --keyFile /var/key/mongodb.key --shardsvr --replSet rs_1 --clusterAut
hMode keyFile --fork --logappend
# mongod --port 27013 --dbpath /data/smail_data3 --logpath /var/smail_log3/mongodb.log --keyFile /var/key/mongodb.key --shardsvr --replSet rs_1 --clusterAut
hMode keyFile --fork --logappend
# mongo --port 27011
> conf={_id:'rs_1',members:[{_id:1,host:'10.166.224.7:27011'}]}
{
"_id" : "rs_1",
"members" : [
{
"_id" : 1,
"host" : "10.166.224.7:27011" ## 10.166.224.7
}
]
}
> rs.initiate(conf)
{ "ok" : 1 }
rs_1:PRIMARY> db.createUser({user:'root',pwd:'root',roles:["root"]})
Successfully added user: { "user" : "root", "roles" : [ "root" ] }
rs_1:PRIMARY> db.auth('root','root')
1
rs_1:PRIMARY> rs.add('10.166.224.7:27013')
{ "ok" : 1 }
rs_1:PRIMARY> rs.add('10.166.224.7:27012')
{ "ok" : 1 }
这里有两个细节:
1.节点之间需要keyfile认证,集群内节点使用keyFile使用的秘钥必须相同
2.不同的服务器使用同一网段注册节点,config server和 副本集 的配置信息不要使用127.0.0.1 或者localhost
config server
mongod --configsvr --port 27019 --dbpath=/data/medium_conf --logpath=/var/conf_log/mongodbconf.log --fork --logappend --keyFile /var/key/mongodb.key --clusterAuthMode keyFile
root@medium-701747-230f8712-ee7xm:~# mongo --port 27019
configsvr> use admin
switched to db admin
configsvr> db.createUser(user:'root',pwd:'root',roles:["root"])
mongos
mongos --port 27021 --logpath=/var/mongosdb_log/mongos.log --fork --logappend --configdb 10.166.224.4:27019 --keyFile /var/key/mongodb.key --clusterAuthMode keyFile
## 使用和分片同一网段的ip
momgo --port 27021
mongos> use admin
switched to db admin
mongos> db.auth('root','root')
mongos> sh.addShard("rs_2/10.166.224.4:27011") ##添加同一主机下的shard成员
{ "shardAdded" : "rs_2", "ok" : 1 }
mongos> sh.addShard("rs_1/10.166.224.7:27011") ##添加10.166.224.7下的shard成员
{ "shardAdded" : "rs_1", "ok" : 1 }
mongos> sh.status() ## sharding status
测试分片集群:
mongos> use test ##database
mongos> for(i=0;i<20000;i++){db.shardtest.insert({'url':'intricate-sutra.com','name':"ike's blog",'i':i})}; ##collection:shardtest
mongos> db.shardtest.stats() ##查看集合状态,发现shards内只有rs_1一个shard
##数据分片
mongos> sh.enableSharding("test")
mongos> sh.shardCollection("test.shardtest",{_id:1})
结束后balance会根据chunk的数量进行数据迁移,直到chunk的数量平均分配到每个shard上,如图:
balancing:
均衡器负责数据的迁移,会周期性的检查分片是否存在不均衡,如果存在balance进程会进行chunk的迁移.
balance进行均衡的条件是chunk数量的多少,而不是chunk大小
mongos> use config
mongos> db.locks.find({_id:"balancer"}).pretty() ##查看balance的状态
chunk:
chunkSize的大小默认是64M,可以修改chunk的大小,使数据分布更均衡
mongos> use config
mongos> db.settings.save({"_id" : "chunksize", "value" : NumberLong(32)})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
也可以在数据插入前配置数据存储chunk
mongos> sh.enableSharding('test')
mongos> db.createCollection("job" ) ##创建集合:test.job
mongos> sh.shardCollection('test.job',{'offer':1})
mongos> sh.splitAt("test.job",{offer:20}) ##按offer的20作为split的点
splitting是后台进程,按照middle或者chunk大小splitting数据,上面的操作就是按照middle(split的点)划分.
分片过程中利用哈希索引作为分片的单个键.
哈希分片的片键只能使用一个字段.
哈希片键最大的好处就是保证数据在各个节点分布基本均匀.