zoukankan      html  css  js  c++  java
  • Mongodb分片部署

    环境:2组分片+1组config+1个路由mongos  2组分片和1组config为副本集集群

    192.168.1.100  shared1_1

    192.168.1.101  shared1_2

    192.168.1.102  shared1_3

    192.168.1.103  shared2_1

    192.168.1.104  shared2_2

    192.168.1.105  shared2_3

    192.168.1.106  config1

    192.168.1.107  config2

    192.168.1.108  config3

    192.168.1.109  mongos

    配置展示

    config server 配置文件

    systemLog:
      # 目标是文件
      destination: file
      # 日志以追加的方式写入
      logAppend: true
      # 日志路径
      path: /usr/local/mongodb/log/mongodb.log
      # 
      quiet: false
    
    storage:
      # 数据库的存储路径
      dbPath: /usr/local/mongodb/data
      # 
      directoryPerDB: false
      engine: wiredTiger
      syncPeriodSecs: 61
      # 每个同步周期时间
      journal:
        enabled: true
    
    processManagement:
      fork: true
      pidFilePath: /usr/local/mongodb/run/mongodb.pid
    
    net:
      port: 27017
      # 指定程序绑定IP
      bindIp: 0.0.0.0
    
    replication:
      replSetName: configs
    
    sharding:
      clusterRole: configsvr

    shared server 配置文件

    systemLog:
      destination: file
      logAppend: true
      path: /usr/local/mongodb/log/mongodb.log
      quiet: false
    
    storage:
      dbPath: /usr/local/mongodb/data
      directoryPerDB: false
      engine: wiredTiger
      syncPeriodSecs: 61
      journal:
        enabled: true
    
    processManagement:
      fork: true
      pidFilePath: /usr/local/mongodb/run/mongodb.pid
    
    net:
      port: 27017
      bindIp: 0.0.0.0
    
    replication:
      # 多个分片修改分片名称即可
      replSetName: shared1
    
    sharding:
      clusterRole: shardsvr

    mongos server 配置文件

    systemLog:
      destination: file
      logAppend: true
      path: /usr/local/mongodb/log/mongodb.log
      quiet: false
    
    processManagement:
      fork: true
      pidFilePath: /usr/local/mongodb/run/mongodb.pid
    
    net:
      port: 27017
      bindIp: 0.0.0.0
      # 设置最大连接数
      maxIncomingConnections: 1024
    
    sharding:
      # 设置config server的地址
      configDB: configs/192.168.1.106:27017,192.168.1.107:27017,192.168.1.108:27017

    分别启动分片集群以及config集群

    /usr/local/mongodb/bin/mongod -f /usr/local/mongodb/etc/mongod.conf

    启动mongos路由

    192.168.1.109  mongos
    /usr/local/mongodb/bin/mongos -f /usr/local/mongodb/etc/mongos.conf

    客户端登录mongos

    /usr/local/mongodb/bin/mongo --host 192.168.1.109 --port 27017

    此时,写不进去数据,如果写数据会报错:

    mongos> use aadb
    switched to db aadb
    mongos> db.aa.insert({aa:"aa"})
    WriteCommandError({
        "ok" : 0,
        "errmsg" : "unable to initialize targeter for write op for collection
    aa.aa :: caused by :: Database aa not found :: caused by :: No shards found",
        "code" : 70,
        "codeName" : "ShardNotFound",
        "operationTime" : Timestamp(1564600123, 2),
        "$clusterTime" : {
            "clusterTime" : Timestamp(1564600123, 2),
            "signature" : {
                "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                "keyId" : NumberLong(0)
           }
       }
    })

    原因: 通过路由节点操作,现在只是连接了配置节点,还没有连接分片数据节点,因此无法写入业务数据。

    在路由节点上进行分片配置操作

    使用命令添加分片:
    (1)添加分片:
    语法:

    sh.addShard("IP:Port")

    将第一套分片副本集添加进来:

    mongos> sh.addShard("shared1/192.168.1.100:27017,192.168.1.101:27017,192.168.1.102:27217")
    {
        "shardAdded" : "myshardrs01",
        "ok" : 1,
        "operationTime" : Timestamp(1564611970, 4),
        "$clusterTime" : {
            "clusterTime" : Timestamp(1564611970, 4),
            "signature" : {
                "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                "keyId" : NumberLong(0)
           }
       }
    }

    查看分片情况:

    --- Sharding Status --- 
      sharding version: {
            "_id" : 1,
            "minCompatibleVersion" : 5,
            "currentVersion" : 6,
            "clusterId" : ObjectId("5f2a1b69c15b4b6bbf33d894")
      }
      shards:
            {  "_id" : "shared1",  "host" : "shared1/192.168.1.100:27017,192.168.1.101:27017",  "state" : 1 }
      active mongoses:
            "4.0.19" : 1
      autosplit:
            Currently enabled: yes
      balancer:
            Currently enabled:  yes
            Currently running:  no
            Failed balancer rounds in last 5 attempts:  0
            Migration Results for the last 24 hours: 
                    No recent migrations
      databases:
            {  "_id" : "articledb",  "primary" : "hqmongodb",  "partitioned" : false,  "version" : {  "uuid" : UUID("8b93073c-bec6-490c-9d2c-9f960dd9236f"),  "lastMod" : 1 } }
            {  "_id" : "config",  "primary" : "config",  "partitioned" : true }

    删除分片

    use admin
    db.runCommand( { removeShard: "myshardrs02" } )

    注意:如果只剩下最后一个 shard,是无法删除的
    移除时会自动转移分片数据,需要一个时间过程。
    完成后,再次执行删除分片命令才能真正删除。

    (2)开启分片功能:sh.enableSharding("库名")、sh.shardCollection("库名.集合名",{"key":1})

    在mongos上的articledb数据库配置sharding:

    mongos> sh.enableSharding("articledb")
    {
        "ok" : 1,
        "operationTime" : Timestamp(1564612296, 5),
        "$clusterTime" : {
            "clusterTime" : Timestamp(1564612296, 5),
            "signature" : {
                "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                "keyId" : NumberLong(0)
           }
       }
    }

    (3)集合分片

    对集合分片,你必须使用 sh.shardCollection() 方法指定集合和分片键。
    语法:

    sh.shardCollection(namespace, key, unique)

    分片规则一:哈希策略

    对于 基于哈希的分片 ,MongoDB计算一个字段的哈希值,并用这个哈希值来创建数据块.在使用基于哈希分片的系统中,拥有”相近”片键的文档 很可能不会 存储在同一个数据块中,因此数据的分离性更好一些.
    使用nickname作为片键,根据其值的哈希值进行数据分片

    mongos> sh.shardCollection("articledb.comment",{"nickname":"hashed"})
    {
        "collectionsharded" : "articledb.comment",
        "collectionUUID" : UUID("ddea6ed8-ee61-4693-bd16-196acc3a45e8"),
        "ok" : 1,
        "operationTime" : Timestamp(1564612840, 28),
        "$clusterTime" : {
            "clusterTime" : Timestamp(1564612840, 28),
            "signature" : {
                "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                "keyId" : NumberLong(0)
           }
       }
    }

    分片规则二:范围策略

    于 基于范围的分片 ,MongoDB按照片键的范围把数据分成不同部分.假设有一个数字的片键:想象一个从负无穷到正无穷的直线,每一个片键的值都在直线上画了一个点.MongoDB把这条直线划分为更短的不重叠的片段,并称之为 数据块 ,每个数据块包含了片键在一定范围内的数据.在使用片键做范围划分的系统中,拥有”相近”片键的文档很可能存储在同一个数据块中,因此也会存储在同一个分片中.
    如使用作者年龄字段作为片键,按照点赞数的值进行分片:

    mongos> sh.shardCollection("articledb.author",{"age":1})
    {
        "collectionsharded" : "articledb.author",
        "collectionUUID" : UUID("9a47bdaa-213a-4039-9c18-e70bfc369df7"),
        "ok" : 1,
        "operationTime" : Timestamp(1567512803, 13),
        "$clusterTime" : {
            "clusterTime" : Timestamp(1567512803, 13),
            "signature" : {
                "hash" : BinData(0,"eE9QT5yE5sL1Tyr7+3U8GRy5+5Q="),
                "keyId" : NumberLong("6732061237309341726")
           }
       }
    }
    注意的是:
    1)一个集合只能指定一个片键,否则报错。
    2)一旦对一个集合分片,分片键和分片值就不可改变。 如:不能给集合选择不同的分片键、不能更新
    分片键的值。
    3)根据age索引进行分配数据。
    查看分片状态:
    articledb.author
                shard key: { "age" : 1 }
                unique: false
                balancing: true
                chunks:
                    myshardrs01 1
               { "age" : { "$minKey" : 1 } } -->> { "age" : { "$maxKey"
    : 1 } } on : myshardrs01 Timestamp(1, 0)
    基于范围的分片方式与基于哈希的分片方式性能对比:
    基于范围的分片方式提供了更高效的范围查询,给定一个片键的范围,分发路由可以很简单地确定哪个数据块存储了请求需要的数据,并将请求转发到相应的分片中.不过,基于范围的分片会导致数据在不同分片上的不均衡,有时候,带来的消极作用会大于查询性能的积极作用.比如,如果片键所在的字段是线性增长的,一定时间内的所有请求都会落到某个固定的数据块中,最终导致分布在同一个分片中.在这种情况下,一小部分分片承载了集群大部分的数据,系统并不能很好地进行扩展.
    与此相比,基于哈希的分片方式以范围查询性能的损失为代价,保证了集群中数据的均衡.哈希值的随机性使数据随机分布在每个数据块中,因此也随机分布在不同分片中.但是也正由于随机性,一个范围查询很难确定应该请求哪些分片,通常为了返回需要的结果,需要请求所有分片.如无特殊情况,一般推荐使用 Hash Sharding。而使用 _id 作为片键是一个不错的选择,因为它是必有的,你可以使用数据文档 _id 的哈希作为片键。这个方案能够是的读和写都能够平均分布,并且它能够保证每个文档都有不同的片键所以数据块能够很精细。似乎还是不够完美,因为这样的话对多个文档的查询必将命中所有的分片。虽说如此,这也是一种比较好的方案了。
    显示集群的详细信息:
    mongos> db.printShardingStatus()
    查看均衡器是否工作(需要重新均衡时系统才会自动启动,不用管它):
    mongos> sh.isBalancerRunning()
    false

    查看当前 Balancer状态:

    mongos> sh.getBalancerState()
    true

    分片后插入数据测试

    测试一(哈希规则):登录mongs后,向comment循环插入1000条数据做测试:

    mongos> use articledb
    switched to db articledb
    mongos> for(var i=1;i<=1000;i++)
    {db.comment.insert({_id:i+"",nickname:"BoBo"+i})}
    WriteResult({ "nInserted" : 1 })
    mongos> db.comment.count()
    1000

    提示: js的语法,因为mongo的shell是一个JavaScript的shell。
    注意:从路由上插入的数据,必须包含片键,否则无法插入。

    分别登陆两个片的主节点,统计文档数量

    测试二(范围规则):登录mongs后,向comment循环插入1000条数据做测试:

    mongos> use articledb
    switched to db articledb
    mongos> for(var i=1;i<=20000;i++)
    {db.author.save({"name":"BoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoB
    oBoBoBoBoBoBoBoBo"+i,"age":NumberInt(i%120)})}
    WriteResult({ "nInserted" : 1 })
    mongos> db.comment.count()
    20000

    插入成功后,仍然要分别查看两个分片副本集的数据情况。

    提示:

    如果查看状态发现没有分片,则可能是由于以下原因造成了:
    1)系统繁忙,正在分片中。
    2)数据块(chunk)没有填满,默认的数据块尺寸(chunksize)是64M,填满后才会考虑向其他片的
    数据块填充数据,因此,为了测试,可以将其改小,这里改为1M,操作如下:

    use config
    db.settings.save( { _id:"chunksize", value: 1 } )

    测试完改回来:

    db.settings.save( { _id:"chunksize", value: 64 } )

    注意:要先改小,再设置分片。为了测试,可以先删除集合,重新建立集合的分片策略,再插入数据测试即可。

  • 相关阅读:
    在struct 中使用string,赋值会报错
    添加telnet命令
    can't set blob value on that column
    Floating-point exception
    2014.01.13 今天目标,完结战斗系统中的已知各种细节
    hanframe开微博了
    Educational Codeforces Round 78 (Rated for Div. 2)D(并查集+SET)
    Codeforces Round #604 (Div. 2)D(构造)
    Codeforces Round #608 (Div. 2)D(贪心)
    【PAT甲级】1108 Finding Average (20分)
  • 原文地址:https://www.cnblogs.com/fat-girl-spring/p/13438784.html
Copyright © 2011-2022 走看看