MongoDB副本集与分片

一、MongoDB 副本集

1.1、MongoDB复制

在mongodb学习阶段,一般用的都是单台服务器,一个mongod服务进程。如果仅仅作为学习开发是可以的,但是如果用到生产环境,风险会很高,例如服务器崩溃、硬件出现问题,最坏的情况是磁盘或网络出问题可能会导致数损坏或数据不可访问。

MongoDB复制是将数据同步在多个服务器的过程。
复制提供了数据的冗余备份,并在多个服务器上存储数据副本,提高了数据的可用性, 并可以保证数据的安全性。

1.2、MongoDB副本集模式的好处:

  • 一切自动化。首先,复制集模式本身做了大量的管理工作,自动管理从节点,确保数据不会不一致。
  • 主节点挂掉后,会自动判断集群中的服务器并进行故障转移,推举新的主节点。
  • 一个复制集集群支持1-7台服务器,在一个复制集中各个服务器数据保持完全一致。

1.3、副本集集群状态

在一个MongoDB副本集集群中,各个服务器有以下几种状态:

  • Primary 主节点,一个复制集有且仅有一台服务器处于Primary状态,只有主节点才对外提供读写服务。如果主节点挂掉,复制集将投票选出一个备节点成为新的主节点。
  • Secondary 备用节点,复制集允许有多台Secondary,每个备用节点的数据与主节点的数据是完全同步的。Recovering 恢复中,当复制集中某台服务器挂掉或者掉线后数据无法同步,重新恢复服务后从其他成员复制数据,这时就处于恢复过程,数据同步后,该节点又回到备用状态。
  • Arbiter 仲裁节点,该类节点可以不用单独存在,如果配置为仲裁节点,就主要负责在复本集中监控其他节点状态,投票选出主节点。该节点将不会用于存放数据。如果没有仲裁节点,那么投票工作将由所有节点共同进行。
  • Down 无效节点,当服务器挂掉或掉线时就会处于该状态。复制集的从节点读请求,也是在各个Driver层设置slaveOk的值来实现的。

1.4、副本集

副本集是一组维护相同数据集的mongod实例

副本集是一组服务器,其中有一个是主服务器(primary),用于处理客户端请求;还有多个备份服务器(secondary),用于保存主服务器的数据副本。如果主服务器崩溃了,备份服务器会自动将其中一个成员升级为新的主服务器。

MongoDB复制结构图如下所示:
在这里插入图片描述

1.5、选举机制

当一个备份节点无法与主节点连通,会联系其他副本成员将自己选为主节点。其他成员会判断自身与主是否连通,被选举的备份节点数据是否最新,有没有其他更高优先级成员可以被选举。
最终被选举的节点的得票数,需满足所有节点一半以上的成员。

1.6、仲裁者(arbiter)

在某些情况下(例如您有一个primary服务器和一个second服务器,但由于成本限制,禁止添加另一个second服务器),您可以选择将mongod实例作为仲裁者添加到副本集。

仲裁者唯一的最用就是参与选举,仲裁者并不保存数据,也不会为客户端提供服务,它只是为了帮助具有两个成员的副本集能够满足"大多数"这个条件。

仲裁者的存在使得复制集可以以偶数个节点存在,而无需为复制集再新增节点 不要将投票节点运行在复制集的主节点或从节点机器上。 仲裁者与其他 复制集节点的交流仅有:选举过程中的投票,心跳检测和配置数据。这些交互都是不加密的。

典型的副本集是一主两从,允许有一台挂掉。实际应用中,应用在资源有限的情况下(mongodb需要运行在高性能服务器上),不得不采用一主一从的架构,那么额外配置一台普通服务器充当仲裁者,其目的仅仅是参与选举投票,作为一台凑数服务器使用。
在这里插入图片描述
需要注意的是:仲裁者只有副本集是偶数个时才能用。如果可能在副本集中使用奇数个数据成员,而不要使用仲裁者。

二、MongoDB 分片

2.1、分片简介

分片(sharding)是指将数据库拆分,将其分散在不同的机器上的过程。将数据分散到不同的机器上,不需要功能强大的服务器就可以存储更多的数据和处理更大的负载。基本思想就是将集合切成小块,这些块分散到若干片里,每个片只负责总数据的一部分,最后通过一个均衡器来对各个分片进行均衡(数据迁移)。通过一个名为mongos的路由进程进行操作,mongos知道数据和片的对应关系(通过配置服务器)。大部分使用场景都是解决磁盘空间的问题,对于写入有可能会变差,查询则尽量避免跨分片查询。使用分片的时机:

1,机器的磁盘不够用了。使用分片解决磁盘空间的问题。
2,单个mongod已经不能满足写数据的性能要求。通过分片让写压力分散到各个分片上面,使用分片服务器自身的资源。
3,想把大量数据放到内存里提高性能。和上面一样,通过分片使用分片服务器自身的资源。

2.2、分片优点

  • mongos 对集群进行抽象,让集群“不可见”
    MongoDB自带了一个叫做Mongos的专有路由进程,mongos就是掌握统一路口的路由器,它会将客户端发来的请求准确无误的路由到集群中的一个或者一组服务器上,同时会把接收到的响应拼装起来发回到客户端。
  • 保证集群总是可读写的
    MongoDB通过多种途径来确保集群的可用性和可靠性。将MongoDB的分片和复制功能结合使用,在确保数据分片到多台服务器的同时,也确保了每分数据都有相应的备份,这样就可以确保有服务器换掉时,其他的从库可以立即接替坏掉的部分继续工作。
  • 使集群易于扩展
    当系统需要更多的空间和资源的时候,MongoDB使我们可以按需方便的扩充系统容量。

2.3、分片集群架构

在这里插入图片描述

  • Config Server:
    mongod实例,存储了整个集群和分片的元数据,其中包括 chunk信息;
  • Shard:
    用于存储实际的数据块,实际生产环境中一个shard server角色可由几台机器组个一个replica set承担,防止主机单点故障;
  • mongos:
    当数据写入时,MongoDB Cluster根据分片键设计写入数据。
    当外部语句发起数据查询时,MongoDB根据数据分布自动路由至指定节点返回数据。
  • mongod
    存储应用数据记录。一般有多个Mongod节点,达到数据分片目的。

在这里插入图片描述

2.4、片键

MongoDB中数据的分片是以集合为基本单位的,集合中的数据通过片键(Shard key)被分成多部分。其实片键就是在集合中选一个键,用该键的值作为数据拆分的依据。

所以一个好的片键对分片至关重要。片键必须是一个索引,通过sh.shardCollection加会自动创建索引(前提是此集合不存在的情况下)。一个自增的片键对写入和数据均匀分布就不是很好,因为自增的片键总会在一个分片上写入,后续达到某个阀值可能会写到别的分片。但是按照片键查询会非常高效

随机片键对数据的均匀分布效果很好。注意尽量避免在多个分片上进行查询。在所有分片上查询,mongos会对结果进行归并排序。

对集合进行分片时,你需要选择一个片键,片键是每条记录都必须包含的,且建立了索引的单个字段或复合字段,MongoDB按照片键将数据划分到不同的数据块中,并将数据块均衡地分布到所有分片中

为了按照片键划分数据块,MongoDB使用基于范围的分片方式或者基于哈希的分片方式。

注意:

分片键是不可变。
分片键必须有索引。
分片键大小限制512bytes。
分片键用于路由查询。
MongoDB不接受已进行collection级分片的collection上插入无分片键的文档(也不支持空值插入)。

2.5、Chunk

在一个shard server内部,MongoDB还是会把数据分为chunks,每个chunk代表这个shard server内部一部分数据。chunk的产生,会有以下两个用途:

  • Splitting:当一个chunk的大小超过配置中的chunk size时,MongoDB的后台进程会把这个chunk切分成更小的chunk,从而避免chunk过大的情况

  • Balancing:在MongoDB中,balancer是一个后台进程,负责chunk的迁移,从而均衡各个shard server的负载,系统初始1个chunk,chunk size默认值64M,生产库上选择适合业务的chunk size是最好的。MongoDB会自动拆分和迁移chunks。

分片集群的数据分布(shard节点):

(1)使用chunk来存储数据
(2)进群搭建完成之后,默认开启一个chunk,大小是64M,
(3)存储需求超过64M,chunk会进行分裂,如果单位时间存储需求很大,设置更大的chunk
(4)chunk会被自动均衡迁移。

chunk分裂及迁移:
随着数据的增长,其中的数据大小超过了配置的chunk size,默认是64M,则这个chunk就会分裂成两个。数据的增长会让chunk分裂得越来越多。
在这里插入图片描述
这时候,各个shard 上的chunk数量就会不平衡。这时候,mongos中的一个组件balancer 就会执行自动平衡。把chunk从chunk数量最多的shard节点挪动到数量最少的节点。
在这里插入图片描述

2.6、片键策略

2.6.1、基于范围划分

Sharded Cluster支持将单个集合的数据分散存储在多shard上,用户可以指定根据集合内文档的某个字段即shard key来进行范围分片(range sharding)。

对于基于范围的分片,MongoDB按照片键的范围把数据分成不同部分。

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

因为数据文件递增,所以会把insert的写IO永久放在最后一片上,造成最后一片的写热点。同时,随着最后一片的数据量增大,将不断的发生迁移至之前的片上。而不能像一个比较均衡分发的系统那样,只需要纠正小的不均衡就好了。

我们可以用一些无规律的字段,比如UUID,作为升序片键,使其规避掉不均衡分发的为问题

2.6.2、基于散列划分

分片过程中利用哈希索引作为分片的单个键,且哈希分片的片键只能使用一个字段,而基于哈希片键最大的好处就是保证数据在各个节点分布基本均匀。
 对于基于哈希的分片,MongoDB计算一个字段的哈希值,并用这个哈希值来创建数据块。在使用基于哈希分片的系统中,拥有”相近”片键的文档很可能不会存储在同一个数据块中,因此数据的分离性更好一些。

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

2.6.3、 两种片键策略比较

基于范围划分对于范围查询比较高效。假设在shard key上进行范围查询,查询路由很容易能够知道哪些块与这个范围重叠,然后把相关查询按照这个路线发送到仅仅包含这些chunks的分片。但是基于范围划分很容易导致数据不均匀分布,这样会削弱分片集群的功能。例如当shard key是个成直线上升的字段,如时间。那么,所有在给定时间范围内的请求都会映射到相同的chunk,也就是相同的分片上。这种情况下,小部分的分片将会承受大多数的请求,那么系统整体扩展并不理想。

相反的,基于散列划分是以牺牲高效范围查询为代价,它能够均匀的分布数据,散列值能够保证数据随机分布到各个分片上。

分片注意:

  • 分片键是不可变、分片键必须有索引、分片键大小限制512bytes、分片键用于路由查询。
  • MongoDB不接受已进行collection级分片的collection上插入无分片键的文档(也不支持空值插入)
  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值