• 分片集群


    mongodb分片+副本集方式部署集群

    介绍

    背景:mongodb集群搭建方式有三种,1、主从(官方已经不推荐),2、副本集,3、分片。这里介绍如何通过分片sharding方式搭建mongodb集群。sharding集群方式也基于副本集,在搭建过程中,需要对分片和配置节点做副本集。最后将做好的副本集的分片加入到路由节点,构成集群。

    sharding方式的集群中,有三类角色,分别是shard,config,router。如下图所示。

    一、配置准备

    创建存放数据的文件夹

    mkdir -p /usr/local/software/mongodb/mongo-cluster/data/shard01
    mkdir -p /usr/local/software/mongodb/mongo-cluster/data/shard02
    mkdir -p /usr/local/software/mongodb/mongo-cluster/data/shard21
    mkdir -p /usr/local/software/mongodb/mongo-cluster/data/shard22
    mkdir -p /usr/local/software/mongodb/mongo-cluster/data/config
    mkdir -p /usr/local/software/mongodb/mongo-cluster/data/config2
    mkdir -p /usr/local/software/mongodb/mongo-cluster/data/config3
    

    shard01.conf

    port=27018
    fork=true
    dbpath=/usr/local/software/mongodb/mongo-cluster/data/shard01
    logpath=/usr/local/software/mongodb/mongo-cluster/logs/shard01.log
    logappend=true
    bind_ip=127.0.0.1
    # 设置副本集名称
    replSet=shard1
    # 声明这是一个集群的分片
    shardsvr=true
    

    shard02.conf

    port=27019
    fork=true
    dbpath=/usr/local/software/mongodb/mongo-cluster/data/shard02
    logpath=/usr/local/software/mongodb/mongo-cluster/logs/shard02.log
    logappend=true
    bind_ip=127.0.0.1
    # 设置副本集名称
    replSet=shard1
    # 声明这是一个集群的分片
    shardsvr=true
    

    两个shard实例

    shard21.conf

    port=27118
    fork=true
    dbpath=/usr/local/software/mongodb/mongo-cluster/data/shard21
    logpath=/usr/local/software/mongodb/mongo-cluster/logs/shard21.log
    logappend=true
    bind_ip=127.0.0.1
    # 设置副本集名称
    replSet=shard2
    # 声明这是一个集群的分片
    shardsvr=true
    

    shard22.conf

    port=27119
    fork=true
    dbpath=/usr/local/software/mongodb/mongo-cluster/data/shard22
    logpath=/usr/local/software/mongodb/mongo-cluster/logs/shard22.log
    logappend=true
    bind_ip=127.0.0.1
    # 设置副本集名称
    replSet=shard2
    # 声明这是一个集群的分片
    shardsvr=true
    

    config.conf

    port=27117
    fork=true
    dbpath=/usr/local/software/mongodb/mongo-cluster/data/config
    logpath=/usr/local/software/mongodb/mongo-cluster/logs/config.log
    logappend=true
    bind_ip=127.0.0.1
    # 设置副本集名称
    replSet=config
    # 声明这是一个集群的config服务
    configsvr=true
    

    config2.conf

    port=27217
    fork=true
    dbpath=/usr/local/software/mongodb/mongo-cluster/data/config2
    logpath=/usr/local/software/mongodb/mongo-cluster/logs/config2.log
    logappend=true
    bind_ip=127.0.0.1
    # 设置副本集名称
    replSet=config
    # 声明这是一个集群的config服务
    configsvr=true
    

    config3.conf

    port=27317
    fork=true
    dbpath=/usr/local/software/mongodb/mongo-cluster/data/config3
    logpath=/usr/local/software/mongodb/mongo-cluster/logs/config3.log
    logappend=true
    bind_ip=127.0.0.1
    # 设置副本集名称
    replSet=config
    # 声明这是一个集群的config服务
    configsvr=true
    

    router.conf

    port=27017
    # 路由节点与元信息节点(config)关联
    configdb=config/127.0.0.1:27117,127.0.0.1:27217,127.0.0.1:27317
    logpath=/usr/local/software/mongodb/mongo-cluster/logs/router.log
    fork=true
    logappend=true
    bind_ip=0.0.0.0
    

    关于配置文件说明

    shard01.conf, shard02.conf是shard1分片的配置。

    shard21.conf, shard22.conf是shard2分片的配置。

    config.conf, config2.conf, config3.conf是config节点配置。

    二、启动分片节点和配置节点

    # 启动分片节点27018 和 27019
    /usr/local/software/mongodb/bin/mongod -f /usr/local/software/mongodb/mongo-cluster/conf/shard01.conf 
    /usr/local/software/mongodb/bin/mongod -f /usr/local/software/mongodb/mongo-cluster/conf/shard02.conf 
    
    # 启动分片节点 27118 和 27119
    /usr/local/software/mongodb/bin/mongod -f /usr/local/software/mongodb/mongo-cluster/conf/shard21.conf 
    /usr/local/software/mongodb/bin/mongod -f /usr/local/software/mongodb/mongo-cluster/conf/shard22.conf 
    
    # 启动配置节点 27117、27217、27317
    /usr/local/software/mongodb/bin/mongod -f /usr/local/software/mongodb/mongo-cluster/conf/config.conf 
    /usr/local/software/mongodb/bin/mongod -f /usr/local/software/mongodb/mongo-cluster/conf/config2.conf 
    /usr/local/software/mongodb/bin/mongod -f /usr/local/software/mongodb/mongo-cluster/conf/config3.conf 
    

    或者如下(不需要配置文件)

    /usr/local/software/mongodb/bin/mongod -f --port 27018 --dbpath /usr/local/software/mongodb/mongo-cluster/data/shard01 --logpath=/usr/local/software/mongodb/mongo-cluster/logs/shard01.log --replSet shard1 --shardsvr --smallfiles --fork
    
    /usr/local/software/mongodb/bin/mongod -f --port 27019 --dbpath /usr/local/software/mongodb/mongo-cluster/data/shard02 --logpath=/usr/local/software/mongodb/mongo-cluster/logs/shard02.log --replSet shard1 --shardsvr --smallfiles --fork
    
    # 下面两个shard2分片节点
    /usr/local/software/mongodb/bin/mongod -f --port 27118 --dbpath /usr/local/software/mongodb/mongo-cluster/data/shard21 --logpath=/usr/local/software/mongodb/mongo-cluster/logs/shard21.log --replSet shard2 --shardsvr --smallfiles --fork
    
    /usr/local/software/mongodb/bin/mongod -f --port 27119 --dbpath /usr/local/software/mongodb/mongo-cluster/data/shard22 --logpath=/usr/local/software/mongodb/mongo-cluster/logs/shard22.log --replSet shard2 --shardsvr --smallfiles --fork
    
    # 下面三个config
    /usr/local/software/mongodb/bin/mongod -f --port 27117 --dbpath /usr/local/software/mongodb/mongo-cluster/data/config --logpath=/usr/local/software/mongodb/mongo-cluster/logs/config.log --replSet config --shardsvr --smallfiles --fork
    
    /usr/local/software/mongodb/bin/mongod -f --port 27217 --dbpath /usr/local/software/mongodb/mongo-cluster/data/config2 --logpath=/usr/local/software/mongodb/mongo-cluster/logs/config2.log --replSet config --shardsvr --smallfiles --fork
    
    /usr/local/software/mongodb/bin/mongod -f --port 27317 --dbpath /usr/local/software/mongodb/mongo-cluster/data/config3 --logpath=/usr/local/software/mongodb/mongo-cluster/logs/config3.log --replSet config --shardsvr --smallfiles --fork
    

    三、配置节点构成副本集

    进入到config的节点

    /usr/local/software/mongodb/bin/mongo -port 27117
    > var config = {_id:'config',members:[{_id:0,host:'127.0.0.1:27117'},{_id:1,host:'127.0.0.1:27217'},{_id:2,host:'127.0.0.1:27317'}]}
    > rs.initiate(config)
    > rs.status() // 查看状态
    

    配置分片之后,等待10S左右,当前节点会变为primary节点。

    四、分片节点构成副本集

    登陆127.0.0.01:27018

    /usr/local/software/mongodb/bin/mongo --port 27018

    > var config = {_id:'shard1',members:[{_id:0,host:'127.0.0.1:27018'},{_id:1,host:'127.0.0.1:27019'}]}
    > rs.initiate(config)
    > rs.status()
    

    接着登陆 127.0.0.1:27118

    /usr/local/software/mongodb/bin/mongo --port 27118

    > var config = {_id:'shard2',members:[{_id:0,host:'127.0.0.1:27118'},{_id:1,host:'127.0.0.1:27119'}]}
    > rs.initiate(config)
    

    两个分片shard,shard2设置成功之后,等待10s左右就会发现当前节点默认变为了当前分片的primary节点。

    五、启动路由节点、并增加分片

    启动路由mongo

    /usr/local/software/mongodb/bin/mongos -f /usr/local/software/mongodb/mongo-cluster/conf/router.conf
    
    /usr/local/software/mongodb/bin/mongos --port 27017  
    --configdb config/127.0.0.1:27117,127.0.0.1:27217,127.0.0.1:27317 
    --logpath=/usr/local/software/mongodb/mongo-cluster/logs/router.log 
    --fork --logappend --bind_ip=0.0.0.0
    

    登陆之后可以看到有个config的数据库 show dbs

    config数据库中的集合包含了整个集群的配置信息。执行命令show collections(或show tables) ,我们可以看到有如下集合。

    mongos> show collections
    changelog //保存被分片的集合的任何元数据的改变,例如chunks的迁移、分割等。
    chunks //保存集群中分片集合的所有块的信息,包含块的数据范围与块所在的片。
    databases //保存数据库中的所有数据库,包含分片与未分片的。
    lockpings //保存跟踪集群中的激活组件。
    locks //均衡器balancer执行时产生锁,在此集合中插入一条记录。 可得知哪个mongos是均衡器
    migrations 
    mongos //保存了集群中所有路由mongos的信息。nginx
    shards //保存了集群中的所有片的信息。
    tags  // 分片标签
    version //保存当前所有信息的所有片信息。
    

    增加分片格式如下: "shard1/127.0.0.1:27018,127.0.0.1:27019"

    # 登陆mongo
    /usr/local/software/mongodb/bin/mongo --port 27017
      # 串联路由服务器与分配副本集
    mongos> sh.addShard("shard1/127.0.0.1:27018,127.0.0.1:27019")
    mongos> sh.addShard("shard2/127.0.0.1:27118,127.0.0.1:27119")
    

    查看集群状态 sh.status()

    mongos> sh.status()
    --- Sharding Status --- 
      sharding version: {
      	"_id" : 1,
      	"minCompatibleVersion" : 5,
      	"currentVersion" : 6,
      	"clusterId" : ObjectId("5da028fabb2fbb93f8991ab1")
      }
      shards:  // 这里是刚才的两个分片集
            {  "_id" : "shard1",  "host" : "shard1/127.0.0.1:27018,127.0.0.1:27019",  "state" : 1 }
            {  "_id" : "shard2",  "host" : "shard2/127.0.0.1:27118,127.0.0.1:27119",  "state" : 1 }
     ...
    

    六、设置数据库启用分片,启用索引。

    在mongos的客户端下

    mongos> use admin
    # 分片指定数据库
    mongos> sh.enableSharding("shop")
    # 指定数据库里需要分片的集合和片键
    sh.shardCollection("shop.goods", {id:1})
    

    如果MongoDB报"sharding already enabled for collection xxx"的错误

    1. 进入到
    2. 查看数据库的集合是否已经存在分片
    3. 删除
    mongos> use config
    mongos> db.chunks.find({},{ns:1})  #查看
    mongos> db.chunks.remove({ns:"shop.goods"})  # 删除
    
    mongos> db.collections.remove( { _id: "shop.goods" } )
    mongos>db.locks.remove( { _id: "shop.goods" } 
    

    七、写入数据测试。

    进入push库

    mongos> use shop
    mongos> for(var i=1;i<=15000;i++){db.goods.save({_id:i,id:i, name:"user"})}
    mongos> sh.status()
    mongos> db.shop.status()
    

    分别登陆shard1分片集 和 shard2分片集查看数据分配状态

    /usr/local/software/mongodb/bin/mongo --port 27018
    use shop
    db.goods.count()
    
    /usr/local/software/mongodb/bin/mongo --port 27118
    use shop
    db.goods.count()
    

    七、手动预先分片

    预先决定可以装多少条数据 和 决定片数

    以shop.user表为例

    // user表  用 userid作片键
    mongos> sh.shardCollection("shop.user", {userid:1})  
    
    //预先在1k,2k...,40k这样的位置切好快
    mongos> for(var i = 1; i<=40;i++) {sh.splitAt('shop.user',{userid:i*1000})}
    // 添加数据
    mongos> for(var i=1; i<=40000; i++) {db.user.insert({"userid":i, "name":"xiao ming"})}
    

    切好块后,这些分割好的chunk是空的

    通过mongos可以添加user数据,这些数据会添加到预先分配好的片, chunk就不会来回移动了

    使用脚本的方式启动集群:

    start.sh

    #!/bin/sh
    
    # 分别是 集群数据存放的文件夹, 配置文件所在的文件夹, mongodb的bin目录
    dataPath=/usr/local/software/mongodb/mongo-cluster/data
    configPath=/usr/local/software/mongodb/mongo-cluster/config
    mongoRoot=/usr/local/software/mongodb/bin
    # 集群内部使用的ip 这里都在一台集器上,使用同一个ip,一般一个副本集一个ip
    IP=127.0.0.1
    # 集群暴露的端口
    rotuePort=27017
    if [ "${1}x" == 'resetx' ]; then 
    	pkill -9 mongo	# 杀mongo相关的进程
    
        rm -rf /usr/local/software/mongodb/mongo-cluster/data/*/*	# 删数据
        rm -rf /usr/local/software/mongodb/mongo-cluster/logs/*	# 删日志
    	
        mkdir -p /usr/local/software/mongodb/mongo-cluster/data/shard01
        mkdir -p /usr/local/software/mongodb/mongo-cluster/data/shard02
        mkdir -p /usr/local/software/mongodb/mongo-cluster/data/shard21
        mkdir -p /usr/local/software/mongodb/mongo-cluster/data/shard22
        mkdir -p /usr/local/software/mongodb/mongo-cluster/data/config
        mkdir -p /usr/local/software/mongodb/mongo-cluster/data/config2
        mkdir -p /usr/local/software/mongodb/mongo-cluster/data/config3
    
    	exit;
    fi
    
    # 第一个参数为上一个命令的执行结果(正确0/不正确其它数字), 第二个参数为失败后的错误信息
    function validate() {
        if [[ $1 != 0 ]]; then
          echo $2
          exit 1
        fi
    }
    
    # 端口
    portArr=(27018 27019  27118 27119  27117 27217 27317)
    # 数据保存位置
    dataArr=(shard01 shard02  shard21 shard22  config config2 config3)
    # 所属的副本集
    replArr=(shard1 shard1  shard2 shard2  config config config)
    # 机器类型 shardsvr分片 configsvr 代表meta信息配置
    hostType=(shardsvr shardsvr  shardsvr shardsvr  configsvr configsvr configsvr)
    
    for ((i=0; i<${#portArr[*]};i++)); do
       /usr/local/software/mongodb/bin/mongod --port ${portArr[$i]} 
       --dbpath  /usr/local/software/mongodb/mongo-cluster/data/${dataArr[$i]} 
       --logpath=/usr/local/software/mongodb/mongo-cluster/logs/${dataArr[$i]}.log 
       --replSet ${replArr[$i]} --${hostType[$i]} --smallfiles --fork >/dev/null 2>&1
       validate $? "===副本${replArr[$i]},类型${hostType[$i]},端口${portArr[$i]}启动失败!==="
       echo "===副本${replArr[$i]},类型${hostType[$i]},端口${portArr[$i]}启动成功!==="
    done
    # replSet: 设置副本集名称
    # ${hostType[$i]} (shardsvr configsvr): 表示当前集器是分片还是配置
    # smallfiles 减少数据文件的初始大小
    # fork 后台启动
    
    # 构建分片副本集1(shard1) 27018 27019
    /usr/local/software/mongodb/bin/mongo --port ${portArr[0]} << EOF
    var config = {_id:"${replArr[0]}",members:[
        {_id:0,host:"${IP}:${portArr[0]}"},
        {_id:1,host:"${IP}:${portArr[1]}"}
    ]}
    rs.initiate(config)
    EOF
    validate $? "===副本集${replArr[0]},IP:${IP}启动失败!==="
    echo "===副本集${replArr[0]},IP:${IP}启动成功!==="
    
    # 构建分片副本集2(shard2) 27118 27119
    /usr/local/software/mongodb/bin/mongo --port ${portArr[2]} << EOF
    var config = {_id:"${replArr[2]}",members:[
    	{_id:0,host:"${IP}:${portArr[2]}"},
    	{_id:1,host:"${IP}:${portArr[3]}"}
    ]}
    rs.initiate(config)
    EOF
    validate $? "===副本集${replArr[2]},IP:${IP}启动失败!==="
    echo "===副本集${replArr[2]},IP:${IP}启动成功!==="
    
    # 配置config节点的副本集 27117 27217 27317
    /usr/local/software/mongodb/bin/mongo -port ${portArr[4]} << EOF
    var config = {_id:"${replArr[4]}",members:[
    	{_id:0,host:"${IP}:${portArr[4]}"},
    	{_id:1,host:"${IP}:${portArr[5]}"},
    	{_id:2,host:"${IP}:${portArr[6]}"}
    ]}
    rs.initiate(config)
    EOF
    validate $? "===副本集${replArr[4]},IP:${IP}启动失败!==="
    echo "===副本集${replArr[4]},IP:${IP}启动成功!==="
    
    # 启动mongos(路由节点) 27017 与config关联(管理集群配置等元数据的节点)
    /usr/local/software/mongodb/bin/mongos --port ${rotuePort}  
    --configdb config/"${IP}:${portArr[4]}","${IP}:${portArr[5]}","${IP}:${portArr[6]}" 
    --logpath=/usr/local/software/mongodb/mongo-cluster/logs/router.log 
    --fork --logappend --bind_ip=0.0.0.0 >/dev/null 2>&1
    validate $? "===路由节点mongos,IP:${IP},端口:${rotuePort}启动失败!==="
    echo "===路由节点mongos,IP:${IP},端口:${rotuePort}启动成功!==="
    
    # 添加分片节点 shard1 shard2 与分片节点关联(管理真实数据的节点)
    /usr/local/software/mongodb/bin/mongo --port ${rotuePort} << EOF
    use admin
    sh.addShard("${replArr[0]}/${IP}:${portArr[0]},${IP}:${portArr[1]}")
    sh.addShard("${replArr[2]}/${IP}:${portArr[2]},${IP}:${portArr[3]}")
    EOF
    
    # 测试(不是必须的)
    /usr/local/software/mongodb/bin/mongo --port ${rotuePort} << EOF
    use admin
    sh.enableSharding("shop")
    sh.shardCollection("shop.goods", {id:1})
    use shop
    for(var i=1;i<=15000;i++){db.goods.insert({id:i, name:"hello world how are you i am fine thanks!"})}
    EOF
    

    集群测试

    对shop数据库进行分片

    对shop数据库中的goods集合分片 片键为id 一般为主键

    切换到分片数据库 并添加测试数据

    登陆到mongs查看集群状态

    /usr/local/software/mongodb/bin/mongo --port 27017
    mongos> sh.status()
    

    查看分片节点上的数据

    # 登陆到shard1查看数据
    /usr/local/software/mongodb/bin/mongo --port 27018 << EOF
    use shop
    db.user.count()
    EOF
    # 登陆到shard2查看数据
    /usr/local/software/mongodb/bin/mongo --port 27118 << EOF
    use shop
    db.user.count()
    EOF
    

    参考教程

  • 相关阅读:
    【Windows】netsh动态配置端口转发
    Python 脚本注册为Windows Service
    【Windows】Python脚本随机启动
    【MySQL】CSV 文件导入MySQL
    【Python】改变对象的字符串显示
    【Python】偏函数
    【Python】装饰器理解
    【Python】什么是闭包
    【Python】高阶函数介绍
    【Python】__all__ 暴露接口
  • 原文地址:https://www.cnblogs.com/qiaozhuangshi/p/11668640.html
Copyright © 2020-2023  润新知