Centos-mongodb分片

MongoDB中使用分片集群结构
1、mongos:
数据库集群请求的入口,所有的请求都通过mongos进行协调,不需要在应用程序添加一个路由选择器,mongos自己就是一个请求分发中心,它负责把对应的数据请求请求转发到对应的shard服务器上。在生产环境通常有多mongos作为请求的入口,防止其中一个挂掉所有的mongodb请求都没有办法操作。

2、config server:
顾名思义为配置服务器,存储所有数据库元信息(路由、分片)的配置。mongos本身没有物理存储分片服务器和数据路由信息,只是缓存在内存里,配置服务器则实际存储这些数据。mongos第一次启动或者关掉重启就会从 config server 加载配置信息,以后如果配置服务器信息变化会通知到所有的 mongos 更新自己的状态,这样 mongos 就能继续准确路由。在生产环境通常有多个 config server 配置服务器,因为它存储了分片路由的元数据,这个可不能丢失!就算挂掉其中一台,只要还有存货, mongodb集群就不会挂掉。

3、shard:
这就是传说中的分片了。上面提到一个机器就算能力再大也有天花板,就像军队打仗一样,一个人再厉害喝血瓶也拼不过对方的一个师。俗话说三个臭皮匠顶个诸葛亮,这个时候团队的力量就凸显出来了。在互联网也是这样,一台普通的机器做不了的多台机器来做

首先确定各个组件的数量,mongos 3个, config server 3个,数据分3片 shard server 3个,每个shard 有一个副本一个仲裁也就是 3 * 2 = 6 个,总共需要部署15个实例。这些实例可以部署在独立机器也可以部署在一台机器,我们这里测试资源有限,只准备了 3台机器,在同一台机器只要端口不同就可以

解压压缩包

tar zxf mongodb-linux-x86_64-rhel62-3.0.6.tgz
mv mongodb-linux-x86_64-rhel62-3.0.6 mongodb

分别在每台机器建立mongos 、config 、 shard1 、shard2、shard3 五个目录。

mkdir -p /usr/nacp/mongodb/mongos/log
mkdir -p /usr/nacp/mongodb/config/data
mkdir -p /usr/nacp/mongodb/config/log
mkdir -p /usr/nacp/mongodb/shard1/data
mkdir -p /usr/nacp/mongodb/shard1/log
mkdir -p /usr/nacp/mongodb/shard2/data
mkdir -p /usr/nacp/mongodb/shard2/log
mkdir -p /usr/nacp/mongodb/shard3/data
mkdir -p /usr/nacp/mongodb/shard3/log

规划5个组件对应的端口号,由于一个机器需要同时部署 mongos、config server 、shard1、shard2、shard3,所以需要用端口进行区分。这个端口可以*定义,在本文 mongos为 20000, config server 为 21000, shard1为 22001 , shard2为22002, shard3为22003。

在每一台服务器分别启动配置服务器。

/usr/nacp/mongodb/bin/mongod --configsvr --dbpath /usr/nacp/mongodb/config/data --port 21000 --logpath /usr/nacp/mongodb/config/log/config.log --fork

在每一台服务器分别启动mongos服务器。

/usr/nacp/mongodb/bin/mongos  --configdb 192.168.2.233:21000,192.168.2.235:21000,192.168.2.236:21000  --port 20000   --logpath  /usr/nacp/mongodb/mongos/log/mongos.log --fork

在每一台配置各个分片的副本集。nojournal 是为了关闭日志信息。 oplogsize是为了降低 local 文件的大小

#在每个机器里分别设置分片1服务器及副本集shard1
/usr/nacp/mongodb/bin/mongod --shardsvr --replSet shard1 --port 22001 --dbpath /usr/nacp/mongodb/shard1/data  --logpath /usr/nacp/mongodb/shard1/log/shard1.log --fork --nojournal  --oplogSize 10
#在每个机器里分别设置分片2服务器及副本集shard2
/usr/nacp/mongodb/bin/mongod --shardsvr --replSet shard2 --port 22002 --dbpath /usr/nacp/mongodb/shard2/data  --logpath /usr/nacp/mongodb/shard2/log/shard2.log --fork --nojournal  --oplogSize 10
#在每个机器里分别设置分片3服务器及副本集shard3
/usr/nacp/mongodb/bin/mongod --shardsvr --replSet shard3 --port 22003 --dbpath /usr/nacp/mongodb/shard3/data  --logpath /usr/nacp/mongodb/shard3/log/shard3.log --fork --nojournal  --oplogSize 10

分别对每个分片配置副本集

#设置第一个分片副本集
/usr/nacp/mongodb/bin/mongo  127.0.0.1:22001
#使用admin数据库
use admin
#定义副本集配置
config = { _id:"shard1", members:[
             {_id:0,host:"192.168.2.233:22001",arbiterOnly:true},
             {_id:1,host:"192.168.2.235:22001"},
             {_id:2,host:"192.168.2.236:22001"}
        ]
     }
#初始化副本集配置
rs.initiate(config);

#设置第二个分片副本集
/usr/nacp/mongodb/bin/mongo  127.0.0.1:22002
#使用admin数据库
use admin
#定义副本集配置
config = { _id:"shard2", members:[
             {_id:0,host:"192.168.2.233:22002"},
             {_id:1,host:"192.168.2.235:22002",arbiterOnly:true},
             {_id:2,host:"192.168.2.236:22002"}
        ]
     }
#初始化副本集配置
rs.initiate(config);

#设置第三个分片副本集
/usr/nacp/mongodb/bin/mongo    127.0.0.1:22003
#使用admin数据库
use admin
#定义副本集配置
config = { _id:"shard3", members:[
             {_id:0,host:"192.168.2.233:22003"},
             {_id:1,host:"192.168.2.235:22003"},
             {_id:2,host:"192.168.2.236:22003",arbiterOnly:true}
        ]
     }
#初始化副本集配置
rs.initiate(config);

#mongodb默认是从主节点读写数据的,副本节点上不允许读,需要设置副本节点可以读。
repset:SECONDARY> db.getMongo().setSlaveOk();

设置分片配置,让分片生效。

如里shard是单台服务器,用 db.runCommand( { addshard : “[: ]” } )这样的命令加入,如果shard是副本集,用db.runCommand( { addshard : “replicaSetName/[:port][,serverhostname2[:port],…]” });这样的格式表示 

#连接到mongos
/usr/nacp/mongodb/bin/mongo  127.0.0.1:20000
#使用admin数据库
user  admin。
#串联路由服务器与分配副本集1
db.runCommand( { addshard : "shard1/192.168.2.233:22001,192.168.2.235:22001,192.168.2.236:22001"});
#串联路由服务器与分配副本集2
db.runCommand( { addshard : "shard2/192.168.2.233:22002,192.168.2.235:22002,192.168.2.236:22002"});
#串联路由服务器与分配副本集3
db.runCommand( { addshard : "shard3/192.168.2.233:22003,192.168.2.235:22003,192.168.2.236:22003"});

查看分片服务器的配置

db.runCommand( { listshards : 1 } );
#内容输出
{
     "shards" : [
        {
            "_id" : "shard1",
            "host" : "shard1/192.168.0.136:22001,192.168.0.137:22001"
        },
        {
            "_id" : "shard2",
            "host" : "shard2/192.168.0.136:22002,192.168.0.137:22002"
        },
        {
            "_id" : "shard3",
            "host" : "shard3/192.168.0.136:22003,192.168.0.137:22003"
        }
    ],
    "ok" : 1
}
分片副本集的仲裁节点,所以在上面结果没有列出来。

连接在mongos上,准备让指定的数据库、指定的集合分片生效。

#指定testdb分片生效
db.runCommand( { enablesharding :"testdb"});
#指定数据库里需要分片的集合和片键
db.runCommand( { shardcollection : "testdb.table1",key : {id: 1} } )

我们设置testdb的 table1 表需要分片,根据 id 自动分片到 shard1 ,shard2,shard3 上面去。要这样设置是因为不是所有mongodb 的数据库和表 都需要分片!

测试分片配置结果。

#连接mongos服务器
/usr/nacp/mongodb/bin/mongo  127.0.0.1:20000
#使用testdb
use  testdb;
#插入测试数据
for (var i = 1; i <= 100000; i++) db.table1.save({id:i,"test1":"testval1"});
#查看分片情况如下,部分无关信息省掉了
db.table1.stats();
{
    "sharded" : true,
    "ns" : "testdb.table1",
    "count" : 100000,
    "numExtents" : 13,
    "size" : 5600000,
    "storageSize" : 22372352,
    "totalIndexSize" : 6213760,
    "indexSizes" : {
        "_id_" : 3335808,
        "id_1" : 2877952
    },
    "avgObjSize" : 56,
    "nindexes" : 2,
    "nchunks" : 3,
    "shards" : {
        "shard1" : {
            "ns" : "testdb.table1",
            "count" : 42183,
            "size" : 0,
            ...
            "ok" : 1
        },
        "shard2" : {
            "ns" : "testdb.table1",
            "count" : 38937,
            "size" : 2180472,
            ...
            "ok" : 1
        },
        "shard3" : {
            "ns" : "testdb.table1",
            "count" :18880,
            "size" : 3419528,
            ...
            "ok" : 1
        }
    },
    "ok" : 1
}

java程序调用分片集群,因为我们配置了三个mongos作为入口,就算其中哪个入口挂掉了都没关系,使用集群客户端程序如下:

public class TestMongoDBShards {
 
       public static void main(String[] args) {
 
         try {
          List<ServerAddress> addresses = new ArrayList<ServerAddress>();
          ServerAddress address1 = new ServerAddress("192.168.2.233" , 20000);
          ServerAddress address2 = new ServerAddress("192.168.2.235" , 20000);
          ServerAddress address3 = new ServerAddress("192.168.2.236" , 20000);
          addresses.add(address1);
          addresses.add(address2);
          addresses.add(address3);
 
          MongoClient client = new MongoClient(addresses);
          DB db = client.getDB( "testdb" );
          DBCollection coll = db.getCollection( "table1" );
 
          BasicDBObject object = new BasicDBObject();
          object.append( "id" , 1);
 
          DBObject dbObject = coll.findOne(object);
 
          System. out .println(dbObject);

          //读操作从副本节点读取
          ReadPreference preference = ReadPreference. secondary();
          DBObject dbObject = coll.findOne(object, null , preference);
          System. out .println(dbObject);
 
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
}

primary:默认参数,只从主节点上进行读取操作;
primaryPreferred:大部分从主节点上读取数据,只有主节点不可用时从secondary节点读取数据。
secondary:只从secondary节点上进行读取操作,存在的问题是secondary节点的数据会比primary节点数据“旧”。
secondaryPreferred:优先从secondary节点进行读取操作,secondary节点不可用时从主节点读取数据;
nearest:不管是主节点、secondary节点,从网络延迟最低的节点上读取数据。

    //连接到MongoDB服务 如果是远程连接可以替换“localhost”为服务器所在IP地址  
        //ServerAddress()两个参数分别为 服务器地址 和 端口  
        ServerAddress serverAddress = new ServerAddress("localhost",27017);  
        List<ServerAddress> addrs = new ArrayList<ServerAddress>();  
        addrs.add(serverAddress);  
          
        //MongoCredential.createScramSha1Credential()三个参数分别为 用户名 数据库名称 密码  
        MongoCredential credential = MongoCredential.createScramSha1Credential("username", "databaseName", "password".toCharArray());  
        List<MongoCredential> credentials = new ArrayList<MongoCredential>();  
        credentials.add(credential);  
          
        //通过连接认证获取MongoDB连接  
        MongoClient mongoClient = new MongoClient(addrs,credentials);
MongoClientOptions.Builder build = new MongoClientOptions.Builder();  
//与数据最大连接数50  
  build.connectionsPerHost(50);  
//如果当前所有的connection都在使用中,则每个connection上可以有50个线程排队等待  
build.threadsAllowedToBlockForConnectionMultiplier(50);  
build.connectTimeout(1*60*1000);  
build.maxWaitTime(2*60*1000);  
MongoClientOptions options = build.build();  
MongoClient client = new MongoClient("127.0.0.1", options); 
上一篇:Centos-SSH免密码登录


下一篇:Centos-mongodb副本集加分片配置