zoukankan      html  css  js  c++  java
  • Mongodb学习笔记--分片集群

    mongodb 分片技术

    在mongodb中存在另一种集群技术--分片技术。用于解决mongodb数量大的需求。 当mongodb中存在海量数据时,一台服务器可能不足以存储数据,也肯能不足以提供可接受的吞吐量。此时就可以在多台数据上分割数据,使得数据库能存放更多的数据。

    为什么使用分片技术?

    • 在mongodb副本集中,所有的写入操作都在主节点。客户端只与主节点打交道,那么如果数据量非常大/访问频率非常高的话,主节点的压力就会非常大。
    • 副本集的节点数量限制。
      官方文档给出:mongodb单个副本集下所有节点不能超过50个,投票节点不能超过7个
    • 当请求量巨大时,可能会出现内存不足。
      使用NoSql数据库的一个重要原因就是内存数据库,效率高,但是数据量过大时就会出现内存不足的情况。
    • 本地磁盘不足。 mongodb的数据也会持久化在本地硬盘上,如果数据量非常大,就会出现本地磁盘不足的情况
    • 垂直拓展价格昂贵 垂直拓展:增加更多的cpu和存储资源来扩展容量 

    高数据量和高吞吐量回对单机造成很大的压力,解决办法:
    水平拓展:将数据集分布在多个服务器上,即水平切片。 垂直拓展。

    分片技术的组件

    mongodb的分片设计主要包含三个组件, 

    shard: 用于存储实际的数据块。实际生产环境中一个shard server角色可以由多个节点组成一个副本集承担,防止节点故障。
    config server: 所有存取数据的方式,所有shard节点的信息,分片功能的配置信息。config sever是由一组至少三个的Mongodbs实例组成的集群。
    query Routers: 前端路由,客户端由此接入。路由没有任何数据,请求过来后会直接找config server,由config server决定去哪儿个分片取数据,以及怎么取数据。
    

    由上面图片可以大概分析请求的流程:
    客户端请求到router, 然后router调用config server获取到数据的位置, 然后router会直接找到存放数据的shard来存取数据。

    分片技术的实现

    受电脑配置限制,我启动三台服务器: 192.168.226.130, 192.168.226.131, 192.168.226.132分别安装mongodb。
    节点分布如下:

    shard1: 192.168.226.131:27017
    shard2: 192.168.226.131:27018
    shard3: 192.168.226.131:27019
    
    shard4: 192.168.226.132:27017
    shard5: 192.168.226.132:27018
    shard6: 192.168.226.132:27019
    
    config server:192.168.226.130:27017
    
    

    shard节点启动

    分别在节点上创建数据库文件夹:
      在s1下创建文件:mongodb-shard.conf 并编辑如下内容:

    dbpath=/data/s1
    logpath=/data/log/mongodb-s1.log
    logappend=true
    fork=true
    bind_ip=192.168.226.131
    port=27017
    

    修改信息复制到其他的文件夹下。 分别启动各个shard节点

    [root@mongodb2 data]# mongod -f /data/s1/mongodb-shard.conf
    ......
    [root@mongodb3 data]# mongod -f /data/s6/mongodb-shard.conf
    

    查看节点启动状态:
     

    config节点启动

    在192.168.226.130 节点下创建/data/config 数据库,并添加配置文件:mongodb-config.conf

    dbpath=/data/config
    logpath=/data/log/mongodb-config.log
    logappend=true
    fork=true
    bind_ip=192.168.226.130
    port=27017
    

    创建mongos文件,添加mongodb-mongos.conf文件,文件内容:

    port=27018
    bind_ip=192.168.226.130
    logpath=/data/log/mongodb-route.log
    logappend=true
    chunkSize=500
    configdb=192.168.226.130:27017
    fork=true
    

    启动路由: mongos -f /data/mongos/mongodb-mongos.conf
    查看启动状态:

    [root@moggledb mongos]# ps -ef |grep mongo
    root      15086      1  0 19:49 ?        00:00:02 mongod -f /data/config/mongodb-config.conf
    root      15124      1  0 19:53 ?        00:00:00 mongos -f /data/mongos/mongodb-mongos.conf
    root      15145  15062  0 19:54 pts/0    00:00:00 grep mongo
    [root@moggledb mongos]#
    

    使用mongo命令进入路由: mongo --host 192.168.226.130 --port 27018 admin

    ## 添加shard节点:
    mongos> db.runCommand({addshard:"192.168.226.131:27017"})
    { "shardAdded" : "shard0000", "ok" : 1 }
    ## 添加其他shard节点......
    mongos> db.runCommand({addshard:"192.168.226.132:27019"})
    { "shardAdded" : "shard0005", "ok" : 1 }
    ## 设置分片存储数据库
    mongos> db.runCommand({enablesharding:"study"})
    { "ok" : 1 }
    ## 指定数据库中的表通过什么分片, 我指定了对study数据库下的book表进行分片,根据表字段id和time分片, 指定的key在文档中必须存在,否则添加失败
    mongos> db.runCommand({shardcollection:"study.book", key:{id:1, time:1}})
    { "collectionsharded" : "study.book", "ok" : 1 }
    

    更多关于mongodb片建信息

    查看分片状态:

    mongos> db.runCommand({listshards:1})
    {
            "shards" : [
                    {
                            "_id" : "shard0000",
                            "host" : "192.168.226.131:27017"
                    },
                    {
                            "_id" : "shard0001",
                            "host" : "192.168.226.131:27018"
                    },
                    {
                            "_id" : "shard0002",
                            "host" : "192.168.226.131:27019"
                    },
                    {
                            "_id" : "shard0003",
                            "host" : "192.168.226.132:27017"
                    },
                    {
                            "_id" : "shard0004",
                            "host" : "192.168.226.132:27018"
                    },
                    {
                            "_id" : "shard0005",
                            "host" : "192.168.226.132:27019"
                    }
            ],
            "ok" : 1
    }
    

    插入三条数据:

    mongos> db.book.insert({"id":"1","name":"java","content":"hello java!","time":"2020-05-05"})
    WriteResult({ "nInserted" : 1 })
    mongos> db.book.insert({"id":"2","name":"php","content":"hello java!","time":"2020-05-06"})
    WriteResult({ "nInserted" : 1 })
    mongos> db.book.insert({"id":"3","name":"python","content":"hello java!","time":"2020-05-07"})
    WriteResult({ "nInserted" : 1 })
    mongos> db.book.find()
    { "_id" : ObjectId("5eb622cb3fad9d07777f6ca0"), "id" : "1", "name" : "java", "content" : "hello java!", "time" : "2020-05-05" }
    { "_id" : ObjectId("5eb622e03fad9d07777f6ca1"), "id" : "2", "name" : "php", "content" : "hello java!", "time" : "2020-05-06" }
    { "_id" : ObjectId("5eb622ee3fad9d07777f6ca2"), "id" : "3", "name" : "python", "content" : "hello java!", "time" : "2020-05-07" }
    

    可以看到在路由段就可以查到数据,因此在客户端只需要连接路由的地址,就可以查询整个集群数据,务需关心数据具体存在哪儿。
    下面我们看一下数据实际存储的数据块:
    首先登录进config库:

    [root@moggledb ~]# mongo --host 192.168.226.130 --port 27017 study
    ......
    2020-05-08T19:49:05.408-0700 I CONTROL  [initandlisten] **        We suggest setting it to 'never'
    2020-05-08T19:49:05.408-0700 I CONTROL  [initandlisten]
    > db.book.find()
    > show dbs
    config  0.078GB
    local   0.078GB
    

    可以看到根本没有study数据库, 之前我们说数据实际存储节点在shard节点中,config存储的是数据的位置。 下面验证一下:

    > use config
    switched to db config
    > show collections
    actionlog
    changelog
    chunks
    collections
    databases
    lockpings
    locks
    mongos
    settings
    shards
    system.indexes
    tags
    version
    

    上面是config库的表数据,我们可以看到chunks表存放数据块信息,shards存放shard节点信息

    > db.shards.find()
    { "_id" : "shard0000", "host" : "192.168.226.131:27017" }
    { "_id" : "shard0001", "host" : "192.168.226.131:27018" }
    { "_id" : "shard0002", "host" : "192.168.226.131:27019" }
    { "_id" : "shard0003", "host" : "192.168.226.132:27017" }
    { "_id" : "shard0004", "host" : "192.168.226.132:27018" }
    { "_id" : "shard0005", "host" : "192.168.226.132:27019" }
    > db.chunks.find()
    { "_id" : "study.book-id_MinKeytime_MinKey", "lastmod" : Timestamp(1, 0), "lastmodEpoch" : ObjectId("5eb62121eebc265b95c4a76d"), "ns" : "study.book", "min" : { "id" : { "$minKey" : 1 },
    "time" : { "$minKey" : 1 } }, "max" : { "id" : { "$maxKey" : 1 }, "time" : { "$maxKey" : 1 } }, "shard" : "shard0000" }
    

    其他表数据信息不一一测试,有兴趣自己验证。
    在上面我们看到数据都存在shard0000节点上,根据节点表信息可以知道shard0000节点地址为 192.168.226.131:27017 登录上去进行验证。

    [root@mongodb2 ~]# mongo --host 192.168.226.131 --port 27017 study
    .....
    2020-05-08T11:00:16.019-0700 I CONTROL  [initandlisten]
    > show dbs
    local  0.078GB
    study  0.078GB
    > use study
    switched to db study
    > db.book.find()
    { "_id" : ObjectId("5eb622cb3fad9d07777f6ca0"), "id" : "1", "name" : "java", "content" : "hello java!", "time" : "2020-05-05" }
    { "_id" : ObjectId("5eb622e03fad9d07777f6ca1"), "id" : "2", "name" : "php", "content" : "hello java!", "time" : "2020-05-06" }
    { "_id" : ObjectId("5eb622ee3fad9d07777f6ca2"), "id" : "3", "name" : "python", "content" : "hello java!", "time" : "2020-05-07" }
    

    可以在切换其他几个节点查看是否有数据:

    [root@mongodb2 ~]# mongo --host 192.168.226.131 --port 27018 study
    .....
    > show dbs
    local  0.078GB
    

    可以看到因为没有数据,所以study数据库还没有初始化。

  • 相关阅读:
    前端面试日更解答 interview-answe 1+1 2020-04-05
    Kafka学习系列----- 消费时序图
    JVM 垃圾回收算法简析
    ORM 框架选型对比
    Spring 中的设计模式之单例模式实现
    Synchroinzed 与lock 锁的区别
    Spring源码分析之ApplicationContextAware
    Springboot 启动简析
    HTTP/2.0 简单分析
    HTTPS 原理简要分析
  • 原文地址:https://www.cnblogs.com/Zs-book1/p/12851990.html
Copyright © 2011-2022 走看看