Manual阅读笔记,Sharding分片配置

作者: 数据库信息  发布:2019-10-18

二、分片键:Shard keys

Chunk迁移

Chunk迁移可以:1.手动迁移,2.自动迁移(通过均衡器)

所有的迁移都是一下过程:

1.均衡器发送moveChunk命令道源shard

2.源Shard使用内部的moveChunk命令。源Shard负责处理写入

3.目标Shard开始复制数据

4.接受到之后一个文档之后,目标sahrd开始同步,保证被修改的文档可以被同步过来

5.当都被同步完成,目标shard连接到config数据库,修改集群元数据

6.当修改完元数据,并没有游标,删除chunk上的文档。

若要进行另外一个chunk迁移,不用等待当前chunk删除完成,直接进行。

2.查询路由(Query Routers)

Shard和非Shard数据

Shard是在collection级别的,可以在多个数据库的多个collection上shard。不管集群的结构,所有的查询和操作都使用mongos路由到数据中心。

本例中只配置一个mongos,方法如下:

关闭均衡器

默认均衡器只有在需要均衡数据的时候运行。也可以使用一下过程关闭均衡器:

1.连接到mongos

2.使用命令sh.setBalancerState(false)来关闭均衡器

3.通过sh.getBalancerState()来获取均衡器状态

可以用以下代码验证关闭后不再有迁移:

useconfig

while(sh.isBalancerRunning()){

          print("waiting...");

          sleep(1000);

}

驱动下,关闭均衡器只能修改settings collection

db.settings.update({_id:"balancer"},{$set:{stopped:true}},true)

五、使用Sharding前需要考虑的一些事情

9.3.2.7配置均衡器进程行为

均衡器运行在其中一个mongos上,保证chunks在集群中的均衡分布。默认的均衡器的配置已经足够使用了。管理员也有可以根据应用来重新配置均衡器。

使用3.0及以前版本的Sharded cluster可能会遇到一个问题,停止写入数据后,数据目录里的磁盘空间占用还会一直增加。

概述

这个过程是把3成员的复制集转为2个shard的集群,每个shard是3成员的复制集。

1.创建选择一个3成员的复制集,插入一些数据到collection

2.启动config数据库,并且创建一个单shard的集群

3.创建第二个复制集

4.把第二个复制集添加到这个集群上

5.在需要shard的collection进行shard。

shard2和shard3的配置文件与shard1基本一致,只需要把相应的replSet设为shard2shard3,相应的目录修改为shard2shard3,相应的端口修改为27020/27021即可。

启动数据库中的Shard

在真正shard collection之前要先启用数据库的shard。

1.连接到mongos

mongo --host mongos0.example.net --port 27017

2.使用sh.enableShard()命令对数据库启用shard

sh.enableSharding("<database>")

也可以使用命令:db.runCommand({enableSharding:<database>})

sh.addShard("192.168.20.70:27022")

9.3.1.6为生产环境部署3个Config服务

这个过程是把只有单个config的测试环境转变为3个config服务的生产环境。

1.关闭所有mongodb进程

2.复制dbpath下的所有文件到其他config服务

rsync -az /data/configdb mongo-config1.example.net:/data/configdb

rsync -az /data/configdb mongo-config2.example.net:/data/configdb

3.启动所有3个config server

mongod --configsvr

4.重启所有的mongod和mongos

路由就是mongos的实例,客户端直接连接mongos,由mongos把读写请求路由到指定的Shard上去。

9.1.1 Shard的目的

当数据库数据增大,应用程序高吞吐量会对单服务的能力进行挑战。查询过大cpu使用过大,数据过大要要求存储能力,working set 过大要求RAM和IO能力。

为了解决这个问题,有2个基本的方案:水平扩展,垂直扩展。

水平扩展:添加更多的cpu,存储资源来这更加处理能力。大cpu大内存的设备价格会远远大于小设备。

Sharding:是一种水平扩展,把数据分片到各个设备上。每个分片都是一个独立的数据库。

sharding处理大数据,大吞吐量的好处:

1.减少了在每个shard上的操作

2.减少了每个shard上的数据保存量。

ranged分片直接使用{id:1}方式指定即可,分片的chunk由mongos自主决定,例如在ranged分片集合中插入1000条数据,其结果如下:

重新启动均衡器

连接到mongos实例,然后执行sh.setBalancerState(true)

PRIMARY> db.isMaster()
{
"hosts" : [
"host1:9003",
"host2:9003",
"host3:9003"
],
"setName" : "mongo-9003",
"setVersion" : 9,
"ismaster" : false, // primary 的 ismaster 为 false???
"secondary" : true,
"primary" : "host1:9003",
"me" : "host1:9003",
"electionId" : ObjectId("57c7e62d218e9216c70aa3cf"),
"maxBsonObjectSize" : 16777216,
"maxMessageSizeBytes" : 48000000,
"maxWriteBatchSize" : 1000,
"localTime" : ISODate("2016-09-01T12:29:27.113Z"),
"maxWireVersion" : 4,
"minWireVersion" : 0,
"ok" : 1
}
添加一个shard 到集群

1.使用mongo连接到mongos

mongo --host mongos0.example.net --port 27017

2.使用sh.addShard增加shard

添加一个复制集,添加一个成员就可以了,以前的版本要添加所有的成员。

sh.addShard("rs1/mongodb0.example.net:27017")

添加一个单实例shard

sh.addShard("mongodb0.example.net:27017")

七、Sharding搭建步骤:

9.3.1.2考虑Shard Key

 

查看所有的shard

使用listShards命令查看

use admin

db.runCommand( { listShards :1 } )

然后启动并配置config server的rs(replica set):

9.3.1.3使用Hash Shard Key

Hash Shard Key是使用Hash索引的字段

config server的rs不能有arbiter(3.2.9版本是这样,其他版本未测试),生产上建议config server的rs至少要有3个副本集成员。

标记Shard Key

使用sh.addTagRange()把shard key分配给tag。

1.分配2个数组给NYC

2.分配一个数组给SFO

sh.addTagRange("records.users", { zipcode: "10001" }, { zipcode: "10281" }, "NYC")

sh.addTagRange("records.users", { zipcode: "11201" }, { zipcode: "11240" }, "NYC")

sh.addTagRange("records.users", { zipcode: "94102" }, { zipcode: "94135" }, "SFO")

recoverShardingState设置

9.2.3.2 Shard集群高可用性

在生产环境下,不能产生单点故障

使用db.t.stats()查看分片结果,使用sh.status()查看本库内所有集合的分片信息。

在备份的时候关闭均衡器

mongodb在迁移时备份会导致数据不一致,所以要在备份时关闭均衡器。可选方法:

1.设置均衡器调度窗口,在窗口外备份

2.手动关闭均衡器

如果关闭均衡器的时候有迁移在处理,那么会先等待迁移完成,然后清理掉之后要迁移的。

要在备份前确认是否有均衡器在运行。

!sh.getBalancerState()&&!sh.isBalancerRunning()

2.ranged sharding:https://docs.mongodb.com/v3.2/core/ranged-sharding/

9.1.4 维护数据均衡发布

新增的数据或者新增的服务会导致数据发布不均衡。有一些chunk会包含比其他chunk大的多的数据,或者比其他chunk的数据更加重要。

然后启动mongos,注意mongos的启动是与其他类型的mongo实例不一样的:(用的mongos而不是mongod命令)

Config服务的读写

只有在一下情况下会写config 服务:

1.在已存在的chunk上创建split

2.在shard之前迁移chunk

再有在一下情况下会读config服务:

1.mongos第一次启动

2.迁移chunk后,mongos更新自己的cache。

3.高可用方面:

9.2.2 Shard集群体系结构

介绍:shard集群要求,生产环境shard集群结构体系,shard集群测试环境的结构体系。

1.hash sharding:https://docs.mongodb.com/v3.2/core/hashed-sharding/

移动非shard数据

在shard环境下,只有primary数据库有非shard的collection

1.使用一下命令查看,删除的shard是不是primary

·  sh.status()

·  db.printShardingStatus()

输出中,databases字段列了所有数据库和它的primary,以下结果说明products数据库的primary在mongodb0上:

{  "_id":"products",  "partitioned":true,  "primary":"mongodb0"}

2.使用movePrimary命令移动primary

db.runCommand({movePrimary:"products",to:"mongodb1"})

这个命令只有当全部处理完之后才会返回

2.对于没有用到shard key的查询,路由进行全集群广播(broadcast operation),对每个shard都查一遍进行scatter/gather,此时效率会很低。

重命名Config服务和集群可用性

如果连接到config的名字和地址被修改,必须重启所有的mongod和mongos。使用CNAME(DNS)可以完成换服务器,但是可以不修改连接字符串。

 

9.3.3 Shard集群的数据管理

创建chunk,split chunk,迁移chunk,修改chunk大小,Tag意向Sharding,管理Shard Tag

,强制唯一键,Shard GridFS数据存储。

启动此实例后,在mongos上执行:

数据量需求

集群会管理大量的数据,数据以chunk为单位进行管理,chunk的大小默认是64MB,当shard之间chunk不均衡的时候(超过了阀值),均衡器会在shard之间迁移chunk知道均衡为止。对于小的collection来说shard是不合算的,光增加了复杂性,除非有写入性能的要求。Chunk默认大小64MB,是可以配置的

将部署在不同机房的shard设置机房标签,将不同chunk范围的数据分布到指定的机房

启动mongos实例

mongos是很轻量的不要求数据文件夹。默认端口是27017。启动mongos的时候需要指定config服务,可以在命令行也可以在配置文件下。最好给每个config服务一个DNS,这样换服务器的时候就不会有下线时间。

mongos --configdb cfg0.example.net:27019,cfg1.example.net:27019,cfg2.example.net:27019

每个mongos启动的时候必须要有相同的configdb配置字符串。

  • sh.addShardTag() 给shard设置标签A

  • sh.addTagRange() 给集合的某个chunk范围设置标签A,最终MongoDB会保证设置标签 A 的chunk范围(或该范围的超集)分布设置了标签 A 的 shard 上。

9.2.1 Shard集群组件

Shard集群有一下几个组件:

Shard:一个shard是一个mongodb实例,保存了collection数据的一个子集,Shard是单实例,也可以是复制集。

Config Server:每个config server是一个mongod实例,保存了元数据。

Routing Instances:路由是mongos实例,路由从应用程序到shard的读写。应用程序不能直接路由到shard。

分片范围是[shard_key_value_m,shard_key_value_n),MongoDB把每个分片叫做一个shard,一部分shard key的集合叫做chunk,一个shard上可以有多个chunk也可以只有一个chunk,一般会有多个。

检查迁移状态

查看迁移状态可以使用一下命令

useadmin

db.runCommand({removeShard:"mongodb0"})

输出

{

     "msg":"draining ongoing",

    "state":"ongoing",

    "remaining":{

        "chunks":42,

        "dbs":1

    },

    "ok":1

}

其中remaining文档显示了剩下要迁移的chunks,dbs表示这个数据库中primary的数据库个数。

--注意:dbpath、directoryperdb等参数是不能出现在mongos的配置文件中的,简单起见只配置如下参数即可:
configdb = config/192.168.20.70:27018,192.168.20.71:27018 --这里的config是config server副本集的名称,后接config server的2个副本集节点。
logpath=/home/mongod/mongos/mongod.log
logappend=true
fork=true
port=27019
pidfilepath=/home/mongod/mongos/mongod.pid
路由进程

Mongos使用一下过程路由到结果:

决定哪些Shard接收查询

1.确定哪些shard必须接收查询

2.在这些shard上创建游标。

如果查询中使用shard key或者shard key前缀过滤可以只查询shard的子集。

Mongos如何处理查询Modifiers

如果查询的结果不要求是排序的,mongos会打开一个游标然后循环shard上来的结果。如果指定了排序,那么把排序给shard,mongos在shard基础上执行合并排序。如果有limit会把limit传给shard,再在结果上limit。若有skip那么不会传,如果有limit和skip那么会传limit,传给shard的limit的个数为skip个数加上limit的个数。

一、Sharding集群简介

9.1.3.4 Range分区和Hash分区的性能区别

对于Range分区,区间查询更加有效,路由可以很容易的决定哪些chunk可以覆盖这些查询,然后路由到想要的shard上。

Range分区会导致数据不均匀,会否定shard带来的好处,会导致大量数据堆积在同一个shard上,弱化了shard的优势。

Hash分区确保了数据的均匀分布,但是对于区间查询就不可用对一些shard进行炒作,会对所有shard产生影响。

  • shard key在sharding搭建完毕后是不能修改的,一个collection上只能有一个shard key。

  • shard key上必须有索引(可以是以shard key开头的联合索引),如果没有mongodb会为shard key创建索引。如果是已经存在的collection那么必须手动为shard key创建索引。

  • 在sharding的collection中只有_id和shard key前缀的索引可以是unique index,其他索引只能是普通索引。如果一个普通key上有unique index那么你不能以其他key为shard key对collection进行sharding。

  • shard key的选择将会影响整个集群的效率,可扩展性和性能。而且也会影响你所能选择的分片策略。

9.3.3.2 Split Chunk

如果chunk大小草果chunk size,mongodb会自动的split这个chunk。但是还是会有手动split chunk出现:

1.有大量的数据但是chunk比较少

2.如果想要导入大量的数据,这些数据起初是在单个chunk或shard 上的。

当mongos认为迁移对未来插入性能有好处,均衡器可能会迁移split的chunk到一个新的shard。均衡器不会中断手动的split,也不会中断自动的split。

使用sh.status确定当前chunks

使用split命令来split chunk,要不是middle,要不是find也可以使用sh.splitFind(),sh.splitAt()。

在有某个值的chunk进行平均的split

sh.splitFind( "records.people", { "zipcode":"63109" } )

对指定位置进行split,新的chunk的边界从指定的值开始。

sh.splitAt( "records.people", { "zipcode":"63109" } )

有同学在将Sharded cluster所有节点都迁移到新的主机上时遇到了上述问题,因为config server的信息发生变化了,而shard启动时还会连接之前的config server,通过在启动命令行加上--setParameter recoverShardingState=false来启动shard就能恢复正常了。

为chunk迁移修改复制集行为

在2.2.1之后_secondaryThrottle变成moveChunk命令的一个参数。_secondaryThrottle可以让均衡器在迁移是等待secondary完成。

2.4之后,_secondaryThrottle默认启动。

当启动之后,secondary会要求写注意为{w:2}来保证修改至少被写入一个secondary。

可以通过以下命令来设置_secondaryThrottle:

useconfig

db.settings.update(

   {"_id":"balancer"},

   {$set:{"_secondaryThrottle":true}},

   {upsert:true}

)

三、Sharding的优势

Chunk迁移写注意

删除chunk的时候等待发布到secondary,会导致迁移速度下降,但是保证了大量chunk迁移的时候集群的可用性。具体看为chunk迁移修改复制集行为

MongoDB Sharding的自动负载均衡目前是由mongos的后台线程来做的,并且每个集合同一时刻只能有一个迁移任务,负载均衡主要根据集合在各个 shard上chunk的数量来决定的,相差超过一定阈值(跟chunk总数量相关)就会触发chunk迁移。

9.3.1.1部署shard集群

将服务能力不通的shard设置服务等级标签,将更多的chunk分散到服务能力更强的shard上去。

9.3.4.1 Config数据库错误字符串

Mongos的configdb都要使用同一个字符串,不然会有一下错误:

could not initialize sharding on connection

mongos specified a different config database string

 

9.3.2.6备份集群元数据

1.关闭均衡器

2.关闭其中一个config

3.备份整个数据文件夹

4.重新启动config

5.启动均衡器

4.至此完成了所有服务器的配置,接下来开始配置具体collection的分片策略。

组件

Config Server:3个Config Server,每个config server有独立的设备,一个shard独占使用config。也就是说config 不能被shard集群共享。

Shards:2个以上的shard,这些shard要求是复制集

Query Rounters(mongos):一个或多个mongos,mongos用来路由,一般是每个应用程序服务都有一个mongos实例。

当然,可以在mongos和应用程序之间使用代理和负载均衡,这种情况下使用client affinity来配置负载均衡,这样同一个链接可以一直使用同一个mongos。

八、Sharding的负载均衡(即Balancer)

9.2.4.2 Shard间Chunk迁移

图片 1

MongoDB版本:3.2.9
节点:192.168.20.70/71/72
架构说明:
70:包含mongos、config server(master)、3个shards(master)
71:包含config server(slave)、3个shards(slave)
72:包含3个shards(arbiter)
--网上很多资料说config server必须是奇数个,但至少在本次搭建的3.2.9版本中2个也是可以的。
删除均衡器调度窗口

使用一下命令来删除调度窗口

useconfig

db.settings.update({_id:"balancer"},{$unset:{activeWindow:true}})

 

9.2.2.1 Shard集群要求

Shard是很给力的功能,但shard集群有很多设备的要求,增加了整体部署的复杂性。

对于某些情况来说shard是唯一的解决方法:

1.数据集超过了单个实例处理的能力

2.数据集需要的内存超过了单个实例可以提供的内存

3.大量写的需求,使用其他方法无法解决。

如果没有以上的情况,使用shard只会影响整体的复杂性。

Shard的部署比较花时间,如果系统已经到达了处理能力的边界,再部署shard肯定会影响应用程序的使用。

Shard的部署应该在设计数据结构的时候就应该考虑。

2.配置shards

9.3.4.3在移动config服务避免下线

使用DNS名称来减少下线时间,名称一改所有成员都要重启。

使用MongoDB Sharded cluster时,还可能遇到一个问题,就是启动 shard后,shard 不能正常服务,Primary上调用ismaster时,结果却为 true,也无法正常执行其他命令,其状态类似如下:

9.3.1.4 Shard集群的认证

使用—keyfile来控制集群内组件的互通,keyfile都一样,内容可以随意

每个shard保存一部分数据,可以通过增加shards来扩容。

9.3.2.9删除Shard集群中的Shard

为了删除shard,必须确认shard中的数据已经被迁移出去了。不要使用一下过程来迁移整个shard集群到一个新的环境。

Tag aware sharding可应用在如下场景:

确保均衡器是启动的

使用sh.getBalancerState()来查看均衡器是否启动。

MongoDB是在collection级别实现的水平分片。

9.2.3.1 Shard Key

Shard key确定了collection的数据分布,shard key是索引字段,或者是组合索引字段。

Mongodb使用shard key来切分collection,每个区间或者chunk,不能重叠。然后mongodb分发这些chunks。

1.sharding集群不支持一些常规的单实例方法,如group(),可以使用mapReduce()或者aggregate()中的group来替代,因此建议从一开始学习就直接使用aggregate(),这种写法较为简单明了,且统一化易于识别。

9.1.2 Mongodb中的Shard

图片 2

shard集群由以下几个组件:shard,query routers和config server

Shard:用来存储数据。提供高可用和数据一致性,在生产环境下一个shard是一个复制集

Query Routers:或者mongos实例,是客户端的接口然后在合适的shard中型操作然后返回数据。对于shard集群可以包含多余一个router来分流客户端请求。一个客户端发送请求到一个router,大多数shard集群由很多query router。

Config Server:保存集群元数据,query router根据config server上的元数据来决定路由到哪个shard。

 

过程

使用测试数据部署复制集:使用下面的顺序来部署复制集

1.为复制集创建文件夹。

mkdir -p /data/example/firstset1 /data/example/firstset2 /data/example/firstset3

2.启动3个mongod实例

mongod --dbpath /data/example/firstset1 --port 10001 --replSet firstset --oplogSize 700 --rest

mongod --dbpath /data/example/firstset2 --port 10002 --replSet firstset --oplogSize 700 --rest

mongod --dbpath /data/example/firstset3 --port 10003 --replSet firstset --oplogSize 700 --rest

3.使用mongo打开一个shell

4.通过以下命令来初始化复制集

db.runCommand({"replSetInitiate":

                    {"_id":"firstset", "members": [{"_id":1, "host":"localhost:10001"},

                                                      {"_id":2, "host":"localhost:10002"},

                                                      {"_id":3, "host":"localhost:10003"}

             ]}})

{

"info":"Config now saved locally.  Should come online in about a minute.",

"ok":1

}

5.使用一下代码插入测试数据

use test

switched to db test

people = ["Marc", "Bill", "George", "Eliot", "Matt", "Trey", "Tracy", "Greg", "Steve", "Kristina", "Katie", "Jeff"];

for(var i=0; i<1000000; i ){

                             name = people[Math.floor(Math.random()*people.length)];

                             user_id = i;

boolean= [true, false][Math.floor(Math.random()*2)];

                             added_at =newDate();

                             number =Math.floor(Math.random()*10001);

                             db.test_collection.save({"name":name, "user_id":user_id, "boolean":boolean, "added_at":added_at, "number":number });

                            }

部署Shard基础设施:这个过程创建了3个config数据库

1.为config服务创建文件夹

mkdir -p /data/example/config1 /data/example/config2 /data/example/config3

2.启动config数据库

mongod --configsvr --dbpath /data/example/config1 --port 20001

mongod --configsvr --dbpath /data/example/config2 --port 20002

mongod --configsvr --dbpath /data/example/config3 --port 20003

3.启动mongos实例

mongos --configdb localhost:20001,localhost:20002,localhost:20003 --port 27017 --chunkSize 1

--chunkSize表示chunk的大小这里是1MB

4.添加第一个shard

         a.连接到mongos

         mongo localhost:27017/admin

         b.增加使用addShard增加sahrd

         db.runCommand( { addShard :"firstset/localhost:10001,localhost:10002,localhost:10003" } )

         c.返回一下信息说明添加成功

         { "shardAdded":"firstset", "ok":1 }

部署第二个复制集:下面的过程部署第二个复制集

1.创建复制集文件夹

  • /data/example/secondset1
  • /data/example/secondset2
  • /data/example/secondset3

2.启动3个mongod实例

mongod --dbpath /data/example/secondset1 --port 10004 --replSet secondset --oplogSize 700 --rest

mongod --dbpath /data/example/secondset2 --port 10005 --replSet secondset --oplogSize 700 --rest

mongod --dbpath /data/example/secondset3 --port 10006 --replSet secondset --oplogSize 700 --rest

3.连接到mongos

mongo localhost:10004/admin

4.初始化第二个复制集

db.runCommand({"replSetInitiate":

                    {"_id":"secondset",

"members": [{"_id":1, "host":"localhost:10004"},

                                  {"_id":2, "host":"localhost:10005"},

                                  {"_id":3, "host":"localhost:10006"}

             ]}})

 

{

"info":"Config now saved locally.  Should come online in about a minute.",

"ok":1

}

5.把复制集增加到集群

use admin

db.runCommand( { addShard :"secondset/localhost:10004,localhost:10005,localhost:10006" } )

是不是只写一个成员就可以了

6.验证shard成员,使用listShards命令

db.runCommand({listShards:1})

{

"shards": [

              {

"_id":"firstset",

"host":"firstset/localhost:10001,localhost:10003,localhost:10002"

              },

              {

"_id":"secondset",

"host":"secondset/localhost:10004,localhost:10006,localhost:10005"

              }

      ],

"ok":1

}

启动Shard:mongodb必须要再数据库和collection级别启动shard

在数据库级别启动Shard:使用enableSharding命令启动数据库

db.runCommand( { enableSharding :"test" } )

{ "ok":1 }

在索引上创建Shard Key:Mongodb使用shard key来发发布数据到shard,一旦决定之后你不能修改shard key。好的shard key:

1.可以均衡的分发数据

2.经常被同时访问的文档会被放在连续的chunk下

3.在活动的shard中有效的分发

Shard key一般的选择是复合索引,hash或者主键。Shard key的选择还是和数据,应用程序结构和使用方式有关。

Shard Collection

use admin

db.runCommand( { shardCollection :"test.test_collection", key : {"number":1} })

{ "collectionsharded":"test.test_collection", "ok":1 }

之后均衡器会均衡chunk,可以在test下的db.stats()或者db.printShardIngStatus()查看是否在同步。

九、其他问题

迁移阀值

Number of Chunks

Migration Threshold

Fewer than 20

2

21-80

4

Greater than 80

8

一旦均衡器启动只有当2个shard的chunk差为2或者迁移失败才会停止。

一段时间后sh.status()看到的结果如下:

增加Shard到集群中

shard可以是复制集也可以是单个实例,对于生产环境应该要求都是复制集。

1.使用mongo连接到mongos

mongo --host mongos0.example.net --port 27017

2.使用sh.addShard添加shard到集群

添加一个复制集,添加一个成员就可以了,以前的版本要添加所有的成员。

sh.addShard("rs1/mongodb0.example.net:27017")

添加一个单实例shard

sh.addShard("mongodb0.example.net:27017")

Balancer默认是开启的,为了避免chunk迁移影响到线上业务,可以通过设置迁移执行窗口,比如只允许凌晨2:00-6:00期间进行迁移。

一个shard不可用

Shard级别,复制集提供了可用性,如果primary变得不可用,复制集就会投票生成另一个primary。如果是secondary不可用不影响使用。如果系统变得不可恢复,那么增加新的成员来弥补冗余。

在3.2版本,该配置项默认值也被设置为false,默认不会对moveChunk的数据在源shard上归档。

集群均衡器

均衡器是用来均衡shard之间的数据量,默认均衡器是开启的。

任何mongos实例都可以启动均衡流程。当均衡器被激活,mongos要修改config数据库中的lock collection,获得锁。

均衡器一旦启动,只有当chunk均衡的时候才会停止。

Chunk迁移会导致负荷上升,影响应用的性能。有2个方法减少影响:

1.一次只迁移一个chunk

2.或者只有当最大chunks个数和最小chunks个数只差超过一个阀值。

当然也可以临时关闭均衡器

注意这里的mongos并不要配置为rs,因为只是个路由,并不存储数据,配置多个mongos的意思是配置多个单独的mongos实例。

使用组合shard key

当存在在collection中的字段都不是最优的key,那么选择多个字段作为组合shard key会更加的理想。

在3个shard的primary上使用db.t.find().count()会发现1000条数据近似均匀的分布到了3个shard上。

Config数据库

Config服务把元数据存放在config数据库中,mongos会缓存这些数据,来路由数据库操作。

--shard1的master、slave、arbiter的配置文件(分别在70、71、72上)
--master:
directoryperdb=true
replSet=shard1
shardsvr = true
logpath=/home/mongod/shard1_master/mongod.log
logappend=true
fork=true
port=27017
dbpath=/home/mongod/shard1_master
pidfilepath=/home/mongod/shard1_master/mongod.pid

--slave:
directoryperdb=true
replSet=shard1
shardsvr = true
logpath=/home/mongod/shard1_slave/mongod.log
logappend=true
fork=true
port=27017
dbpath=/home/mongod/shard1_slave
pidfilepath=/home/mongod/shard1_slave/mongod.pid

--arbiter:
directoryperdb=true
replSet=shard1
shardsvr = true
logpath=/home/mongod/shard1_arbiter/mongod.log
logappend=true
fork=true
port=27017
dbpath=/home/mongod/shard1_arbiter
pidfilepath=/home/mongod/shard1_arbiter/mongod.pid
检查均衡器状态

使用sh.getBalancerState()查看均衡器状态

mongo --port=27019 --27019是mongos的端口号
use test
for(i=1,i<=1000,i  ){db.t.insert({id:i,name:"Leo"})}

9.3.1.5添加Shard到集群

当shard增加到集群的时候要保证,集群有足够的能力来迁移数据。

关于sharding的操作方法参考:

完成迁移

为了清理所有的元数据和完成迁移,再次使用removeShard命令

useadmin

db.runCommand({removeShard:"mongodb0"})

当完成的时候会返回以下结果:

{

    "msg":"removeshard completed successfully",

    "state":"completed",

    "shard":"mongodb0",

    "ok":1

}

只有完成到这步的时候,你才能完全的关闭这个shard的进程。

在第4步中针对test的t集合进行了分片配置,因此这里向t插入1000条数据做测试:

基数(cardinality 选择性类似)

基数决定了这个系统中可以分为几个chunks。

1.如果用state作为shard key,因为state少会造成集群不均衡有以下影响:

         a.不能分离chunks因为这个chunk都是同一个shard key,迁移这些chunk变得无比困难。很难让集群均衡。

         b.如果固定了chunks的个数,那么就不能超过这个个数了。

2.zipcode字段作为shard key:

         这个字段选择度高但是也有可能照成un-splittable的情况,有些用户很多,有些却很少。

3.考虑手机号码作为shard key:

         手机号码是高基数(和选择度一样)的,所有的用户都有自己的手机号码并且是唯一的。

高基数可以保证数据均衡,但是不能保证查询隔离和合适的写扩展。

此外最后几个部分还引用了https://yq.aliyun.com/articles/60096中的一些问题描述及解决方案。

9.3.3.3迁移Chunk

一般chunk迁移都是自动的,但是以下情况可以考虑自动迁移:

1.split空的collection,然后分发他们

2.如果在均衡窗口内无法迁移chunk

使用moveChunk命令来迁移chunk。

db.adminCommand( { moveChunk : "myapp.users",

                   find : {username : "smith"},

                   to : "mongodb-shard3.example.net" } )

把包含shard key为 smith的chunk启动到mongodb-shard3

可以使用如下命令迁移:

var shServer = [ "sh0.example.net", "sh1.example.net", "sh2.example.net", "sh3.example.net", "sh4.example.net" ];

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.adminCommand({moveChunk :"myapp.users", find : {email : prefix}, to : shServer[(y-97)/6]})

  }

}

2.2版本后,会有个_secondaryThrottle参数当为true时,mongodb会保证对chunk的迁移分发到secondary。

当出现以下错误时是有太多游标打开了这个chunk,要不等待游标关闭,要不干掉游标。

The collection's metadata lock is already taken.

另外,在进行sharding备份时(通过mongos或者单独备份config server和所有shard),需要停止负载均衡以免备份出来的数据出现状态不一致问题。

9.3.2.1查看集群配置

Ps:mongod是mongodb实例,mongos被默认为为mongodb sharding的路由实例。

9.2.4.5Shard集群元数据

Config服务保存了集群的元数据,元数据反映了状态和shard数据集和系统的组合。mongos实例缓存了这些数据并使用它来路由读写操作。config数据库包含了以下collection:

·changelog

·chunks

·collections

·databases

·lockpings

·locks

·mongos

·settings

·shards

·version

在shard key选取不正确的情况下,范围分片会导致数据分布不均匀,也可能遭遇性能瓶颈,因此需要合理的选择ranged shard key。

9.2.2.3测试环境的体系结构

测试环境下:1个config server,1个以上shard,一个mongos实例。

mongo --port=27019 --连接到mongos
use config
db.settings.update(
{ _id: "balancer" },
{ $set: { activeWindow : { start : "02:00", stop : "06:00" } } },
{ upsert: true }
)
Balancer会在服务器local time的凌晨2-6点才执行chunk的balance。
Config服务可用性

当有3个config 服务其中1个或2个不可用的时候,集群的元数据变为只读,可以读数据,但是不能迁移chunk或者创建split。

如果3个config服务都不可用,如果不重启mongos那么任然可以使用集群,如果在config服务可用之前mongos重启了,mongos就不能再路由。

当没有元数据的时候集群变得不可操作,所以保持一个可用的完好的config十分重要。备份起到一个很关键作用。Config服务的数据和整个集群比很小,负荷也少,并且config服务并不要求一直可用来支持shard集群。

当shard集群使用的config服务修改了名字或者地址,需要重启每一个mongod和mongos,为了避免这种情况,可以使用CNAME来唯一标示衣蛾ocnfig服务。

 

2.扩容方面:

9.2.4 Shard机制

介绍,shard collection均衡,chunk迁移,chunk split,Shard key所有,shard集群元数据。

六、Sharding策略选择

启动Config服务

config服务是保存了集群元数据的mongod,启动的时候标记configsvr,每个config保存了一份完整的集群元数据。

生产环境下最好在不同的服务器上部署3个config服务。

1.为config服务创建数据文件夹

mkdir /data/configdb

2.启动mongod服务

mongod --configsvr --dbpath <path> --port <port>

默认端口是27019,当然可以通过--port来指定端口。

5.hashed分片验证

跨多个tag的chunk

一个chunk包含的shard key可能跨多个tag,为了解决这个问题,均衡器可能会把chunk迁移到比chunk的shard key小的tag上。

如:有2个tag

1.shard key 为100-200的tag NYC

2.shard key为200-300的tag SFO

当有一个chunk要迁移shard key为150-220,那么会被迁移到NYC,因为150到200比到300近。

 

启动均衡器

1.使用mongo连接到mongos

2.使用以下任意一种语句来启用:

sh.setBalancerState(true)

db.settings.update({_id:"balancer"},{$set:{stopped:false}},true)

一个Sharding集群,可以有一个mongos,也可以如上图所示为每个App Server配置一个mongos以减轻路由压力。

关闭均衡器

关闭均衡器来停止chunk迁移,在整个过程中不要有元数据写入,若均衡器已经启动了迁移,那么先等待均衡器迁移完,在执行这个过程。sh.stopBalancer()来关闭均衡器。然后可以使用sh.getBalancerStatue()来查看均衡器状态。

3.Tag aware sharding:https://docs.mongodb.com/v3.2/core/tag-aware-sharding/

9.2.4.3 Shard集群下Chunk的分离

当Chunk的大小超过了指定的chunk大小,mongos会把这个chunk分成2半

图片 3

 

启动Collection的Shard

1.确定shard key

2.如果collection已经有数据库的要先在shard key上创建索引使用ensureIndex(),如果是空的,Mongodb会通过sh.shardCollection创建。

3.使用sh.shardCollection() shard一个collection

sh.shardCollection("<database>.<collection>",shard-key-pattern)

shard-key-pattern表示shard key

如:

sh.shardCollection("records.people",{"zipcode":1,"name":1})

sh.shardCollection("people.addresses",{"state":1,"_id":1})

sh.shardCollection("assets.chairs",{"type":1,"_id":1})

db.alerts.ensureIndex({_id:"hashed"})

sh.shardCollection("events.alerts",{"_id":"hashed"})

6.其他分片方式

Shard key和集群可用性

选择Shard Key要考虑:

1.保证mongod可以均匀的分布数据

2.可以扩展写能力

3.保证mongos在大多数查询上可以查询隔离,也就是路由到指定的mongod。

跟多:

1.每个shard应该是一个复制集

2.如果可以隔离大多数操作,shard不可用,只会影响部分数据。

3.如果每个操作都要发布到整个集群,当一个shard不可用会导致整个集群不可用。

sharding将读写负载均匀到各个shard,且workload上限可以通过水平扩展来增加。

修改指定Shard的最大存储大小

最大存储大小,指定后,如果mapped大小超过了最大存储大小,均衡器就不会再移入数据这个mapped大小是值所有被映射的数据库文件的大小。maxsize被保存在config数据库中的shards collection下。

默认maxsize可以无限大,撑满所有可用空间为止。这个maxsize可以在添加shard的时候指定也可以手动修改:

1.通过addShard指定,单位MB

db.runCommand( { addshard : "example.net:34008", maxSize : 125 } )

2.修改已存在shard的maxsize

use config

db.shards.update( { _id : "shard0000" }, { $set : { maxSize : 250 } } )

tag aware分片策略还未测试,有待以后补充。

Chunks Collection

上述行为是由sharding.archiveMovedChunks配置项决定的,该配置项在3.0及以前的版本默认为true,即在move chunk时,源shard会将迁移的chunk数据归档一份在数据目录里,当出现问题时,可用于恢复。也就是说,chunk发生迁移时,源节点上的空间并没有释放出来,而目标节点又占用了新的空间。

Shard key唯一性约束

过程:可以在shardCollection中指定unique保证唯一性

db.runCommand( { shardCollection : "test.users" , key : { email : 1 } , unique : true } );

限制

1.只能限制一个字段的唯一性

2.可以使用组合的shard key,只能对组合进行唯一约束

很多情况下,最好的shard key是组合的可以允许读隔离和写扩展。

moveChunk归档设置

9.3.3.4修改Chunk的大小

如果你注意到,自动迁移超过了硬件的处理能力,就可能想要减少chunk大小。修改chunk大小过程:

1.连接到mongos

2.切换到config数据库

3.使用save命令来保存chunk大小

db.settings.save( { _id:"chunksize", value: <sizeInMB> } )

修改chunk有一下几个限制:

1.自动split会在插入或者修改的时候发生

2.如果设置了低的chunk,那么需要时间来split所有的chunk

3.split是不能undone的

4.如果增加了chunk的大小,那么只有通过insert,和update让chunk增长到新的大小。

原理如下:

9.1.4.1 分离(Splitting)

Splitting是一个后台进程,不让chunk变得太大,当chunk超过阀值是就会splits,split会影响元数据,split不会迁移也不会影响shard。

图片 4

本文由金沙澳门官网发布于数据库信息,转载请注明出处:Manual阅读笔记,Sharding分片配置

关键词: 金沙澳门官网