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);

友情链接
KaDraw流程图
API参考文档
OK工具箱
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:ixiaoyang8@qq.com
QQ群:637538335
关注微信