MongoDB11-分片集群
1、分片概述
- 分片是一种跨多台机器分发数据的方法。MongoDB可以分片来支持非常大的数据集和高吞吐量操作。
- 具有大数据集或高吞吐量应用程序的数据库系统可能挑战单个服务器的性能。例如,过高的查询率会耗尽服务器的CPU容量。工作集大小如果超过了系统内存会增加磁盘驱动器的I/O容量。
- 扩展有两种方法:垂直扩展和水平扩展。
- 垂直扩展涉采用增加单个服务器容量的方法,例如使用更强大的CPU、添加更多RAM或增加存储空间。但无论从技术上还是经济上考虑,都会限制单台机器的性能。此外,性能不是无限扩张的,会有一个瓶颈值,因此垂直缩放是不经济而且有上限的。
- 水平扩展是将系统数据集和负载分配到多个服务器上,根据需要添加额外的服务器以增加容量。虽然单个机器的总体速度或容量可能不高,但每台机器只处理总体工作负载的一部分,可能比单个高速高容量服务器提供更好的效率。只需要根据需要添加额外的服务器,这可能比单个机器的高端硬件的总体成本更低,但增加了部署和维护的复杂性。
- MongoDB通过分片实现水平扩展。
1.1、分片架构
- MongoDB分片集群由以下组件组成:
- shard(分片):每个shard包含分片数据的一个子集。从MongoDB 3.6开始,分片必须作为副本集部署,以提供冗余和高可用性。
- mongos(路由器):mongos是查询路由器,提供客户端应用程序和分片集群之间的接口。从MongoDB 4.4开始,MongoDB可以支持对冲读取以最小化延迟。
- config servers(配置服务器):配置服务器存储集群的元数据和配置设置。
- 下图描述了分片集群内部组件之间的交互:
- MongoDB在集合级别对数据进行分片,将集合数据分布到集群中的各个分片。
- 在生产环境中,要确保数据是冗余的,和系统是高可用的。分片集群一般部署为:
- 将config server(配置服务器)部署为有3节点的副本集。
- 将每个Shard(分片)部署为有3节点的副本集。
- 部署一个或多个mongos(路由器)。
- mongos路由器的数量是没有限制的,但由于mongos路由器经常与配置服务器通信,所以在增加路由器数量时要密切监视配置服务器的性能。
- 生产环境中,常见的分片集群架构:
- 测试环境中,常见的分片集群架构:
1.2、分片三个术语
1、Shard Keys(分片键)
- 为了对一个集合中的文档进行分割, MongoDB使用shard key对集合进行分割,shard key由文档中的一个或多个字段组成。
- 从4.4版开始,分片集合中的文档可能会缺少shard key字段。在跨分片分发文档时,缺失的shard key字段将被视为空值,而在路由查询时则不会。
- 在4.2版本及更早版本中,分片集合的每个文档中都必须存在shard key字段。
- 在对集合进行切分时选择切分键。
- 从MongoDB 5.0开始,可以通过更改集合的shard key来重新对集合进行分片。
- 从MongoDB 4.4开始,可以通过向现有的shard key添加一个或多个后缀字段来优化shard key。
- 在MongoDB 4.2及更早的版本中,分片后无法更改shard key的选择。
- 文档的shard key值决定了它在shard中的分布。
- 从MongoDB 4.2开始,可以更新文档的shard key值,除非你的shard key字段是不可变的_id字段。
- 在MongoDB 4.0和更早的版本中,文档的shard key字段值是不可变的。
- 如果非空集合进行切分,则集合必须具有以shard key开头的索引。对空集合进行切分,如果集合尚不具有指定shard key的适当索引,则MongoDB会自动为其创建索引。
- 分片密钥的选择会影响分片群集的性能、效率和可伸缩性。再好的机器硬件,如果shard key的选择不合理,也一样会遇到瓶颈。shard key及其支持索引的选择也会影响集群可以使用的分片策略。
2、Chunks(块)
- MongoDB将分片数据划分为Chunks。每个chunk都有一个基于shard key的左闭右开的范围值。
3、Balancer(均衡器)
- 为了在集群中的所有分片上实现数据块的均匀分布,一个均衡器在后台运行,在分片之间迁移数据块。
1.3、分片的优点
- reads/writes
- MongoDB将读写工作负载均衡到分片集群中的分片上,允许每个分片处理集群操作的一个子集。通过添加更多的分片,可以在集群中水平扩展读和写工作负载。
- 对于包含shard key或复合shard key前缀的查询,mongos可以将查询定位于特定的分片或分片
- 集。这些有针对性的操作通常比向集群中的每个分片查询更高效。
- 存储容量
- 分片将数据分布到集群中的各个分片,允许每个分片包含总集群数据的一个子集。随着数据集的增长,新加入更多的分片将增加集群的存储容量。
- 高可用性
- 可以将配置服务器和分片部署为副本集。
- 即使一个或多个分片副本集完全不可用,分片集群也可以继续执行部分读写操作。也就是说,虽然无法访问不可用分片上的数据,但针对可用分片的读写仍然可以成功。
1.4、分片之前的注意事项
- 分片的集群配置之初,就需要仔细的规划、执行和维护。
- 一旦一个集合被分片,就不能取消对集合的分片。
- 虽然可以重新对集合进行分片,但一定要认真选择shard key,以避免可伸缩性和性能问题。
- 如果查询不包括shard key或使用符合shard key开头的索引,则mongos扫描整个分片,即查询分片架构中的所有分片,这种操作耗时非常长。
1.5、分片集合和非分片集合
- 数据库可以混合使用分片集合和非分片集合。
- 分片集合切分并分布在集群中的各个分片上。
- 未分片的集合存储在主分片上。
- 下图是一个有两个分片的集群架构,可以看出所有未开启分片的集合都会存储在主分片上。
1.6、分片策略
- MongoDB支持两种分片策略,用于在分片集群之间分发数据。
1、Hash分片
- 选择作为Hash shard key的字段应具有良好的基数或大量不同的值,对字段单调变化(如Objectld值或时间戳〉的shard key是比较好的。
- Hash分片涉及计算shard key字段值的散列,然后根据散列的shard key值为每个块分配一个范围。
- MongoDB在使用Hash索引解析查询时自动计算散列值,而应用程序不需要计算啥希值。
- 虽然一系列shard key可能是“接近的”,但它们的散列值不太可能在同一个块上。基于散列值的数据分布有利于更均匀的分布数据,特别是在shard key单调变化的数据集中。然而,Hash分布意味着查询范围大,需要扫描所有分片,这个效率是比较低的。
2、range(范围)分片
- range分片根据范围将值放到指定的分片中,每个Chunk根据自己的范围存放到对应的分片中。
- range分片使得数据可能驻留在相同的Chunk上,这允许有针对性的操作,因为mongos可以将对应的操作仅路由到包含该数据的Shard上。
- range分片的效率取决于选择的shard key,shard key选择得不好会导致数据分布不均匀,这可能会使得整个分片集群遇到瓶颈。
- 从下图能够看出,值相近的会放入一个Chunk中,如果查询的文档涉及的Chunk是连续的,则对于范围查询来说会有较好的效率。
- 一个优秀的范围分片应该具有以下特征:
- shard key的值范围比较大
- 不存在高频的范围
- 非单调递增或递减
1.7、分片集群中的zone(分区)
- 分区可以帮助跨多个数据中心的分片集群提高数据的局部性。
- 在分片集群中,可以根据shard key创建分片数据分区。
- 每个分区与集群中的一个或多个分片相关联。
- 一个分片可以与任意数量的分区相关联。
- 在均衡数据时,MongoDB只将一个分区的块迁移到与该分区关联的那些分片上。
- 如下图所示,一个zone可以包含多个范围(range),一个zone可以划分到多个分片中,zone的范围始终是左闭右开的。
- 定义zone时,必须使用shard key中包含的字段。如果使用复合shard key,shard key列必须作为复合索引的前缀(类似MySQL 的最左前缀原则)。
- 从MongoDB 4.0.3开始,在对空集合或不存在的集合进行分片之前设置分区和分区范围可以更快地设置分区分片。
- 一般zone应用于如下场景:
- 隔离一组特定分片上的特定数据子集。
- 确保最相关的数据位于地理位置最接近的应用程序服务器的shard上。
- 根据Shard硬件的性能将数据路由到Shard中。
1.8、排序集合进行分片
- 使用带有collation: {locale: "simple"}选项的shardCollection命令对具有默认排序规则的集合进行分片。需要:
- 集合必须有一个前缀为shard key的索引
- 索引必须有排序规则{locale: "simple"}
- 对分片集合的查询将继续使用为集合配置的默认排序规则。要使用shard key索引的简单排序规则,请在查询的排序规则文档中指定{locale: "simple"}。
2、分片集群的组件
2.1、Shards(分片)
- 一个分片包含一个分片集群的分片数据的子集。
- 客户端要连接到mongos执行集群级别的读或写操作,而不应连接到单个分片机器上进行读或写入操作。
1、主分片
- 分片集群中的每个数据库都有一个主分片,用于保存该数据库的所有非分片集合。主分片与复制集中的主分片没有关系。
- 当创建一个新数据库时,mongos通过在集群中选择数据量最少的分片来作为该数据库的主分片。
- 使用movePrimary命令可以更改数据库的主分片。迁移主分片的过程可能需要很长时间才能完成,在迁移完成之前不应该访问与该数据库关联的集合。根据迁移的数据量,迁移可能会影响整个集群操作。
2、分片的状态
- 可以使用sh.status()查看分片集群的概述,包括哪个分片是数据库的主分片以及跨分片的块分布。
2.2、Config Servers(配置服务器)
- 从3.4开始,不再支持使用镜像mongod实例作为配置服务器(SCCC)。在将分片集群升级到3.4之前,必须将配置服务器从SCCC转换为CSRS(config server的副本集架构)。
- 配置服务器存储分片集群的元数据。元数据反映了分片集群中所有数据和组件的状态和组织,包括每个分片上的块列表和定义块的范围。
- mongos实例缓存这些数据,并使用它将读和写操作路由到正确的分片。mongos在集群的元数据发生变化时更新缓存,比如块分拆或添加一个分片。
- 配置服务器还存储身份验证配置信息,如基于角色的访问控制或集群的内部身份验证设置。
- MongoDB还使用配置服务器来管理分布式锁。
- 每个分片集群必须有自己的配置服务器。不要为不同的分片集群使用相同的配置服务器。
- admin数据库和config数据库在配置服务器上。
- admin数据库包含与身份验证和授权相关的集合,以及内部使用的其他集合(system.*)。
- config数据库包含分片集群元数据的集合。MongoDB在元数据发生变化时(如块迁移或块分裂后)将数据写入配置数据库。
- 在对配置服务器进行任何维护之前,一定要备份config数据库。
- 配置服务器的副本集允许分片集群拥有3个以上的配置服务器,配置服务器必须运行WiredTiger存储引擎。
- 对配置服务器的副本集中的节点的限制:
- 必须没有仲裁节点。
- 必须没有延迟节点。
- 必须构建索引(即没有节点将members[n].buildIndexes设置为false)。
- 用户应避免在正常运行或维护过程中直接写入配置数据库。
- 当写入配置服务器时,MongoDB使用的写关注是“majority”。
- 当读取配置服务器时,MongoDB使用的读关注是“majority”。
- 如果配置服务器副本集失去了它的主节点,并且不能选择一个主节点,集群的元数据将变为只读。但仍然可以从分片中读写数据,但在副本集选择主节点之前,不会发生块迁移或块分割。
- 如果所有配置服务器都不可用,则集群可能无法使用。为了确保配置服务器保持可用和完整,配置服务器的备份是至关重要的。与存储数据的分片服务器相比,配置服务器上的数据很小,并且负载也低。
2.3、mongos(路由器)
- MongoDB mongos实例将读和写操作路由到分片集群中的分片上。从应用程序的角度来看,Mongos为分片集群提供了唯一的接口。应用程序从不直接与分片连接或通信。
- mongos通过缓存配置服务器的元数据来跟踪数据在哪个分片上。mongos使用元数据将应用程序和客户端的操作路由到mongod实例。
- mongos没有持久状态,消耗的系统资源最少。
- 可以在应用服务器上运行mongos实例,但也可以在分片或其他专用资源上运行mongos实例。
1、mangos路由过程和结果
- mongos实例通过以下方式将查询路由到集群:
- 必须确定接收查询的分片列表。
- 在所有目标分片上建立游标。
- mongos将自每个目标分片的数据合并,并返回结果。某些查询修饰符(如排序),在mongos检索结果之前对每个分片执行。
- 在3.6版更改:对于在多个shard上运行的聚合操作,如果操作不需要在数据库的主shard上运行,这些操作可以将结果路由回mongos,然后在那里合并结果。
- 有两种情况下,聚合不适合在mongos上进行。
- 合并部分包含一个必须在主分片上运行的阶段时。例如,如果$lookup需要访问与运行聚合的分片集合相同数据库中的未分片集合,则合并必须在主分片上运行。
- 合并部分包含一个可能将临时数据写入磁盘的阶段,例如$group,并且客户端指定了allowDiskUse:true。在这种情况下,假设合并管道中没有需要主分片的其他阶段,那么合并将在聚合所针对的分片集中随机选择的分片上运行。
2、mongos如何处理查询修饰符
- Sorting
- 如果查询的结果没有排序,mongos实例打开一个结果游标,“轮询”(round robins)所有分片上的结果。
- Limits
- 如果查询使用limit()方法限制结果的大小,mongos实例将该限制传递给分片,然后在将结果返回给客户端之前将该限制重新应用到结果上。
- Skips
- 如果查询使用skip()方法指定要跳过的记录数量,mongos不能skip()传递给分片,而是在合并结果后跳过指定数量的文档。
- 当与limit()一起使用时,mongos将把limit加上skip()的值传递给分片,以提高这些操作的效率。
3、广播操作
- 通常,在分片集群中最快的查询是mongos将查询操作路由到单个分片的查询。使用shard key和来自配置服务器的集群元数据,定位满足查询文档的分片或分片子集。
- 对于不包含shard key的查询,mongos必须查询所有的分片,等待它们的响应,然后将结果返回给应用程序。这些“分散/收集”查询可以是长时间运行的操作。
- mongos从所有分片接收到响应后,它合并数据并返回结果文档。广播操作的性能取决于集群的总体负载,以及网络延迟、单个分片负载和每个分片返回的文档数量等变量。只要可能,优先考虑导致目标操作的操作,而不是导致广播操作的操作。
- 广播操作:
- updateMany()和deleteMany()方法是广播操作,除非查询文档完整地指定了shard key。
- 路由到指定的分片的操作:
- Mongos可以将包含shard key或复合shard key前缀的查询路由到特定的shard或shard集。Mongos使用shard key值来定位其范围包括shard key值的块,并将查询指向包含该块的分片。
- 所有insertOne()操作都指向一个分片。insertMany()数组中的每个文档都指向单个分片,但不能保证数组中的所有文档都插入到单个分片中。
- 所有updateOne()、replaceOne()和deleteOne()操作都必须在查询文档中包含shard key或_id。如果使用这些方法时没有shard key或_id, MongoDB将返回一个错误。
- 索引使用
- 如果查询不包含shard key, mongos必须将查询作为“分散/聚集”操作发送到所有分片。每个分片将依次使用shard key索引或另一个更有效的索引来完成查询。
- 如果查询包含多个引用由shard key和二级索引索引的字段的子表达式,mongos可以将查询路由到特定的分片,而分片将使用允许它最有效地完成的索引。
3、Shard Keys
- shard key可以是单个字段,也可以是复合的多个字段。shard key决定了集合中存储的数据在Shard集群中的分布。
- MangoDB使用shard key值的范围对集合中的数据进行切割, 每个范围定义了shard key值的非重叠范围,并且与Chunk相关联。
- MangoDB会尝试在集群中的分片之间均匀分配Chunk,shard key与Chunk分布的有效性有直接关系。
1、shard key的索引
- 所有的分片集合必须有一个支持shard key的索引。索引可以是shard key上的索引,也可以是复合索引,其中shard key是索引的前缀。
- 如果集合为空,sh.shardCollection()在shard key上创建索引(如果这样的索引还不存在)。
- 如果集合不为空,则必须在使用sh.shardCollection()之前先创建索引。
- 如果删除了shard key的最后一个有效索引,则通过仅在shard key上重新创建索引来恢复。
2、唯一索引
- 对于分片集合,只有id字段索引、shard key上的索引、或shard key是前缀的复合索引可以是唯一的:
- 如果其他字段有唯一索引,则不能对该集合进行分片,也无法在分片集合的其他字段上创建唯一索引。
- 如果集合为空,则sh.shardCollection()将在shard key上创建唯一索引;如果集合不为空,则必须在使用sh.shardCollection()之前创建索引。
- 不能对Hash索引指定唯一索引。
3、选择一个shard key
- shard key的选择会影响分片集群的均衡器在可用的分片中创建和分发chunk的过程,即影响分片集群内操作的整体效率和性能。
- shard key影响分片集群使用分片策略的性能和效率。
- 理想的shard key允许MongoDB在整个集群中平均分配文档。
- 如下图所示,要考虑x在各个范围的分布,如果X在10到20的居多,就会导致分片不均匀,即Shard B的数据会远高于Shard A和Shard C,这对性能有很大影响。
4、shard key的基数
- shard key的基数决定了均衡器可以创建的最大块数,这可以降低或消除集群中水平缩放的有效性。
- 在任何给定时间,每个唯一的shard key值只能存在于一个块上。例如一个包含带有七大洲字段的用户数据的数据集。如果你选择用七大洲进行分片,shard key的基数将是7。基数为7意味着在分片集群中不能有超过7个块,每个块存储一个唯一的shard key值。这也限制了集群中有效分片的数量为7个——添加超过7个分片不会带来任何好处。
- 下图显示了使用字段X作为shard key的分片集群,如果X具有较低的基数,则插入的分布可能看起来类似于以下内容。
5、shard key的频率
- 决定shard key时,要考虑到写入的shard key频率是否过高,如果大多数文档只包含这些值的一个子集,那么存储这些文档的Chunk就成为集群内的一个瓶颈。而且,随着这些大块的成长,它们可能变成不可分割的块,因为它们不能再分裂。
- 频率低的shard key也不能保证在分片集群中数据的均匀分布,shard key的基数和变化率都和数据分配相关。
- 如果你的数据模型需要使用具有高频率值的shard key进行分片,则可考虑使用唯一或低频率值的复合索引。
- 下图显示了使用字段X作为shard key的分片集群。如果X值的子集高频出现,则插入的分布可能看起来类似于以下内容。
6、shard key单调递增或递减
- 单调增加或减少的shard key更有可能导致其中一个块数据量过大。
- 如果shard key值始终增加,则将所有新插入的键值以maxKey作为上限路由到Chunk中;如果shard key值始终减小,则将所有新插入的键值以minKey作为下限进行路由操作。包含该Chunk的分片将成为写入操作的瓶颈。
- 下图显示了使用字段X作为shard key的分片集群,如果X的值单调递增,则插入的分布可能如下所示。
4、Chunk(块)
- MongoDB使用shard key将数据分成若干个Chunk,Chunk是集合的子集。每个Chunk具有基于shard key的范围,左闭右开。
- mangos根据shard key的值将文档写入对应的Chunk,当超出配置的Chunk大小时,MongoDB会分割Chunk。插入和更新都可以触发Chunk拆分。
- Chunk可以表示的最小范围是单个唯一的shard key值,只包含具有单个shard key值文档的Chunk不能被分割。
1、Chunk的大小
- 块的默认大小是64MB,可以增加或减小Chunk大小。
- 小Chunk可以十数据分布地更加均匀,但会导致频繁的迁移,这在查询路(mongos)时会有一定开销。
- 大Chunk触发的迁移更少,但也会导致数据分布不均匀。
- 为一个己经存在的集合做分片操作时,Chunk的大小会影响该集合的最大大小值。Chunk分割后,Chunk大小不会限制集合大小。
2、Chunk的限制
- 更改Chunk大小会影响Chunk的拆分,所以会受到一些限制。
- 自动分割仅在插入或更新期间发生,如果降低Chunk大小,则可能需要一段时间才能将所有Chunk分割完。
- 拆分不能被“撤消”,如果增加Chunk大小,现有的Chunk必须通过插入或更新来增长,直至达到阔值后才能拆分。
3、Chunk的拆分
- 分裂是为了让Chunk不能太大,当一个Chunk增长到指定大小后,或者如果该Chunk中的文档数量超过了每个Chunk的最大文档数时,MongoDB将根据该Chunk的shard key值来分割Chunk。插入和更新可能触发拆分。
- 分裂可能会导致Chunk在Shard集群中分布不均匀,这时候balancer会均衡各Shard中Chunk的数量。
4、Chunk迁移
- MongoDB迁移Chunk的情况有:
- 手动迁移,一般我们不需要手动迁移Chunk。
- 自动迁移,balancer进程在各个Shard中分布不均匀时进行Chunk迁移。
- balancer是管理Chunk迁移的后台进程,如果各Shard之间的Chunk数量差值超过了阔值,则balancer开始在集群中迁移Chunk以确保数据的均匀分布。
5、不可分割的Chunk
- 在某些情况下,Chunk可能超出指定的块大小,但不能进行拆分。最常见的情况是,块代表单个shard key值。由于块不能分割,所以它会继续增长,超出块的大小,成为一个巨大的块。
- 这些巨型块可能会成为一个性能瓶颈,因为它们继续增长,尤其是当shard key值高频率出现的时候很容易遇到瓶颈。
- 新数据或新分片的添加可能导致集群内的数据分布不均衡。一个特定的分片可能比另一个分片获得更多的块,或者块的大小可能超过配置的最大块大小。
5、部署分片集群
5.1、部署环境
- 软件版本
- mongodb-org-server-5.0.11
- 系统环境
- 10.1.1.11:CentOSLinuxrelease7.7.1908(Core)
- 10.1.1.12:CentOSLinuxrelease7.7.1908(Core)
- 10.1.1.13:CentOSLinuxrelease7.7.1908(Core)
- 部署架构图
- 端口分配
- Shard Server 1:27017(副本集)
- Shard Server 2:27018(副本集)
- Shard Server 3:27019(副本集)
- Config Server:27020(副本集)
- mongos Server:27021(三个独立节点)
5.2、准备三个节点
- 在三台机器上分别安装mongodb。
- https://www.cnblogs.com/maiblogs/p/16656465.html
5.3、部署shard
- 以部署shard 1为例。
1、配置文件
- 注意,每个分片的副本集名称和端口是不同的。
//三个机器上都有,修改IP即可 cat > /etc/mongod-shard-1.conf << EOF systemLog: destination: file logAppend: true path: /apps/mongodb/logs-27017/mongod.log storage: dbPath: /apps/mongodb/data-27017/ journal: enabled: true directoryPerDB: true processManagement: fork: true pidFilePath: /apps/mongodb/mongod-27017.pid timeZoneInfo: /usr/share/zoneinfo net: port: 27017 bindIp: 10.1.1.11 #副本集名称,每个分片的副本集名称是不同的 replication: replSetName: rs1 #在分片集群中的角色 sharding: clusterRole: shardsvr EOF
- 创建目录
mkdir -p /apps/mongodb/{data,logs}-27017/
2、启动shard服务
//在三个节点上分布启动shard 1 mongod --config /etc/mongod-shard-1.conf
3、将shard 1配置成副本集
- 连接shard 1
//连接到那个主机,那个主机上的将主节点 mongosh --host 10.1.1.11:27017
- 初始化shard 1
rs.initiate( { _id : "rs1", members: [ { _id : 0, host : "10.1.1.11:27017" }, { _id : 1, host : "10.1.1.12:27017" }, { _id : 2, host : "10.1.1.13:27017" } ] } )
4、另外两个shard的配置文件
- shard 2的配置文件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
cat > /etc/mongod-shard-2.conf << EOF systemLog: destination: file logAppend: true path: /apps/mongodb/logs-27018/mongod.log storage: dbPath: /apps/mongodb/data-27018/ journal: enabled: true directoryPerDB: true processManagement: fork: true pidFilePath: /apps/mongodb/mongod-27018.pid timeZoneInfo: /usr/share/zoneinfo net: port: 27018 bindIp: 10.1.1.11 #副本集名称,每个切片的副本集名称是不同的 replication: replSetName: rs2 #在切片集群中的角色 sharding: clusterRole: shardsvr EOF
- shard 3的配置文件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
cat > /etc/mongod-shard-3.conf << EOF systemLog: destination: file logAppend: true path: /apps/mongodb/logs-27019/mongod.log storage: dbPath: /apps/mongodb/data-27019/ journal: enabled: true directoryPerDB: true processManagement: fork: true pidFilePath: /apps/mongodb/mongod-27019.pid timeZoneInfo: /usr/share/zoneinfo net: port: 27019 bindIp: 10.1.1.11 #副本集名称,每个切片的副本集名称是不同的 replication: replSetName: rs3 #在切片集群中的角色 sharding: clusterRole: shardsvr EOF
5.4、部署config server
1、配置文件
- config server的和分片的配置文件区别是clusterRole: configsvr和replSetName: configserver,同时修改路径和端口号
//三个机器上都有,修改IP即可 cat > /etc/mongod-config.conf << EOF systemLog: destination: file logAppend: true path: /apps/mongodb/logs-27020/mongod.log storage: dbPath: /apps/mongodb/data-27020/ journal: enabled: true directoryPerDB: true processManagement: fork: true pidFilePath: /apps/mongodb/mongod-27020.pid timeZoneInfo: /usr/share/zoneinfo net: port: 27020 bindIp: 10.1.1.11 #副本集名称 replication: replSetName: configserver #在分片集群中的角色 sharding: clusterRole: configsvr EOF
- 创建目录
mkdir -p /apps/mongodb/{data,logs}-27020/
2、启动config server服务
//在三个节点上分布启动config server mongod --config /etc/mongod-config.conf
3、将config server配置成副本集
- 连接config server
mongosh --host 10.1.1.11:27020
- 初始化config server
rs.initiate( { _id : "configserver", members: [ { _id : 0, host : "10.1.1.11:27020" }, { _id : 1, host : "10.1.1.12:27020" }, { _id : 2, host : "10.1.1.13:27020" } ] } )
5.5、部署mongos
1、配置文件
//三个机器上都有,修改IP即可 cat > /etc/mongos.conf << EOF systemLog: destination: file logAppend: true path: /apps/mongodb/logs-27021/mongos.log processManagement: fork: true pidFilePath: /apps/mongodb/mongos-27021.pid timeZoneInfo: /usr/share/zoneinfo net: port: 27021 bindIp: 10.1.1.11 #config server的replSetName/ip:port sharding: configDB: configserver/10.1.1.11:27020,10.1.1.12:27020,10.1.1.13:27020 EOF
- 创建目录
mkdir -p /apps/mongodb/logs-27021/
2、启动mongos服务
//在三个节点上分布启动mongos mongos --config /etc/mongos.conf
3、向分片集群中添加分片
- 连接mongos
mongosh --host 10.1.1.11:27021
- 向分片集群中添加分片(仅在一个节点上执行即可)
//shard的replSetName/ip:port sh.addShard("rs1/10.1.1.11:27017,10.1.1.12:27017,10.1.1.13:27017") sh.addShard("rs2/10.1.1.11:27018,10.1.1.12:27018,10.1.1.13:27018") sh.addShard("rs3/10.1.1.11:27019,10.1.1.12:27019,10.1.1.13:27019")
5.6、启用分片
- 在对集合进行分片之前,必须为集合所在的数据库启用分片。为数据库启用分片并不会重新分配数据,但可以对该数据库中的集合进行分片。
1、为数据库启用分片
- 一旦为一个数据库启用了分片,MongoDB会为该数据库分配一个主分片,MongoDB在该数据库中存储了所有数据。
//(1)连接到mongos mongosh --host 10.1.1.11:27021 //(2)为数据库启用分片 sh.enableSharding("<database>")
2、为集合启用分片
- 如果集合已经包含数据,在对集合进行分片之前,必须创建一个支持shard key的索引。如果集合为空,MongoDB将创建索引作为sh.shardCollection()的一部分。
- 两种分片收集策略
//哈希分片使用单个字段的哈希索引作为shard key,在整个分片集群中划分数据 sh.shardCollection("<database>.<collection>", { <shard key field> : "hashed" } ) //基于范围的分片可以使用多个字段作为shard key,并将数据划分为由shard key值确定的连续范围 sh.shardCollection("<database>.<collection>", { <shard key field> : 1, ... } )
6、管理分片集群
//查看分片集群的状态 sh.status() //添加一个分片 sh.addShard(<url>):向分片集群中添加一个分片。 sh.addShard("repl0/mongodb3.example.net:27327") //启用分片 sh.enableSharding(database, primaryShard):在指定的数据库上启用分片。一旦为数据库启用了分片,就可以使用sh.shardCollection()对数据库中的集合进行分片。 //为集合启用分片。 sh.shardCollection( namespace, #"<database>.<collection>" key, #{ <field1>: <1|"hashed">, ... } unique, #可选的,boolean { numInitialChunks: integer #可选的。指定在使用hash分片对空集合进行分片时最少的块数。每个分片的numInitialChunks必须小于8192。默认为2。 collation: document #可选的。如果指定给shardCollection的集合具有默认排序规则,则必须包含带有{locale: "simple"}的排序规则文档,否则shardCollection命令将失败。字段支持shard key模式的索引中至少有一个必须具有简单排序规则。 presplitHashedZones: boolean #可选的。指定true可根据为集合定义的区域和区域范围为空或不存在的集合执行初始块创建和分发。仅针对哈希分片。 }) //查看均衡器的信息 sh.getBalancerState():查看是否启用了均衡器,返回true表示启用了均衡器。但这并不反映均衡操作的当前状态。 sh.isBalancerRunning():查看均衡器是否正在迁移数据块。返回true,表示正在迁移数据块 //启用或禁用均衡器 sh.setBalancerState(state):启用或禁用均衡器。从MongoDB 4.2开始,如果启用均衡器,该方法也会启用自动分裂,如果禁用均衡器,则禁用自动分裂。 sh.startBalancer(timeout, interval):启动均衡器并等待均衡启动。从MongoDB 4.2开始,sh.startBalancer()也支持分片集群的自动分裂。 sh.stopBalancer(timeout, interval):禁用分片集群中的均衡器。从MongoDB 4.2开始,sh.stopBalancer()也禁止分片集群的自动分裂。 sh.disableBalancing(namespace):在指定集合上禁用均衡器。但不影响其他集合的均衡。 sh.enableBalancing(namespace):如果之前使用sh.disableBalancing()禁用了均衡器,则该方法可以均衡器。 //等待均衡器的变化 sh.waitForBalancer(wait, timeout, interval):内部的。等待均衡器状态改变。 sh.waitForBalancerOff(timeout, interval):内部的。等待直到均衡器停止运行。 //启用或禁用块自动拆分 sh.disableAutoSplit():禁用分片集群中块的自动拆分功能。默认情况下块的自动拆分是启用的。 sh.enableAutoSplit():启用分片集群中块的自动拆分功能 //拆分块 sh.splitAt(namespace, query):使用shard key的特定值(查询)作为分界点,将现有的块分成两个块。 sh.splitAt( "test.foo", { x: 70 } ) sh.splitFind(namespace, query):将包含匹配查询的文档的现有块划分为两个大致相等的块。 sh.splitFind( "test.foo", { x: 70 } ) //迁移块 sh.moveChunk(namespace, query, destination):将包含查询指定的文档的块迁移到目标分片。 //块是否均衡 sh.balancerCollectionStatus(namespace):返回关于分片集合的块是否均衡的信息。4.4新版功能。 sh.balancerCollectionStatus("test.contacts") //重新分片 sh.reshardCollection(namespace, key, unique, options):进行重新分片操作。以更改集合的shard key,从而更改数据的分布。5.0新版功能。 sh.commitReshardCollection(namespace):在重分片操作期间,MongoDB不会阻塞写操作,使用该方法阻止写操作直到重分片完成。5.0新版功能。 sh.commitReshardCollection("sales.orders") sh.abortReshardCollection():在重分片操作期间,可以使用该方法中止重分操作。5.0新版功能。在提交阶段之前,可以在任何时候中止重分片操作。如果在运行sh.abortReshardCollection()方法之前,重分片操作已经达到提交阶段,该方法将返回一个错误。 sh.abortReshardCollection("sales.orders") //zone与分片 sh.addShardTag(shard, tag):将一个分片关联到一个zone。支持在分片集群中配置分区。在MongoDB 3.4中,这个方法别名为sh.addShardToZone(shard, zone) sh.addShardTag("shard0000", "NYC") sh.addShardToZone("shard0000", "JFK") sh.removeShardTag():移除分片和区域之间的关联。管理分区分片。在MongoDB 3.4中,这个方法别名为sh.removeShardFromZone(shard, zone) //zone与shard key sh.addTagRange(namespace, minimum, maximum, tag):将多个shard key关联到一个zone。支持在分片集群中配置分区。在MongoDB 3.4中,这个方法别名为sh.updateZoneKeyRange() sh.addTagRange( "exampledb.collection", { state: "NY", zip: MinKey }, { state: "NY", zip: MaxKey }, "NY" ) sh.removeTagRange(namespace, minimum, maximum, tag):移除多个shard key和区域之间的关联。支持在分片集群中配置分区。在MongoDB 3.4中,这个方法别名为sh.removeRangeFromZone(namespace, minimum, maximum) sh.waitForPingChange(activePings, timeout, interval):内部的。等待来自分片集群中的一个mongos的ping状态的变化。 convertShardKeyToHashed():返回输入的散列值。
1
# #