当前位置:Gxlcms > 数据库问题 > 通过一步步创建sharded cluster来认识mongodb

通过一步步创建sharded cluster来认识mongodb

时间:2021-07-01 10:21:17 帮助过:14人阅读

#!/bin/bash 2 export BIN_HOME=/usr/local/mongodb/bin 3 export DB_PATH=/home/mongo_db/data 4 export LOG_PATH=/home/mongo_db/log 5 6 LOCAL=127.0.0.1 7 8 #config rs 9 export RS1_1_DB_PATH=$DB_PATH/rs1_1 10 export RS1_2_DB_PATH=$DB_PATH/rs1_2 11 export RS1_3_DB_PATH=$DB_PATH/rs1_3 12 export RS2_1_DB_PATH=$DB_PATH/rs2_1 13 export RS2_2_DB_PATH=$DB_PATH/rs2_2 14 export RS2_3_DB_PATH=$DB_PATH/rs2_3 15 16 export RS1_1_DB_LOG=$LOG_PATH/rs1_1.log 17 export RS1_2_DB_LOG=$LOG_PATH/rs1_2.log 18 export RS1_3_DB_LOG=$LOG_PATH/rs1_3.log 19 export RS2_1_DB_LOG=$LOG_PATH/rs2_1.log 20 export RS2_2_DB_LOG=$LOG_PATH/rs2_2.log 21 export RS2_3_DB_LOG=$LOG_PATH/rs2_3.log 22 23 export RS1_1_PORT=27018 24 export RS1_2_PORT=27019 25 export RS1_3_PORT=27020 26 export RS2_1_PORT=27021 27 export RS2_2_PORT=27022 28 export RS2_3_PORT=27023 29 30 export RS1=rs1 31 export RS2=rs2 32 33 #config config_server 34 export CONF1_DB_PATH=$DB_PATH/db_conf1 35 export CONF2_DB_PATH=$DB_PATH/db_conf2 36 export CONF3_DB_PATH=$DB_PATH/db_conf3 37 38 export CONF1_DB_LOG=$LOG_PATH/conf1.log 39 export CONF2_DB_LOG=$LOG_PATH/conf2.log 40 export CONF3_DB_LOG=$LOG_PATH/conf3.log 41 42 export CONF1_PORT=40000 43 export CONF2_PORT=40001 44 export CONF3_PORT=40002 45 46 export CONF1_HOST=$LOCAL:$CONF1_PORT 47 export CONF2_HOST=$LOCAL:$CONF2_PORT 48 export CONF3_HOST=$LOCAL:$CONF3_PORT 49 50 #config route_server 51 export ROUTE_DB_LOG=$LOG_PATH/route.log 52 53 export ROUTE_PORT=27017

   可以在会话窗口中将这些命令执行一遍,不过更好的方式是将其保存在一个文件中(如mongodb_define.sh),然后执行这个文件就行了:source mongodb_define.sh

启动shards(replica set)

  在这一部分,会创建两个replica set,分别是rs1, rs2。每个replica set包含三个节点,且其中一个是arbiter。由于两个replica set创建过程没什么区别,因此以rs1为例。关于replica set的搭建,可参见mongodb doc中deploy-replica-set-for-testing部分,讲得比较清楚。   step1: 首先得创建好存放数据的目录:   mkdir -p $RS1_1_DB_PATH   mkdir -p $RS1_2_DB_PATH   mkdir -p $RS1_3_DB_PATH   PS: -p means "no error if existing, make parent directories as needed"     step2: 启动组成rs1的三个mongod 

  $BIN_HOME/mongod --port $RS1_1_PORT --dbpath $RS1_1_DB_PATH --fork --logpath $RS1_1_DB_LOG --replSet $RS1 --smallfiles --nojournal
  $BIN_HOME/mongod --port $RS1_2_PORT --dbpath $RS1_2_DB_PATH --fork --logpath $RS1_2_DB_LOG --replSet $RS1 --smallfiles --nojournal
  $BIN_HOME/mongod --port $RS1_3_PORT --dbpath $RS1_3_DB_PATH --fork --logpath $RS1_3_DB_LOG --replSet $RS1 --smallfiles --nojournal

  关于mongod的启动选项,可以通过mongod --help查看,在上面的命令行中,--replSet 指定了replica set的名字, --smallfiles 声明使用更小的默认文件, --nojournal表明不开启journaling机制。注意,在这个地方不开启journaling是因为实验环境磁盘空间有限,而所有的mongod实例都在这个机器上,在生成环境中,一定要开始journaling,这个是mongodb durability的保证。      step3:初始化复制集rs1   在这一步,需要通过mongdb的客户端mongo连接到复制集的任何一个节点,对复制集初始化,这里连接到RS1_1(端口为27018):   mongo --port $RS1_1_PORT   先来看一下现在复制集的状态(PS:下面所有以 > 开头的命令行都表示是在mongo这个交互式客户端输入的指令)   > rs.status()   技术分享   可以看到这个复制集还没有初始化   >config = {

    _id : "rs1",
    members : [
      {_id : 0, host : "127.0.0.1:27018"},
      {_id : 1, host : "127.0.0.1:27019"},
      {_id : 2, host : "127.0.0.1:27020", arbiterOnly: true},
    ]
  }

  >rs.initiate(config)

  技术分享   从config和运行后的复制集状态都可以看到,RS1_3(127.0.0.1:27020)这个mongod为一个Arbiter,即只参与投票,不持久化数据。另外RS1_1为Primary, RS1_2为Secondary。   到此为止,复制集rs1就启动好了。       关于s2的启动,下面也给出所有命令。方便读者实践

  mkdir -p $RS2_1_DB_PATH
  mkdir -p $RS2_2_DB_PATH
  mkdir -p $RS2_3_DB_PATH

  $BIN_HOME/mongod --port $RS1_1_PORT --dbpath $RS1_1_DB_PATH --fork --logpath $RS1_1_DB_LOG --replSet $RS1 --smallfiles --nojournal
  $BIN_HOME/mongod --port $RS1_2_PORT --dbpath $RS1_2_DB_PATH --fork --logpath $RS1_2_DB_LOG --replSet $RS1 --smallfiles --nojournal
  $BIN_HOME/mongod --port $RS1_3_PORT --dbpath $RS1_3_DB_PATH --fork --logpath $RS1_3_DB_LOG --replSet $RS1 --smallfiles --nojournal

  mongo --port $RS2_1_PORT
  >config = {
  _id : "rs2",
  members : [
  {_id : 0, host : "127.0.0.1:27021"},
  {_id : 1, host : "127.0.0.1:27022"},
  {_id : 2, host : "127.0.0.1:27023", arbiterOnly: true},
  ]
  }
  >rs.initiate(config)

启动config servers

  mongodb官方建议config server需要三个mongod实例组成,每一个mongod最好部署在不同的物理机器上。这个三个mongod并不是复制集的关系,

  step1:创建db目录

  mkdir -p $CONF1_DB_PATH
  mkdir -p $CONF2_DB_PATH
  mkdir -p $CONF3_DB_PATH

  step2:启动三个mongod实例:

  $BIN_HOME/mongod --port $CONF1_PORT --dbpath $CONF1_DB_PATH --fork --logpath $CONF1_DB_LOG --configsvr --smallfiles --nojournal
  $BIN_HOME/mongod --port $CONF2_PORT --dbpath $CONF2_DB_PATH --fork --logpath $CONF2_DB_LOG --configsvr --smallfiles --nojournal
  $BIN_HOME/mongod --port $CONF3_PORT --dbpath $CONF3_DB_PATH --fork --logpath $CONF3_DB_LOG --configsvr --smallfiles --nojournal

  同样启动参数中nojournal只是为了节省存储空间,在生产环境中一定要使用journaling。与创建replica set时mongod的启动不同的是,这里有一个configsvr 选项,表明这些节点都是作为config server存在。

  再启动这三个mongod之后,不会有类似replica set那样讲三个mongod绑定之类的操作,也说明了config server之间是相互独立的

 

启动router

  在Sharded Cluster中,router(mongos)是应用程序连接的对象,一切对mongodb的操作都通过router来路由   step1:启动mongos     $BIN_HOME/mongos --port $ROUTE_PORT --configdb $CONF1_HOST,$CONF2_HOST,$CONF3_HOST --fork --logpath $ROUTE_DB_LOG --chunkSize 32   注意这里的可执行程序是mongos,而不是之前的mongod,关于参数,也是可以通过mongos --help查看的。在上面的命令中,--configdb选项指定了三个config server,--chunkSize指定了chunk的大小,单位为M。关于chunksize,默认是64M,虽然可以在初次启动的时候指定chunksize,但mongodb官方推荐按照以下方式修改。 在本文中将chunkSize改小的目的,是为了以后实验的时候更方便观察数据的拆分和迁移。   chunkSize事实上会持久化到config.setting中,连接到mongos可查看:   mongo --port $ROUTE_PORT    技术分享

  在上面截图蓝色框中可以看出,现在还没有任何shard的信息,原因是到现在为止,config servers与replica set还没有任何关系

    step2:将在前面创建的两个replica set(rs1 rs2)加入到Sharded Cluster中   mongo --port $ROUTE_PORT 

  mongos> sh.addShard(‘rs1/127.0.0.1:27018‘)
  mongos> sh.addShard(‘rs2/127.0.0.1:27021‘)

  PS:为什么需要在rs1后面指定一个mongod的ip port,这个是用来找到对应的mongod,继而找到相应rs

  再次查看结果:

  技术分享   可以看到已经添加了两个shard,每一个都是一个replica set。有意思的是Arbiter(比如RS1_3)并没有显示在查询结果中,可能的原因是Arbiter并不持久化数据,显示在这里也没有什么意义。     到此为止,整个Sharded Cluster就算搭建好了,但是还未进入真正使用阶段,要发挥Sharded Cluster的作用,我们得指定哪些collection可以被sharding,以及如何sharding

创建sharding key

  为了演示,我们假设添加一个db叫test_db, 其中有两个collection,一个是需要sharding的,叫sharded_col;另一个暂时不用sharding,叫non_sharded_col, 当然之后也可以增加新的集合,或者把原来没有sharding的集合改成sharding。

  一下操作都需要登录到router进行: mongo --port $ROUTE_PORT 

  step1:首先得告知mongodb test_db这个数据库支持sharding

  mongos> sh.enableSharding("test_db")
  { "ok" : 1 }

  这个时候可以查看数据库的状态,注意,是在config这个db下面的databases集合

  mongos> use config

  mongos> db.databases.find()   { "_id" : "admin", "partitioned" : false, "primary" : "config" }   { "_id" : "test_db", "partitioned" : true, "primary" : "rs1" }   从查询结果可以看到,test_db是支持sharding的("partitioned" : true)。另外上面加粗部分primary: rs1,这个primary与replica set里面的primary不是一回事,这里的primary是primary shard的意思,我们知道即使在sharded cluster环境中,一些数据量比较小的db也是无需分片的,这些db默认就存放在primary shard上面     step2:为需要的collection(即这里的sharded_col)指定sharding key   前面已经提到了sharding key的作用,关于sharding key的选择,是一个比较复杂的问题,sharding key对索引,对CRUD语句的操作都有诸多限制,这一部分以后再细讲,在这里默认使用_id做sharding key(_id是mongodb默认为每个集合增加的索引)   mongos> sh.shardCollection(‘test_db.sharded_col‘, {‘_id‘: 1})   接下来看看整个sharded cluster的状态:

  技术分享

  sh.status()反应的内容事实上也是来自config整个数据库的内容,只不过做了一定程度的整合。从上面可以看到,有两个shard,rs1, rs2;test_db允许sharding,test_db.sharded_col整个collection的sharding key为{"_id": 1},且目前只有一个chunk在rs1整个shard上。

总结:

  到目前为止,我们已经搭建了一个有三个config server,两个shard的sharded cluster,其中每一个shard包含三个节点的replica set,且都包含一个Arbiter。我们可以查看一下刚创建好之后各个mongod实例持久化的数据大小:

  技术分享

  可以看到,两个Arbiter(rs1_3, rs2_3)所占的空间要小得多。

  对于应用程序来说,集群(sharded cluster)和单点(standalone)是有一定差异的,如果需要发挥sharded cluster高性能、高可用的特点,需要根据应用场景精心选择好sharding key,而sharding key的选择跟索引的建立以及CRUD语句息息相关,这一部分以后再聊。对于目前搭建的这个实例,简单测试的话,往sharded_col插入足够多条document就能看到chunks的拆分和迁移。

 

references:

db engines

the-id-field

replication-introduction

deploy-replica-set-for-testing

deploy-shard-cluster

通过一步步创建sharded cluster来认识mongodb

标签:exist   .sh   migrate   分解   prim   rate   ide   应用   演示   

人气教程排行