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 } )

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

posted @ 2020-08-05 11:35  fat_girl_spring  阅读(401)  评论(0编辑  收藏  举报