加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

mongodb在线增加分片节点

(2014-08-25 16:19:42)
标签:

mongodb

分类: 数据库
本文章没有任何权威性,纯属自己测试发现的结果

如果shard里只有2台机器,需要一个仲裁节点。否则主挂了从不会提升成主,从表象上看需要超过半数的机器投票才能生效,下面做出解释:
primary  负责client的读写。
secondary作为热备节点,应用Primary的oplog读取的操作日志,和primary保持一致,不提供读写操作!
secondary有两种类型:
1)normal secondary   随时和Primay保持同步, 
2)delayed secondary  延时指定时间和primary保持同步,防止误操作.
3)arbiter.它不负责任何读写,只作为一个仲裁者,负责primary down的时候剩余节点的选举操作. 在Replica Set 如果主库down了,要进行故障切换,集群的选举策略:
当primary当了之后,剩下的节点会选择一个primary节点,仲裁节点也会参与投票,避免僵局出现(如果没有仲裁节点,对于两节点的replica set 从节点down,主节点会变为secondary,导致整个replica set 不可用)选择依据为:优先级最高的且数据新鲜度最新的!
    primary 节点使用心跳来跟踪集群中有多少节点对其可见。如果达不到1/2,活跃节点会自动降级为secondary。这样就能够防止上面说的僵局状态或者当网络切割后primary已经与集群隔离的时候!

下面是测试过程
三台机器做mongos,config和仲裁节点  30000/27000/30001
192.168.10.202
192.168.10.203
192.168.10.204


两台机器做shard1 27020
192.168.10.202
192.168.10.203

两台台机器做shard2 27021
192.168.10.203
192.168.10.204

两台台机器做shard3  27022
192.168.10.202
192.168.10.204



1,在202/203/204机器上分别启动相关进程,仲裁节点不能是自己,并且仲裁节点需要和数据节点是一个shard

192.168.10.202
mkdir -p /data/27020 /data/27022 /data/arbiter
/usr/local/mongodb/bin/mongod --replSet shard1 --shardsvr --dbpath /data/27020 --port 27020 & 
/usr/local/mongodb/bin/mongod --replSet shard3 --shardsvr --dbpath /data/27022 --port 27022 &
/usr/local/mongodb/bin/mongod --replSet shard2 --shardsvr --dbpath /data/arbiter --port 30001 &


192.168.10.203
mkdir -p /data/27020 /data/27021 /data/arbiter
/usr/local/mongodb/bin/mongod --replSet shard2 --shardsvr --dbpath /data/27021 --port 27021 &
/usr/local/mongodb/bin/mongod --replSet shard1 --shardsvr --dbpath /data/27020 --port 27020 &
/usr/local/mongodb/bin/mongod --replSet shard3 --shardsvr --dbpath /data/arbiter --port 30001 &

192.168.10.204
mkdir -p /data/27021 /data/27022 /data/arbiter
/usr/local/mongodb/bin/mongod --replSet shard1 --shardsvr --dbpath /data/arbiter --port 30001 &
/usr/local/mongodb/bin/mongod --replSet shard3 --shardsvr --dbpath /data/27022 --port 27022 &
/usr/local/mongodb/bin/mongod --replSet shard2 --shardsvr --dbpath /data/27021 --port 27021 & 
 


2.在shard1 192.168.10.202上
初始化replica set
用mongo连接shard1的mongod,
/usr/local/mongodb/bin/mongo --port 27020
执行: #id要和启动时--replSet shard1的shard1匹配
config = {_id: 'shard1', members: [{_id:0, host: '192.168.10.202:27020'},{_id:1, host: '192.168.10.203:27020'},{_id:2, host: '192.168.10.204:30001', arbiterOnly:true}]}  
rs.initiate(config);


在shard2 192.168.10.203上
用mongo连接shard2的mongod,
/usr/local/mongodb/bin/mongo --port 27021
执行:
config = {_id: 'shard2', members: [{_id: 0, host: '192.168.10.203:27021'},{_id:1, host: '192.168.10.204:27021'},{_id: 2, host: '192.168.10.202:30001', arbiterOnly:true}]}
rs.initiate(config);

在shard3 192.168.10.204上
/usr/local/mongodb/bin/mongo --port 27022
执行:
config = {_id: 'shard3', members: [{_id: 0, host: '192.168.10.202:27022'},{_id:1, host: '192.168.10.204:27022'},{_id: 2, host: '192.168.10.203:30001', arbiterOnly:true}]}
rs.initiate(config);



3.配置3台config server
在192.168.10.202/203/204上:
mkdir -p /data/27000
/usr/local/mongodb/bin/mongod --configsvr --dbpath /data/27000 --port 27000 &


4.配置mongs
在192.168.10.202/203/204上分别执行:
/usr/local/mongodb/bin/mongos --configdb  192.168.10.202:27000,192.168.10.203:27000,192.168.10.204:27000 --port 30000 --logpath /data/mongos.log --logappend --fork
#mongs不需要dbpath

5.Configuring the Shard Cluster
连接到其中一个mongos进程,并切换到admin数据库做以下配置
a. 连接到mongs,并切换到admin
>use admin
>db
Admin
b. 加入shards
如果shard是replica sets,用replicaSetName/[:port] [,serverhostname2[:port],…]这样的格式表示,例如本例执行:
db.runCommand( { addshard : "shard1/192.168.10.202:27020,192.168.10.203:27020,192.168.10.204:30001"} );
db.runCommand( { addshard : "shard2/192.168.10.203:27021,192.168.10.204:27021,192.168.10.202:30001"} );
db.runCommand( { addshard : "shard3/192.168.10.202:27022,192.168.10.204:27022,192.168.10.203:30001"} );

c. Listing shards
>db.runCommand( { listshards : 1 } )
如果列出了以上二个你加的shards,表示shards已经配置成功

6.对库进行分片,必须为分片enable一个数据库
db.runCommand({enablesharding:"uam"})
db.printShardingStatus();

7.对需要分片的collections进行分片,用shardcollection 命令分隔数据集,key自动生成
db.runCommand({shardcollection : "uam.MONITOR_INFO","key":{"_id":"hashed"}})


先插入20W条数据:
mongos> for(i=1;i<200000;i++){
db.MONITOR_INFO.insert({uid:i,username:"Falcon +i",sex:"m",age:25 +i});
}
以下省略不重要部分
mongos> db.MONITOR_INFO.stats()
{
        "sharded" : true,
        "ns" : "uam.MONITOR_INFO",
        "count" : 199999,
        "shards" : {
                "shard1" : {
                        "ns" : "uam.MONITOR_INFO",
                        "count" : 66571,
                        "ok" : 1
                },
                "shard2" : {
                        "ns" : "uam.MONITOR_INFO",
                        "count" : 66422,
                        "ok" : 1
                },
                "shard3" : {
                        "ns" : "uam.MONITOR_INFO",
                        "count" : 67006,
                        "ok" : 1
                }
按hashed分片数据分配的很平均


测试新增分片结果:
增加分片,在192.168.10.202启动mongodb 27023端口做shard4

mkdir -p /data/27024 /data/27025 /data/30002
/usr/local/mongodb/bin/mongod --replSet shard4 --shardsvr --dbpath /data/27024 --port 27024 &
/usr/local/mongodb/bin/mongod --replSet shard4 --shardsvr --dbpath /data/27025 --port 27025 & 
/usr/local/mongodb/bin/mongod --replSet shard4 --shardsvr --dbpath /data/30002 --port 30002 &


用mongo连接shard4的mongod,
/usr/local/mongodb/bin/mongo --port 27024
执行:
config = {_id: 'shard4', members: [{_id: 0, host: '192.168.10.202:27024'},{_id:1, host: '192.168.10.202:27025'},{_id: 2, host: '192.168.10.202:30002', arbiterOnly:true}]}
rs.initiate(config);
rs.status()

3. 连接到之前的mongs,并切换到admin
/usr/local/mongodb/bin/mongo --port 30000
>use admin
Admin
a. 加入shards
mongos> sh.status()
  shards:
        "_id" : "shard1",  "host" : "shard1/192.168.10.202:27020,192.168.10.203:27020" }
        "_id" : "shard2",  "host" : "shard2/192.168.10.203:27021,192.168.10.204:27021" }
        "_id" : "shard3",  "host" : "shard3/192.168.10.202:27022,192.168.10.204:27022" } 这些是之前的

执行命令:
>db.runCommand( { addshard : "shard4/192.168.10.202:27024,192.168.10.202:27025,192.168.10.202:30002"} );  #这是新增的

可以看到下面的日志:
Mon Aug 25 16:14:53.790 [Balancer]  ns: uam.MONITOR_INFO going to move { _id: "uam.MONITOR_INFO-_id_MinKey", lastmod: Timestamp 5000|0, lastmodEpoch: ObjectId('53fae885efc2906eeccf321a'), ns: "uam.MONITOR_INFO", min: { _id: MinKey }, max: { _id: -6148914691236517204 }, shard: "shard1" } from: shard1 to: shard4 tag []
Mon Aug 25 16:14:53.790 [Balancer] moving chunk ns: uam.MONITOR_INFO moving ( ns:uam.MONITOR_INFOshard: shard1:shard1/192.168.10.202:27020,192.168.10.203:27020lastmod: 5|0||000000000000000000000000min: { _id: MinKey }max: { _id: -6148914691236517204 }) shard1:shard1/192.168.10.202:27020,192.168.10.203:27020 -> shard4:shard4/192.168.10.202:27024,192.168.10.202:27025

稍等一会:
mongos> db.MONITOR_INFO.stats()
{
        "sharded" : true,
        "ns" : "uam.MONITOR_INFO",
        "count" : 207867,
        "shards" : {
                "shard1" : {
                        "ns" : "uam.MONITOR_INFO",
                        "count" : 41317,
                        "ok" : 1
                },
                "shard2" : {
                        "ns" : "uam.MONITOR_INFO",
                        "count" : 66422,
                        "ok" : 1
                },
                "shard3" : {
                        "ns" : "uam.MONITOR_INFO",
                        "count" : 67006,
                        "ok" : 1
                },
                "shard4" : {
                        "ns" : "uam.MONITOR_INFO",
                        "count" : 33122,
                        "ok" : 1
                }
看到之前的数据已经迁移一部分至shard4节点,但是这里可能会有疑问,为什么shard2和shard3的数据不迁移?
首先要理解一个问题:
MongoDB的分片是指定一个分片key来进行,数据按范围分成不同的chunk,每个chunk的大小有限制。
有多个分片节点保存这些chunk,每个节点保存一部分的chunk。
每一个分片节点都是一个Replica Sets,这样保证数据的安全性。
当一个chunk超过其限制的最大体积时,会分裂成两个小的chunk。
当chunk在分片节点中分布不均衡时,会引发chunk迁移操作。
OK,明白了上面的道理,我继续插入了100W数据做测试,以下是chunk变化过程:
插入数据中....
                                shard4  1
                                shard1  2
                                shard3  4
                                shard2  3

插入完成,chunk发现分布节点不均衡,引发了迁移操作:
                                shard4  2
                                shard1  2
                                shard3  3
                                shard2  3


继续测试:
删除分片:
db.runCommand({removeshard:"shard4"})
这一步要持续一段时间,这个过程可以看在没有迁移完成的数据,shard4会保留,等完全迁移完成后才开始删除
"shard1" : {
                        "ns" : "uam.MONITOR_INFO",
                        "count" : 66571,
"shard4" : {
                        "ns" : "uam.MONITOR_INFO",
                        "count" : 18378,

过几秒在执行db.runCommand({removeshard:"shard4"})
"shard1" : {
                        "ns" : "uam.MONITOR_INFO",
                        "count" : 66571,
"shard4" : {
                        "ns" : "uam.MONITOR_INFO",
                        "count" : 12514,

出现以下信息才表明shard4已经被删除
mongos> db.runCommand({removeshard:"shard4"})
{
        "msg" : "removeshard completed successfully",
        "state" : "completed",
        "shard" : "shard4",
        "ok" : 1
}
这下才彻底删除了shard4



继续测试shard4只加入一个节点:
因为之前shard4有配置,所以这里先删除/data下的shard4节点,重新做config:
config = {_id: 'shard4', members: [{_id: 0, host: '192.168.10.202:27024'}]}
rs.initiate(config);
rs.status()

连接mongos,加入shard4
db.runCommand( { addshard : "shard4/192.168.10.202:27024"} );
看日志有以下输出
Mon Aug 25 16:03:42.244 [Balancer] moving chunk ns: uam.MONITOR_INFO moving ( ns:uam.MONITOR_INFOshard: shard1:shard1/192.168.10.202:27020,192.168.10.203:27020lastmod: 5|0||000000000000000000000000min: { _id: MinKey }max: { _id: -6148914691236517204 }) shard1:shard1/192.168.10.202:27020,192.168.10.203:27020 -> shard4:shard4/192.168.10.202:27024
也迁移了 但是只迁移了极少的数据,这点还不明白,不过线上新增分片也不会不要副本集的,这里慢慢在研究

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有