1.应用的开始是否适合使用分片
通常,如果数据集能够运行在单个服务器上,则不需要做sharding;
把一个没有sharding的数据库变为sharded集群是比较容易的
疑问:怎么把已经存在的服务器变成sharding
2.分片机制与复制是怎么联合工作的
每个分片作为一个副本集
3.当某个集合添加了分片键后,可以修改这个分片键吗?
不能
没有现成的工具来实现自动的片键修改,这种实现设计强调一开始选择一个片键的重要性。如果必须修改片键,当已经创建片键后,可以按照下面的方式进行:
导出所有的数据
删除原来的分片集合
创建集合,并且提前进行拆分,即创建集合的时候指定要分成多少个块,目的是插入的时候提高性能
导入数据
4.对于一个分片的数据库,没有做分片的集合会怎么处理
当前的实现中,所有的数据库都有主分区,没有分片的集合位于主分区中
5.如果客户端正在更新文档,而此文档所在的块正在迁移怎么办?
mongos会路由更新操作到老的分片,当更新操作完成后,分片实例将会复制更新后的数据,最终保证数据一致
6.如果某个分片不可用或者变得很慢,当有查询操作的时候,将会怎么处理
返回一个错误
当然,客户端可以设置一个查询属性,叫partial,如果设置,查询将会只返回可用分片的数据,而不管不可用分片
如果分片仅仅是响应慢,mongos会等待这个分片返回数据
7.mongodb怎么在分片之间分配查询的?
在分片的机器中进行查询,怎么执行主要看查询的方式和分片集群的配置。假如有一个集合,它的分片键是user_id,同时还有last_login和email两个属性:
通过user_id查询一个或者多个文档:
mongos会判断那些分片包含要查询的文档,依据是集群的元数据信息,也就是配置服务器中的分片信息,然后把查询分片到对应的分片上去,然后把所有返回的数据返回到客户端
如果是按照user_id查询,然后需要做一个排序
与上面一致,只不过会把返回的有序的数据做一次有序合并
如果以last_login作为条件查询
请求会被发送到所有的分片
8.如果没有用_id作为分片键,mongodb怎么确保_id属性的唯一性
需要应用自己保证,通过ObjectiId可以实现
9.我已经添加了一个新片,并且启动了分片功能,为什么所有的数据都只在一个分片服务器上?
首先,需要确定是否添加了分片键,在添加分片键之前,MongoDB不会创建块,因此,不会触发分片动作;
然后,需要明确的是,块的默认大小为64M,只有数据大于64M,才会触发块的迁移,在新的版本中,数据没有64M,也会出现多块,这时就会出现迁移,详情见第10条;
另外,为了避免不必要的迁移,基于分片的数量,分片键,以及数据的大小,系统通常需要10块才会触发迁移
10.数据块的创建规则
为了避免数据插入后,数据块的大量移动,mongodb会提前对数据块进行分块操作,通过此优化来提高性能,所以,尽管只有130m,实际的块数有10块,其分块原理可见源代码:
int ChunkManager::getCurrentDesiredChunkSize() const {
// split faster in early chunks helps spread out an initial load better
const int minChunkSize = 1 << 20; // 1 MBytes
int splitThreshold = Chunk::MaxChunkSize;
int nc = numChunks();
//返回值的单位是字节
if ( nc <= 1 ) {
return 1024;
}
else if ( nc < 3 ) {
return minChunkSize / 2;
}
else if ( nc < 10 ) {
splitThreshold = max( splitThreshold / 4 , minChunkSize );
}
else if ( nc < 20 ) {
splitThreshold = max( splitThreshold / 2 , minChunkSize );
}
return splitThreshold;
}
此函数的功能是计算块多大时,开始分块(split),从代码来看,可以得出如下结论:
刚开始插入数据时,由于只有一个块,此时当块大小到达1024字节即1k时即由一块拆分成两块
当块数达到2块时,符合nc<3的条件,这时,当块大小达到1m/2=512k时才开始分裂成两块
当块的数量大于等于3时,满足nc<10的条件,此时只有块大小达到16m时才会分裂成两块,也就是说如果块数小于10,则块最大的也肯定小于16m
当块数大于等于10小于20时,只有块的数据大于等于32m才会分裂
当块数多于20时,才会按照默认的64m来切分数据库
11.删除moveChunk目录下的老数据文件是安全的吗?
是的,在分片负载均衡的时候,mongod在后台创建这些备份
一旦这些迁移完成,就可以删除这些文件了
12.mongos怎么维护链接
每个客户端维护一个链接链接到mongos实例。每个mongos实例维护一个连接池,通过这个连接池链接到分片集群中副本集中的成员。
客户端每次使用一个mongos与mongod之间的连接。某个请求不会使用多个连接(多路复用),多个请求也不会串行执行(pipeline);当执行完成客户端的请求,这个请求就会被回收到连接池
总结:也就是说mongos维护的连接池的链接对客户端是无状态的,每次使用都需要重新分配
13.为什么mongos需要一直保持连接,与mongod
mongos通过连接池与每个分片的mongod服务器进行通信,但是这个池里面的连接数不会由于客户端连接的减少而减少。
这将会导致一个没有使用的mongos进程占用大量的链接,因此,如果一个mongos不在使用,应该关闭这个进程
14.怎么查看mongos的链接使用情况
链接到mongos,通过mongo shell,执行命令:
db._adminCommand("connPoolStats");
15.What does writebacklisten in the log mean(什么是回写监听器)
The writeback listener is a process that opens a long poll to relay writes back from a mongod or mongos after migrations to make sure they have not gone to the wrong server. The writeback listener sends writes back to the correct server if necessary.
These messages are a key part of the sharding infrastructure and should not cause concern.
16.管理员怎么干预失败的块迁移
失败的迁移不需要管理员干预。块迁移总会保证数据状态的一致性。如果某个块的迁移失败了,集群会重新执行这个操作的,当数据块迁移成功,这个数据块只会存在新的分片上
17.如果某个配置服务器出现问题,需要重新配置怎么操作?
1)把失效的配置服务器迁移到新的服务器中,并且采用新的hostname
注意事项:
需要停机处理,即需要重新启动集群中所有的进程(数据节点,没有问题的其他配置服务器,mongos进程)
当迁移配置服务器的时候,要保证所有的mongos实例都有三个配置服务器,并且mongos中关于配置服务器的顺序也必须一致
步骤:
临时关闭负载均衡器进程,执行sh.stopBalancer()
关闭需要被迁移的配置服务器(这样会导致,配置信息对集群服务器来说当前只能处于只读状态)
把被迁移的配置服务中数据文件拷贝到新的配置服务器中(dbpath指定的目录下的文件)
启动新的配置服务器
关闭当前存在的所有mongoDB进程,包括:分片节点,其它没有失效的配置节点以及mongos实例
重启所有的mongod实例(数据节点)
重启原来运行正常的配置节点实例
更新mongos所指向的配置服务列表
重启mongos实例
重新开启负载均衡功能:sh.setBalancerState(true)
2)失效的配置服务器迁移到新的服务器,但是采用原来的hostname
步骤:
1. 关闭有问题的配置服务器进程
2.把hostname配置在新的配置服务器中,即原来的域名或者主机名指向新的配置服务器
3.把原来配置服务器中dbpath指定的目录数据文件拷贝到新的服务器中
4.启动新的配置服务器文件
注:如果需要把所有的配置服务器都要迁移到新的配置服务器中,则需要按照mongos配置中配置服务器的顺序按照倒序的方式一个一个的迁移,迁移的过程如上面的4个步骤;比如cfg0 cfg1 cfg2,则先迁移cfg2
18.mongos服务器什么时候感知到配置服务器的变化?
mongos本地会保持一份配置数据库的元数据信息;
mongos会延迟更新本地的配置数据,通过向分片(应该是配置服务器)发送一个请求来判断本地数据是否过期。
客户端是没有任何方式来干预这个缓存数据的更新,但是可以运行命令flushRouterConfig命令来强迫mongos刷新它自己的缓存
19.在分片系统环境下,索引对查询的影响有多大?
如果查询条件没有包含分片键,mongos将会把查询发送给所有的分片,每个分片轮流使用分片索引或者其它索引来进行查询,然后再合并查询数据结果。
如果查询条件中包含分片键和其它索引,则mongos会把查询路由到分片键指定的分片,然后这个分片将会选择效率最高的索引进行查询,这将会获取最好的性能表现
20.分片键可以随机生成吗?
分片键可以随机产生,随机产生的键可以保证集群数据的最优分布
但是,随机的分片键将会导致查询的时候,数据会分散到所有的分片中,这样查询请求就会发送到所有的分片节点,这将导致数据查询性能有所下降
说明:官方的这种说法有一定局限性,如果单次查询的数据比较多,磁盘IO的开销大于网络开销的时候,这样做应该不但不会导致性能低下,反而会有利于提升性能;对于
查询的数据不多,当然在一个地方读取,直接返回会更快
21.分片键的值必须是均匀分布的吗?
不是的,没有强制文档的分片键是均匀分布的
但是,拥有相同分片键的数据会位于同一个块里面,当然也会在同一个服务器上,如果拥有同一个key的文档比较多,则会出现写比较聚集的情况,大家都往一个服务器写,会增加单台服务器的压力,另外,
数据的分布也会不均匀,这样单个块的大小会出现不一样(某些块时64M,某些大于64M),而数据均衡的时候是按照块来均匀的。
22.当日志里面出现moveChunk commit failed错误信息的时候,代表什么意思?
当块迁移完成的时候,当前分片需要连接到配置服务器更新块记录的元数据信息(块属于那个分片)。如果分片不能连接到配置服务器,mongoDB将会提示如下错误信息:
ERROR: moveChunk commit failed: version is at <n>|<nn> instead of
<N>|<NN>" and "ERROR: TERMINATING"
当出现这个错误信息的时候,分片(副本集)的主节点将会为了保证数据的一致性而停止提供服务;如果分片的第二个(次要)成员可以连接上配置服务器,当副本集进行重新选举后,刚迁移的数据库
在当前片上将可以被访问到
23.How does draining a shard affect the balancing of uneven chunk distribution?
The sharded cluster balancing process controls both migrating chunks from decommissioned shards (i.e. draining) and normal cluster balancing activities. Consider the following behaviors for different versions of MongoDB in situations where you remove a shard in a cluster with an uneven chunk distribution:
•After MongoDB 2.2, the balancer first removes the chunks from the draining shard and then balances the remaining uneven chunk distribution.
•Before MongoDB 2.2, the balancer handles the uneven chunk distribution and then removes the chunks from the draining shard.