zoukankan      html  css  js  c++  java
  • MongoDB集群之分片技术应用 —— 学习笔记

    课程链接:https://www.imooc.com/learn/501

    一、什么是分片?

    分片:将数据进行2拆分,将数据水平的分散到不同的服务器上。

    二、为什么要分片?

    • 架构上:读写均衡、去中心化
    • 结构上:12节点(version<=2.6)
    • 硬件上:内存、硬盘容量限制

    分片目的

    改善单台机器数据的存储及数据吞吐性能。
    提高在大量数据下随机访问性能。

    分片(Shard)、副本集(Replication)集群对比

    成员节点介绍

    • Shard节点:存储数据的节点(单个mongod或者副本集)
    • Config server:存储元数据,为mongos服务,将数据路由到Shard。
    • Mongos:接受前端请求,进行对应消息路由。

    成员组合图:

    成员节点启动参数

    Shard节点:

    • mongod --shardsvr
    • mongod --shardsvr --rpelSet 副本集

    Config server:

    • mongod --configsvr

    Mongos:

    • mongos —— configdb <configdb server>

    课程使用系统:Red Hat Enterprise Linux Server release 6.4 (Santiago)
    课程使用MongoDB版本:v3.0.4

    启动Shard(10.156.11.233):

    mongod --shardsvr --logpath=/opt/data/logs/shard.log -logappend --dbpath=/opt/mdb/ --fork --port 27017
    

    查看mongod Shard有没有启动起来:

    ps -aux | grep mongod
    netstat -luntp | grep 27017
    

    启动Config(10.156.11.233):

    mongod --configsvr --logpath=/opt/data/logs/config.log --logappend --dbpath=/opt/config --fork --port 27018
    

    查看mongod Config有没有启动起来:

    netstat -luntp | grep mongo
    ps -aux | grep mongod
    

    启动Mongos(10.156.11.232):

    mongos --port 27017 --logappend --logpath=/opt/data/logs/mongos.log --configdb 10.156.11.233:27018 --fork
    

    查看Mongos有没有启动起来:

    netstat -luntp | grep 27017
    ps -aux | grep mongos
    

    添加分片过程

    步骤一、连接到mongos
    步骤二、Add Shards
    步骤三、Enable Sharding
    步骤四、对一个集合进行分片

    步骤二、Add Shards

    1. 单个数据库实例:
      { addShard: "<hostname> <:port>", maxSize: <size>, name: "<shard_name>"}
    2. 副本集群:
      { addShard: "<replica_set>/<hostname> <:port>", maxSize:<size>, name: "shard_name" }
    3. 如果你的mongos和shard在同一台机器上,添加分片不能使用“localhost”,建议使用IP。

    步骤四、对一个集合进行分片

    1. db.runCommand
      ({shardcollection: " <namespoace>", key: " <key>"})
    2. unique: " true/false"
      启动对shard key的唯一性约束
    3. shard key选择

    在10.156.11.232上的操作
    这台电脑之前已经启动了mongos服务
    输入如下指令登陆mongos:

    mongo 127.0.0.1:27017
    

    在mongos命令行下执行如下命令,将10.156.11.232上的mongod添加进来:

    mongos> use admin
    mongos> db.runCommand({"addShards":"10.156.11.233:27017"})
    

    其他:
    查看目前有几个数据库的mongos命令:

    mongos> show dbs;
    

    创建名为“shardtest”的数据库的mongos命令:

    mongos> use shardtest
    

    测试在数据库shardtest中的集合userid中插入测试数据的例子:

    mongos> for(i=0;i<10000;i++){db.shardtest.userid.insert({"user_id":i})};
    

    采用如下命令来Enable刚才创建的名为“shardtest”的Sharding:

    mongos> use admin
    mongos> db.runCommand({enablesharding:"shardtest"})
    

    不过这个时候它会报一个这样的错误:

    { "ok": 0, "errmsg": "already enabled" }
    

    使用如下命令启用shardtest数据库的userid集合对应的分片,将根据键user_id来进行分片:

    mongos> db.runCommand({"shardcollection":"shardtest.userid",key:{"user_id":1}})
    

    其中,"user_id"对应的1表示是按照升序来进行分片。

    分片测试

    在mongos命令行执行如下命令:

    mongos> use config
    mongos> db.shards.find()
    
    1. 查看集合状态:
    > use shardtest
    > db.userid.stats()
    
    1. 查看分片状态:
    db.printShardingStatus()
    
    1. 写入数据测试:
    for (var i=1;i<10000000;i++>){db.userid.insert(user_id:i)}
    

    什么是分片片键:

    集合里面选一个键,用该键的值作为数据拆分的依据。

    什么是Chunk:

    MongoDB分片后,存储数据的但愿快,默认大小:64MB。

    Chunk拆分

    数据块(chunk)的拆分:
    记录每个块中插入多少数据,一旦达到某个阈值,执行检查是否需要拆分块,需要则更新config服务器上这个块的元信息。

    Balancing

    数据块平衡:
    均衡器负责数据的迁移,会周期性的检查分片是否存在不均衡,如果存在则会进行块的迁移。
    注意:均衡器进行均衡的条件是 块数量的多少 ,而不是块大小。

    哈希分片

    哈辛分片(hash key):
    分片过程中利用哈希索引作为分片的单个键。

    • 哈希分片的片键只能使用一个字段
    • 哈希片键最大的好处就是保证数据在各个节点分布基本均匀
      shardcollection ==> {userid:"hashed"}

    233上进行如下操作来进行分片:

    mongos> db.userid_hash.insert({userid:11})
    mongos> db.userid_hash.insert({userid:22})
    mongos> use shardtest
    mongos> db.userid_hash.ensureIndex({userid:"hash"})
    mongos> use admin
    mongos> db.runCommand({"shardcollection":"shardtest.userid_hash","key":{userid:"hashed"}})
    

    插入一些数据进行测试:

    mongos> use shardtest
    mongos> for(i=0;i<100000;i++>{db.userid_hash.insert({userid:i})})
    

    查看效果:

    mongos> use shardtest
    mongos> db.userid_hash.stats()
    mongos> db.printShardingStatus()
    

    如何选择合适片键

    选择片键的好坏很大程度上影响集群的性能,容量和功能。

    考虑因素一、数据块的大小
    印象:片键相同导致数据块不拆分,容易形成大的数据块,导致数据不均。

    考虑因素二、数据写均匀分布
    影响:单调递增的_id或时间戳作为片键,这样将会导致你一直往最后一个副本集中添加数据。

    请求查询机制

    方式一、Routed Request

    方式二、Scatter Gather Request

    方式三、Distributed Merge Sort Req

    手动分片

    为什么要手动分片?
    为了减少自动平衡过程带来的IO等资源消耗。

    前提:

    1. 关闭自动平衡,关闭auto balence;
    2. 充分了解数据,并对数据进行预先划分。

    步骤一、关闭自动平衡
    关闭方式:sh.stopBalancer()
    (启动方式:sh.startBalancer()
    此时平衡器状态:CurrentLy enabled: no

    步骤二、分片切割

    > use admin
    > db.runCommand({"enablesharding":"myapp"})
    > db.runCommand({"shardcollection":"myapp.users","key":{"email":1}})
    for (var x=97;x<97+26;x++) {
        for (var y=97;y<97+26;y+=6) {
            var prefix = String.fromCharCode(x) + String.fromCharCode(y);
            db.runCommand({
                split: "myapp.users",
                middle: { email: prefix }
            });
        }
    }
    

    步骤三、手动移动分割快

    var shServer = [
        "ShardServer 1",
        "ShardServer 2",
        "ShardServer 3",
        "ShardServer 4",
        "ShardServer 5",
    ]
    for (var x=97;x<97+26;x++) {
        for (var y=97;y<97+26;y+=6) {
            var prefix = String.fromCharCode(x) + String.fromCharCode(y);
            db.runCommand({
                moveChunk: "myapp.users",
                find: { email: prefix },
                to: shServer[(y-97)/6]
            });
        }
    }
    

    实践:
    首先登陆233的mongos
    执行如下命令来关闭平衡:

    mongos> sh.stopBalancer()
    

    然后执行下面代码:

    mongos> for (var x=97;x<97+26;x++) {
        for (var y=97;y<97+26;y+=6) {
            var prefix = String.fromCharCode(x) + String.fromCharCode(y);
            db.runCommand({
                split: "myapp.users",
                middle: { email: prefix }
            });
        }
    }
    mongos> var shServer = [
        "10.156.11.232:27016",
        "10.156.11.232:27017",
        "10.156.11.232:27016",
        "10.156.11.232:27017",
        "10.156.11.232:27016",
    ]
    mongos> for (var x=97;x<97+26;x++) {
        for (var y=97;y<97+26;y+=6) {
            var prefix = String.fromCharCode(x) + String.fromCharCode(y);
            db.runCommand({
                moveChunk: "myapp.users",
                find: { email: prefix },
                to: shServer[(y-97)/6]
            });
        }
    }
    

    常用部署场景

    场景一

    场景二

    考虑因素:
    一、预估数据增长量
    二、预估集群的访问量
    三、预估投入成本(硬件、人员维护等)

    场景一部署

    机器规划:

    三台电脑均相同方式启动如下服务:

    mongod --fork --logpath=/opt/data/logs/mongod27018.log -logappend --dbpath=/opt/mdb27018/ --port 27018 --replSet imooc1
    mongod --fork --logpath=/opt/data/logs/mongod27019.log -logappend --dbpath=/opt/mdb27019/ --port 27019 --replSet imooc1
    mongod --fork --logpath=/opt/data/logs/mongod27020.log -logappend --dbpath=/opt/mdb27020/ --port 27020 --replSet imooc1
    

    在173节点,执行如下命令进入mongod:

    mongo 127.0.0.1:27018
    

    在命令行执行如下指令:

    cfg = {
        _id: 'imooc1', members: [
            { _id: 0, host: '10.156.11.173:27018' },
            { _id: 1, host: '10.156.11.232:27018' }
        ]
    }
    
    rs.initiate(cfg)
    
    rs.addArb("10.156.11.233:27018")
    

    另外两台电脑的配置类似,此处略。

    通过如下命令查看每一个副本集的成员状态:

    re.status()
    

    接下来完成对分片的配置(也就是启动configsvr),
    在清空之前,我要确认我的configsvr的logpath目录存在,并且log信息是空的:

    rm -rf /opt/data/config/*
    

    然后启动configsvr:

    mongod --configsvr --logpath=/opt/data/logs/config.log --logappend /opt/data/config --fork --port 27016
    

    在三台电脑上都这么进行启动configsvr的操作。

    接下来启动mongos,
    这一步需要将所有的configsvr的配置都加上,
    如下:

    mongos --port 27017 --logappend --logpath=/opt/data/logs/mongos.log --configdb 10.156.11.233:27016,10.156.11.232:27016,10.156.11.173:27016 --fork
    

    同样的,我们可以登陆mongos服务:

    mongo 127.0.0.1:27017
    

    这样我们就顺利地把mongos服务启动起来。

    接下来登陆到(233上的)mongos上,把我们的成员节点添加进来:
    在命令行下执行mongo进入mongos命令行,然后执行如下命令来进行分片配置操作:

    mongos> use admin
    mongos> db.runCommand({addshard:"imooc1/10.156.11.173:27018,10.156.11.232:27018",name:"shard1",maxsize:20480});
    mongos> db.runCommand({addshard:"imooc2/10.156.11.232:27019,10.156.11.233:27019",name:"shard2",maxsize:20480});
    mongos> db.runCommand({addshard:"imooc3/10.156.11.233:27020,10.156.11.173:27020",name:"shard3",maxsize:20480});
    

    创建一个测试库:

    mongos> use myimooc
    mongos> db.user.insert({userid:1,name:"zifeiy",email:"zifeiy@123.com"})
    mongos> db.runCommand({ enablesharding:"zifeiy"})
    mongos> db.runCommand({"shardcollection":"zifeiy.user","key":{email:1}});
    
  • 相关阅读:
    ReportViewer,RDLC 报表开发之分页
    Mvc2.0 处理自定义错误.
    使用 WPS中粘贴VS里的代码,并整理格式
    Sql2008中添加程序集.
    快速整理列说明.SQL2008.
    ASP.NET MVC在IIS6下部署的小技巧
    MS SQL Server将数据导出Insert语句的存储过程
    在IE6下发生Internet Explorer cannot open the Internet site错误
    Windows7 中配置IIS7的方法(HTTP 错误 404.3 Not Found)
    安卓2.2手动开启APP2SD方法
  • 原文地址:https://www.cnblogs.com/zifeiy/p/9671238.html
Copyright © 2011-2022 走看看