暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

NoSQL学习笔记--MongoDB基本操作(分片)

张春光的一亩三分地 2018-07-08
847

MongoDB数据库实例建立后,就可以对数据库进行各种操作了,比如插入,更新,删除,查询,索引,聚合,复制,分片等等

1、插入文档

2、查询文档

3、更新文档

4、删除文档

5、索引

6、聚合

7、复制

8、分片

分片(sharding)是指将数据拆分,将其分散存放在不同的机器上的过程。有时也用分区(partitioning)来表示这个概念。MongoDB数据库分片技术对大数据集和高吞吐量操作提供很好的部署支持功能。基本思想就是将集合切成小块,这些块分散到若干片里,每个片只负责总数据的一部分,最后通过一个均衡器来对各个分片进行均衡(数据迁移)。通过一个名为mongos的路由进程进行操作,mongos知道数据和片的对应关系(通过配置服务器)。

分片实现基本原理

MongoDB数据库分片实现原理涉及分片集群组件构成、分片算法和分片管理等

分片集群组成构成

MongoDB分片集群原理如图:


shard(分片)

每个分片包含被分片数据集合子集,即一个集合可以被分为若干个分片,每个分片可以部署为副本集

mongos(路由器)

mongos充当查询路由器,提供用户端应用程序和分片集群之间的接口。

mongos实例通过跟踪config服务器上的分片元数据来确定用户需要访问哪个分片服务器,为不同访问用户的读、写操作提供了数据访问统一接口。用户应用程序不能直接参与分片服务器的连接或通信。

例如,mongos接受用户查询请求后,通过config服务确定查询数据分片所在位置,然后在所有分片服务器上建立游标,mongos把各分片服务返回的分片数据合并,并把最终结果返回给查询用户。

config servers(配置服务)

配置服务存储集群的元数据(含数据块相关信息)和配制设置。配置服务必须部署为副本集。要将配置服务器部署为副本集,必须运行WiredTiger存储引擎。

shard key(分片键)和chunk(块)

MongoDB通过建立唯一性的分片键来把集合文档分片存储在各个分片服务器之中,也就是一个分片对应一个分片键,分片键一旦建立就不能更改。分片键存在于集合中给个文档的索引字段或索引复合字段。

MongoDB使用分片键值范围对集合中的数据进行分割。每个范围定义分片键值和数据块关联。MongoDB将集合文档分割成块(默认64M),每块带有唯一性的分片键,然后通过分片集群平衡器(balancer)实现不同服务器上的数据均衡块存储。

说明:允许用户更改块的大小;块自动拆分发生在insert或update这两个操作动作上;分块大小应该合理,太小意味着花费更多的时间进行拆分,查询汇总也会产生更多时间,太大意味着查询方便,但是在不同服务器分布可能不均匀;在人工设置块大小过程,如果设置比现在小,则对所有现有块进行重新拆分,要花费时间,并影响执行速度,设置的比现有大,则现有块仅通过插入或者更新增长,直到达到新的大小,该过程影响小;一个分片最多设置8192个数据块。

分片键是不可变。

分片键必须有索引。

分片键大小限制512bytes

分片键用于路由查询。

MongoDB不接受已进行collection级分片的collection上插入无分片

键的文档(也不支持空值插入)

分片算法

在不同服务器之间对数据块进行分片存储,MongoDB提供三种算法:

哈希分片(hashed sharding)

给需要分片的集合创建哈希索引或用sh.shardCollection("database.collection",{<field>:"hashed"})方法来设置哈希分片操作。


哈希分片,可以把集合数据相对均匀的分布到不同分片服务器上,使数据存储均匀化;若对空集合进行哈希分片,MongoDB会默认把两个空块分配到一个分片上。

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

Hash分片与范围分片互补,能将文档随机的分散到各个chunk,充分的扩展写能力,弥补了范围分片的不足,但不能高效的服务范围查询,所有的范围查询要分发到后端所有的Shard才能找出满足条件的文档。

范围分区(ranged sharding)

当集合里具有连续的字段键值时,如1、2、3、4、5....等,在分布式分片存储时,可以考虑按照顺序范围分片。

用sh.shardCollection("database.collection",{<sharedkey>})方法来设置范围分片操作。


范围分片的优点是同一范围的相邻数据块都可以存放在一个分片内,有利加快查询速度;范围分片为MongoDB默认的分片方法。

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

分区分片

就是根据文档字段的键值不同分类,同时根据读取数据的实际需要按类进行分片。

如商城,销售商品包括电子产品,书,食品,衣服,体育用品等,这里按照上述分类进行集合文档记录分片,形成如下分片:


需要先建立单一或复合索引;用sh.shardCollection("database.collection",{<sharedkey>})方法来设置分区分片操作。

分片集群管理

分片集群管理涉及config server管理、平衡器管理、查看集群配置、已分片集群迁移到其他硬件等内容。

 

构建分片集群单服务器测试环境

切记:之前的配置全部删除,最好将软件卸载,重新安装,安装后立刻将下列需要的目录创建出来,不要基于操作。

配置分片服务器

配置如下 :

shard server 1:27021    //分片服务器1,端口号27021

shard server 1:27022    //分片服务器1,端口号27022

shard server 1:27023    //分片服务器1,端口号27023

shard server 1:27024    //分片服务器1,端口号27024

config server:27100    //配置服务器,端口号27100

route process:40000    //路由处理器,端口号40000

四个分片服务用于分片数据存储;一个配置服务,用于提供配置信息服务;一个数据读写访问路由,用于客户端的读写访问和分片路由服务。

然后用cmd依次配置并启动分片服务:

mkdir d:\mongodb\shard\s0

mkdir d:\mongodb\shard\s0\data\db

mkdir d:\mongodb\shard\s0\data\log

其他路径按照这个复制粘贴

cd /d d:\mongodb\shard\s0\data\bin

mongod -port 27021 -dbpath d:\mongodb\shard\s0\data\db-logpath d:\mongodb\shard\s0\data\log\s0.log --logappend --shardsvr

cd /d d:\mongodb\shard\s1\data\bin

mongod -port 27022 -dbpath d:\mongodb\shard\s1\data\db-logpath d:\mongodb\shard\s1\data\log\s1.log --logappend --shardsvr

cd /d d:\mongodb\shard\s2\data\bin

mongod -port 27023 -dbpath d:\mongodb\shard\s2\data\db-logpath d:\mongodb\shard\s2\data\log\s2.log --logappend --shardsvr

cd /d d:\mongodb\shard\s3\data\bin

mongod -port 27024 -dbpath d:\mongodb\shard\s3\data\db-logpath d:\mongodb\shard\s3\data\log\s3.log --logappend --shardsvr

启动configserver

首先创建:D:\mongodb\shard\config。然后在主节点执行

cd /d D:\MongoDB\mongodata\db\bin

mongod -port 27017 --configsvr -dbpathD:\mongodb\shard\config -logpath D:\mongodb\shard\log\config.log --logappend-replSet rs0

接着执行配置服务的两个从节点:

cd /d D:\MongoDB1\mongodata\db\bin

mongod -port 27018 --configsvr -dbpathd:\MongoDB1\mongodata\db -logpath d:\MongoDB1\mongodata\log\mongodb.log-replSet rs0

cd /d D:\MongoDB2\mongodata\db\bin

mongod -port 27019 --configsvr -dbpathd:\MongoDB2\mongodata\db -logpath d:\MongoDB2\mongodata\log\mongodb.log-replSet rs0

设置副本集配置

mongo -port 27017

use admin

 

config = {

_id: "rs0",

members: [

{ _id: 0,host:"127.0.0.1:27017","priority":3 },

{ _id: 1,host:"127.0.0.1:27018","priority":2 },

{ _id: 2,host:"127.0.0.1:27019","priority":1 }

]

}

 

rs.initiate(config)

 

启动routeprocess

cd /d D:\MongoDB\mongodata\db\bin

mongos -port 4000 -configdb"rs0/127.0.0.1:27017,127.0.0.1:27018,127.0.0.1:27019" -logpathD:\mongodb\shard\log\route.log

配置sharding添加分片节点

C:\Users\Micky>cd /d D:\MongoDB\mongodata\db\bin

 

D:\MongoDB\mongodata\db\bin>mongo admin -port 4000

MongoDB shell version v3.6.5

connecting to: mongodb://127.0.0.1:4000/admin

MongoDB server version: 3.6.5

Server has startup warnings:

2018-07-08T15:50:57.520+0800 I CONTROL  [main]

2018-07-08T15:50:57.521+0800 I CONTROL  [main] ** WARNING: Access control is not

 enabled for thedatabase.

2018-07-08T15:50:57.521+0800 I CONTROL  [main] **          Read and write access

 to data andconfiguration is unrestricted.

2018-07-08T15:50:57.521+0800 I CONTROL  [main]

2018-07-08T15:50:57.521+0800 I CONTROL  [main] ** WARNING: This server is bound

to localhost.

2018-07-08T15:50:57.521+0800 I CONTROL  [main] **          Remote systems will b

e unable to connect to this server.

2018-07-08T15:50:57.521+0800 I CONTROL  [main] **          Start the server with

 --bind_ip<address> to specify which IP

2018-07-08T15:50:57.521+0800 I CONTROL  [main] **          addresses it should s

erve responses from, or with --bind_ip_all to

2018-07-08T15:50:57.521+0800 I CONTROL  [main] **          bind to all interface

s. If this behavior is desired, start the

2018-07-08T15:50:57.521+0800 I CONTROL  [main] **          server with --bind_ip

 127.0.0.1 todisable this warning.

2018-07-08T15:50:57.521+0800 I CONTROL  [main]

mongos>db.runCommand({addShard:"127.0.0.1:27021"})

{

       "shardAdded" : "shard0000",

       "ok" : 1,

       "$clusterTime" : {

               "clusterTime" : Timestamp(1531039178, 2),

               "signature" : {

                       "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),

                        "keyId" :NumberLong(0)

               }

        },

       "operationTime" : Timestamp(1531039178, 2)

}

mongos>db.runCommand({addShard:"127.0.0.1:27022"})

{

       "shardAdded" : "shard0001",

       "ok" : 1,

       "$clusterTime" : {

               "clusterTime" : Timestamp(1531039186, 3),

               "signature" : {

                       "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),

                       "keyId" : NumberLong(0)

               }

        },

       "operationTime" : Timestamp(1531039186, 3)

}

mongos>db.runCommand({addShard:"127.0.0.1:27023"})

{

       "shardAdded" : "shard0002",

       "ok" : 1,

       "$clusterTime" : {

               "clusterTime" : Timestamp(1531039192, 3),

               "signature" : {

                       "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),

                       "keyId" : NumberLong(0)

               }

        },

       "operationTime" : Timestamp(1531039192, 3)

}

mongos> db.runCommand({addShard:"127.0.0.1:27024"})

{

       "shardAdded" : "shard0003",

       "ok" : 1,

       "$clusterTime" : {

               "clusterTime" : Timestamp(1531039198, 3),

               "signature" : {

                       "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),

                       "keyId" : NumberLong(0)

               }

        },

       "operationTime" : Timestamp(1531039198, 3)

}

mongos>

查看分片服务器配置

mongos> db.runCommand({listshards:1})

{

       "shards" : [

               {

                       "_id" : "shard0000",

                       "host" : "127.0.0.1:27021",

                       "state" : 1

               },

               {

                       "_id" : "shard0001",

                       "host" : "127.0.0.1:27022",

                       "state" : 1

               },

               {

                       "_id" : "shard0002",

                       "host" : "127.0.0.1:27023",

                       "state" : 1

               },

               {

                        "_id" :"shard0003",

                       "host" : "127.0.0.1:27024",

                       "state" : 1

               }

        ],

       "ok" : 1,

       "$clusterTime" : {

               "clusterTime" : Timestamp(1531039274, 1),

               "signature" : {

                       "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),

                       "keyId" : NumberLong(0)

               }

        },

       "operationTime" : Timestamp(1531039274, 1)

}

mongos>

设置分片存储的数据库:

mongos>db.runCommand({enablesharding:"testdb"})

{

       "ok" : 1,

       "$clusterTime" : {

               "clusterTime" : Timestamp(1531039438, 1),

               "signature" : {

                       "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),

                       "keyId" : NumberLong(0)

               }

        },

       "operationTime" : Timestamp(1531039438, 1)

}

mongos>

sale集合的goodsid设置片键索引并分片

mongos>db.runCommand({shardcollection:"testdb.sale",key:{goodsid:1}})

{

        "collectionsharded" :"testdb.sale",

       "collectionUUID" :UUID("50cb8746-5e6e-4f02-9da0-c4846eb9cc16"),

       "ok" : 1,

       "$clusterTime" : {

               "clusterTime" : Timestamp(1531039595, 2),

               "signature" : {

                       "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),

                       "keyId" : NumberLong(0)

               }

        },

       "operationTime" : Timestamp(1531039595, 2)

}

插入数据

mongos> db.sale.insert(

... [

... {goodsid:"1000",amount:2,price:10,ok:false},

...{goodsid:"1001",amount:3,price:15,ok:false},

...{goodsid:"1002",amount:5,price:18.6,ok:false},

...{goodsid:"1003",amount:6,price:10.5,ok:true},

...{goodsid:"1004",amount:4,price:20,ok:true},

... {goodsid:"1005",amount:10,price:50,ok:true},

... ]

... )

BulkWriteResult({

       "writeErrors" : [ ],

       "writeConcernErrors" : [ ],

       "nInserted" : 6,

       "nUpserted" : 0,

       "nMatched" : 0,

       "nModified" : 0,

       "nRemoved" : 0,

       "upserted" : [ ]

})

mongos>

mongos>

mongos>

mongos> db.sale.find().pretty()

{

       "_id" : ObjectId("5b41cfb4130e119943c67102"),

       "goodsid" : "1000",

       "amount" : 2,

       "price" : 10,

       "ok" : false

}

{

       "_id" : ObjectId("5b41cfb4130e119943c67103"),

       "goodsid" : "1001",

       "amount" : 3,

       "price" : 15,

       "ok" : false

}

{

       "_id" : ObjectId("5b41cfb4130e119943c67104"),

       "goodsid" : "1002",

       "amount" : 5,

       "price" : 18.6,

       "ok" : false

}

{

       "_id" : ObjectId("5b41cfb4130e119943c67105"),

       "goodsid" : "1003",

       "amount" : 6,

       "price" : 10.5,

       "ok" : true

}

{

       "_id" : ObjectId("5b41cfb4130e119943c67106"),

       "goodsid" : "1004",

       "amount" : 4,

       "price" : 20,

       "ok" : true

}

{

       "_id" : ObjectId("5b41cfb4130e119943c67107"),

       "goodsid" : "1005",

       "amount" : 10,

       "price" : 50,

       "ok" : true

}

mongos> show collections

sale

system.keys

system.version

分片测试结果如下

mongos> sh.status()

--- Sharding Status ---

  shardingversion: {

       "_id" : 1,

       "minCompatibleVersion" : 5,

       "currentVersion" : 6,

       "clusterId" : ObjectId("5b41c094479a9b6809f3b97d")

  }

  shards:

        {  "_id" : "shard0000",  "host" :"127.0.0.1:27021",  "state": 1 }

        {  "_id" : "shard0001",  "host" :"127.0.0.1:27022",  "state": 1 }

        {  "_id" : "shard0002",  "host" :"127.0.0.1:27023", "state" : 1 }

        {  "_id" : "shard0003",  "host" :"127.0.0.1:27024",  "state": 1 }

  activemongoses:

       "3.6.5" : 1

  autosplit:

       Currently enabled: yes

  balancer:

       Currently enabled:  yes

        Currentlyrunning:  no

        Failedbalancer rounds in last 5 attempts:  0

       Migration Results for the last 24 hours:

               No recent migrations

  databases:

        {  "_id" : "config",  "primary" :"config",  "partitioned": true }

                config.system.sessions

                       shard key: { "_id" : 1 }

                       unique: false

                       balancing: true

                       chunks:

                                shard0000       1

                       { "_id" : { "$minKey" : 1 } } -->> {"_id" : { "$maxKey"

 : 1 } } on :shard0000 Timestamp(1, 0)

        {  "_id" : "testdb",  "primary" :"shard0001",  "partitioned": true }

               testdb.log

                       shard key: { "id" : 1 }

                       unique:false

                        balancing: true

                        chunks:

                                shard0001       1

                       { "id" : { "$minKey" : 1 } } -->> {"id" : { "$maxKey" :

 1 } } on :shard0001 Timestamp(1, 0)

                testdb.sale

                        shard key: {"goodsid" : 1 }

                       unique: false

                       balancing: true

                       chunks:

                               shard0001       1

                       { "goodsid" : { "$minKey" : 1 } } -->> {"goodsid" : { "

$maxKey" : 1 } } on : shard0001 Timestamp(1, 0)

 


文章转载自张春光的一亩三分地,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论