开发者学堂课程【MongoDB精讲课程(下):分片策略 哈希&范围演示】学习笔记与课程紧密联系,让用户快速学习知识
课程地址:https://developer.aliyun.com/learning/course/727/detail/12987
分片策略 哈希&范围演示
内容介绍:
一、哈希&范围
二、使用建议
一、哈希&范围
分片规则有两个策略,一个是哈希策略
对于基于哈希的分片MongoDB计算一个字段的哈希值,并用这个哈希值来创建数据块。
在使用基于哈希分片的系统中,拥有“相近片健的文档 很可能不会存储在同一个数据块中,因比数据的分离性更好些。
使用nickname作为片键,根据其值的哈希值进行数据分片。
mcngos>sh.shardco7lection("articledb.comment,{"nickname":"hashed"})
{
"collectionsharded" : "articledb.conment",
“co1lectionUUID":UUID(ddea6ed8-ee61-4693-bd16-196acc3a45e8")
"ok":1.
"operationTime":Timestamp(1564612840,28)
"Sclustertime":[
"custertime":Timestamp(1564612840,28),
"signature":{
"hash"":BinDataCO"AAAAAAAAAAAAAAAAAAAAAAAAAAA-")。
"keyId":NumberLong(0)
}
再添加一个范围策略,他添加的规则是一样的,前面是库,后面的集合进行分片,分片的规则通过每个字段。后边的值跟之前建立的索引很像,写1或者-1都可以。
分片规则:范围策略
对于基于范围的分片,MongoDB 按照片键的范国把数据分成不同部分,假设有一个数字的片键:想象一个从负无穷到正无穷的直线每一个片键的值都在直线上画了一个点MongoDB把这条百线划分为更短的不重鲁的片段,并称之为数据块,每个数据块包含了片键在一定范围内的数据。
在使用片键做范围刘分的系统中拥有相近片键的文档很可能存储在同一个数据块中,因此也会存储在同一个分片中。
如使用作者年龄字段作为片键,按照点赞数的值进行分片:
mongos> sh.shardco77ection("articledb.author",{"age":1})
{
"collectionsharded":"articledb.author".
"collectionUUID”:UUID9a47bdaa-213a-4039-9c18-e70bfc369df7"),
"ok”:1,
"operationTime":Timestamp(1567512803,13):
"$clusterTime”:{
"clusterTime":Timestamp(1567512803,13),
"signature" :{
"hash":BinData(0."eE90T5yE5sL1Tyr7+3U8GRY5+50=")
"keyId":NumberLong(6732061237309341726")
}
}
加的时候注意,加第一个哈希策略的时候用的是 comment 集合,加范围策略的时候用的是 author,因为 MongoDB 有一个特点,他只能通过一个字段给某一个集合分片,不可以comment既按照哈希策略又按照范围策略,只能二选一。哈希策略可能通过一些哈希值已经固定分了四片,但是范围策略并不会先分,他会通过插入数据的时候自动来分,它默认先分到myshardrs02,然后根据数据大小来自动的进行分片。哈希值有一个上限,有一个最小值,有一个最大值,他有比较确定的数值,但是他不知道默认age是多大,所以先分到myshardrs02来进行一个范围分配。
范围策略
acticledh.author
shard kay: i"age":1 )
unique:false
balancing: true
chunke:
mysharces02 1
(“age”:“SminKey”:1} } -->> : "age”:{ “*SmaxKey’”;1 } } on : myshardre02 Timestamp(1, 0)
哈希策略
articledb.comment
shard key: {"nickname":"hashed" }
unique: false
balancing: true
chunks:
myshardrs01 2
myshardrs02 2
{"nickname”:{"$minKey":1}}-->> {"nickname”:NumberLong("-4611686018427387902")} on : myshardrs01 Timestamp(1,0)
{"nickname”:NumberLong("-4611686018427387902")} -->> {"nickname”: NumberL song(0)} on : myshardrs01 Timestamp(1,1)
("nickname”:NumberLona(0)}-->> {"nickname”:NumberLona(4611686018427387902")} on :myshardrs02 Timestamp(1,2)
接下来向两个集合里面加一些数据,看一下是怎么分类的。
先开两个客户端,Show dbs,数据同步时,articledb中存了多些,哪有数据存在分片1还是分片2。
再开一个客户端连接分片2,
/usr/local/mongodb/bin/mongo --port 27318
开出来两个分片1和2,分片后插入数据测试
测试一(哈希规则):登录mongs后,向comment循环插入1000条数据做测试:
mongos> use articedb
switched to db articledb
mongos>for(vari=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
注意:从路由上插入的数据,必须包含片键,否则无法插入。
mongos> db
articledb
mongos>for(vari=1;i<=1000;i++){db.comment.insert({ id:i+"",nickname:"BoBo"+i})}
WriteResult({ "nInserted":1 })
mongos>
插入数据成功
mongos> show collections
author
comnent
mongos>
这个时候comnent 已经出来了
刚刚的一千条数据被分别存储到分片1和分片2里面,这个时候就可以看到分片1里面存储了507条数据,计算一下分片二就存储了493条数据。
分片2计算执行过程
myshardrs02:PRIMARY> db test
myshardrs02:PRIMARY> use articledb switched to db articledb
myshardrs02:PRIMARY> db.comment.count()
493
myshardrs02:PRIMARY>
其实这里也是有一定的随机性的,根据哈希特性,数值越大分布的越均匀。
范围策略
测试二(范围规则):登录mongs后,向comment循环播人1000条数据做测试:
mongos> use articledb
switched to db articledb
mongos> for(var i=1;i<=2000;i++)
{db.author.save({"name”:"BOBОBОBCBCBОBОBОBОBОBОBОBОBОBОBОBОBОBCBCBОBОBОBОBОBOBОBОBОBОBOBO BCBOBoBo"+i,"age":NumberInt(i%120)})} writeresult({"ninserted":1})
Mongos>db.comnent.count()
20000
插入成功后,仍然要分别查看两个分片副本集的数据情况。
分片效果:
articledb.author
shard key:{"age":1}
unique:false
balancing:true
chunks:
myshardrs01 2
myshardrs02 1
{"age":{ "$minkey" : 1 } } -->> { "age':} on : myshardrs02
Timestamp(2,0)
{ "age":0 } -->> {"age":112 } cn : myshardrs01 Timestamp(2,
1)
{ "age": 112 } -->> { "age":{"Sraxkey':1 } } on :
myshardrs01 Timestamp(1.3)
提示:
如果查看状态发现没有分片,则可能是由于以下原因造成了:
1)系统繁忙,正在分片中。
2)数据块(chunk)没有填满,默认的范围规则只给分配到了分片2,
默认的数据块尺寸(chunksize)是64M,填满后才会考虑向其他片的数据块地充数据,因此,为了测试,可以将其改小,这里改为1M,操作如下:
use config
db.settings.save({_id:"chunksize",value: 1})
测试完改回来:
db.settings.save({_id:"chunksize", value: 64 } )
注意:要先改小,再设置分片。为了测试,可以先测除集合,重新建立集合的分片策略,再插入数据测试即可。如果数据块够大是可以不考虑分片的。
二、使用建议
当数据不太确定的时候,又想让他随机分片,但是又不确定范围是多少,这里就建议用哈希规则。
如果范围比较多,每次查询的时候有明确目的,使用范围规则的效率是比较高的。