MongoDB 分片集群技术

作者: IT_小白 | 来源:发表于2018-08-10 17:10 被阅读0次

    1.1 MongoDB复制集简介

    一组Mongodb复制集,就是一组mongod进程,这些进程维护同一个数据集合。复制集提供了数据冗余和高等级的可靠性,这是生产部署的基础。

    1.1.1 复制集的目的

      保证数据在生产部署时的冗余和可靠性,通过在不同的机器上保存副本来保证数据的不会因为单点损坏而丢失。能够随时应对数据丢失、机器损坏带来的风险。

      换一句话来说,还能提高读取能力,用户的读取服务器和写入服务器在不同的地方,而且,由不同的服务器为不同的用户提供服务,提高整个系统的负载。

    1.1.2 简单介绍

      一组复制集就是一组mongod实例掌管同一个数据集,实例可以在不同的机器上面。实例中包含一个主导,接受客户端所有的写入操作,其他都是副本实例,从主服务器上获得数据并保持同步。

      主服务器很重要,包含了所有的改变操作(写)的日志。但是副本服务器集群包含有所有的主服务器数据,因此当主服务器挂掉了,就会在副本服务器上重新选取一个成为主服务器。

      每个复制集还有一个仲裁者,仲裁者不存储数据,只是负责通过心跳包来确认集群中集合的数量,并在主服务器选举的时候作为仲裁决定结果。

    1.2 复制的基本架构

    基本的架构由3台服务器组成,一个三成员的复制集,由三个有数据,或者两个有数据,一个作为仲裁者。

    1.2.1 三个存储数据的复制集

    具有三个存储数据的成员的复制集有:

    一个主库;两个从库组成,主库宕机时,这两个从库都可以被选为主库。 当主库宕机后,两个从库都会进行竞选,其中一个变为主库,当原主库恢复后,作为从库加入当前的复制集群即可。

    1.2.2 当存在arbiter节点

    在三个成员的复制集中,有两个正常的主从,及一台arbiter节点:

    一个主库    一个从库,可以在选举中成为主库    一个aribiter节点,在选举中,只进行投票,不能成为主库

    说明:

      由于arbiter节点没有复制数据,因此这个架构中仅提供一个完整的数据副本。arbiter节点只需要更少的资源,代价是更有限的冗余和容错。

    当主库宕机时,将会选择从库成为主,主库修复后,将其加入到现有的复制集群中即可。

    1.2.3 Primary选举

      复制集通过replSetInitiate命令(或mongo shell的rs.initiate())进行初始化,初始化后各个成员间开始发送心跳消息,并发起Priamry选举操作,获得『大多数』成员投票支持的节点,会成为Primary,其余节点成为Secondary。

    『大多数』的定义

      假设复制集内投票成员(后续介绍)数量为N,则大多数为 N/2 + 1,当复制集内存活成员数量不足大多数时,整个复制集将无法选举出Primary,复制集将无法提供写服务,处于只读状态。

    通常建议将复制集成员数量设置为奇数,从上表可以看出3个节点和4个节点的复制集都只能容忍1个节点失效,从『服务可用性』的角度看,其效果是一样的。(但无疑4个节点能提供更可靠的数据存储)

    1.3 复制集中成员说明

    所有成员说明

    1.3.2 Priority 0节点

    作为一个辅助可以作为一个备用。在一些复制集中,可能无法在合理的时间内添加新成员的时候。备用成员保持数据的当前最新数据能够替换不可用的成员

    1.3.3 Hidden 节点(隐藏节点)

      客户端将不会把读请求分发到隐藏节点上,即使我们设定了 复制集读选项 。

    这些隐藏节点将不会收到来自应用程序的请求。我们可以将隐藏节点专用于报表节点或是备份节点。 延时节点也应该是一个隐藏节点。

    1.3.4 Delayed 节点(延时节点)

      延时节点的数据集是延时的,因此它可以帮助我们在人为误操作或是其他意外情况下恢复数据。

    举个例子,当应用升级失败,或是误操作删除了表和数据库时,我们可以通过延时节点进行数据恢复

    1.4 配置MongoDB复制集

    配置分片集群请看我的另一篇文章:    https://www.jianshu.com/p/d9efee400087

    MongoDB分片(Sharding)技术

    分片(sharding)是MongoDB用来将大型集合分割到不同服务器(或者说一个集群)上所采用的方法。尽管分片起源于关系型数据库分区,但MongoDB分片完全又是另一回事。

      和MySQL分区方案相比,MongoDB的最大区别在于它几乎能自动完成所有事情,只要告诉MongoDB要分配数据,它就能自动维护数据在不同服务器之间的均衡。

    2.1 MongoDB分片介绍

    2.1.1 分片的目的

      高数据量和吞吐量的数据库应用会对单机的性能造成较大压力,大的查询量会将单机的CPU耗尽,大的数据量对单机的存储压力较大,最终会耗尽系统的内存而将压力转移到磁盘IO上。

      为了解决这些问题,有两个基本的方法: 垂直扩展和水平扩展。

    垂直扩展:增加更多的CPU和存储资源来扩展容量。

    水平扩展:将数据集分布在多个服务器上。水平扩展即分片。

    2.1.2 分片设计思想

      分片为应对高吞吐量与大数据量提供了方法。使用分片减少了每个分片需要处理的请求数,因此,通过水平扩展,集群可以提高自己的存储容量和吞吐量。举例来说,当插入一条数据时,应用只需要访问存储这条数据的分片.

      使用分片减少了每个分片存储的数据。

    例如,如果数据库1tb的数据集,并有4个分片,然后每个分片可能仅持有256 GB的数据。如果有40个分片,那么每个切分可能只有25GB的数据。

    2.1.3 分片机制提供了如下三种优势

    1.对集群进行抽象,让集群“不可见”

      MongoDB自带了一个叫做mongos的专有路由进程。mongos就是掌握统一路口的路由器,其会将客户端发来的请求准确无误的路由到集群中的一个或者一组服务器上,同时会把接收到的响应拼装起来发回到客户端。

    2.保证集群总是可读写

      MongoDB通过多种途径来确保集群的可用性和可靠性。将MongoDB的分片和复制功能结合使用,在确保数据分片到多台服务器的同时,也确保了每分数据都有相应的备份,这样就可以确保有服务器换掉时,其他的从库可以立即接替坏掉的部分继续工作。

    3.使集群易于扩展

      当系统需要更多的空间和资源的时候,MongoDB使我们可以按需方便的扩充系统容量。

    2.1.4 分片集群架构

    分片集群的构造

        (1)mongos :数据路由,和客户端打交道的模块。mongos本身没有任何数据,他也不知道该怎么处理这数据,去找config server

    (2)config server:所有存、取数据的方式,所有shard节点的信息,分片功能的一些配置信息。可以理解为真实数据的元数据。

    (3)shard:真正的数据存储位置,以chunk为单位存数据。

    Mongos本身并不持久化数据,Sharded cluster所有的元数据都会存储到Config Server,而用户的数据会议分散存储到各个shard。Mongos启动后,会从配置服务器加载元数据,开始提供服务,将用户的请求正确路由到对应的碎片。

    Mongos的路由功能

      当数据写入时,MongoDB Cluster根据分片键设计写入数据。

      当外部语句发起数据查询时,MongoDB根据数据分布自动路由至指定节点返回数据。

    2.2 集群中数据分布

    2.2.1 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是最好的。ongoDB会自动拆分和迁移chunks。

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

    (1)使用chunk来存储数据

    (2)进群搭建完成之后,默认开启一个chunk,大小是64M,

    (3)存储需求超过64M,chunk会进行分裂,如果单位时间存储需求很大,设置更大的chunk

    (4)chunk会被自动均衡迁移。

    2.2.2 chunksize的选择

      适合业务的chunksize是最好的。

      chunk的分裂和迁移非常消耗IO资源;chunk分裂的时机:在插入和更新,读数据不会分裂。

    chunksize的选择:

      小的chunksize:数据均衡是迁移速度快,数据分布更均匀。数据分裂频繁,路由节点消耗更多资源。大的chunksize:数据分裂少。数据块移动集中消耗IO资源。通常100-200M

    2.2.3 chunk分裂及迁移

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

    chunkSize 对分裂及迁移的影响

      MongoDB 默认的 chunkSize 为64MB,如无特殊需求,建议保持默认值;chunkSize 会直接影响到 chunk 分裂、迁移的行为。

      chunkSize 越小,chunk 分裂及迁移越多,数据分布越均衡;反之,chunkSize 越大,chunk 分裂及迁移会更少,但可能导致数据分布不均。

      chunkSize 太小,容易出现 jumbo chunk(即shardKey 的某个取值出现频率很高,这些文档只能放到一个 chunk 里,无法再分裂)而无法迁移;chunkSize 越大,则可能出现 chunk 内文档数太多(chunk 内文档数不能超过 250000 )而无法迁移。

      chunk 自动分裂只会在数据写入时触发,所以如果将 chunkSize 改小,系统需要一定的时间来将 chunk 分裂到指定的大小。

      chunk 只会分裂,不会合并,所以即使将 chunkSize 改大,现有的 chunk 数量不会减少,但 chunk 大小会随着写入不断增长,直到达到目标大小。

    2.3 数据区分

    2.3.1 分片键shard key

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

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

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

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

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

    注意:

            分片键是不可变。

            分片键必须有索引。

            分片键大小限制512bytes。

            分片键用于路由查询。

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

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

    2.3.2 以范围为基础的分片Sharded Cluster

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

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

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

    2.3.3 基于哈希的分片

    分片过程中利用哈希索引作为分片的单个键,且哈希分片的片键只能使用一个字段,而基于哈希片键最大的好处就是保证数据在各个节点分布基本均匀。

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

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

    2.3.4 分片键选择建议

    1、递增的sharding key

    数据文件挪动小。(优势)

    因为数据文件递增,所以会把insert的写IO永久放在最后一片上,造成最后一片的写热点。同时,随着最后一片的数据量增大,将不断的发生迁移至之前的片上。

    2、随机的sharding key

    数据分布均匀,insert的写IO均匀分布在多个片上。(优势)

    大量的随机IO,磁盘不堪重荷。

    3、混合型key

    大方向随机递增,小范围随机分布。

    为了防止出现大量的chunk均衡迁移,可能造成的IO压力。我们需要设置合理分片使用策略(片键的选择、分片算法(range、hash))

    分片注意:

      分片键是不可变、分片键必须有索引、分片键大小限制512bytes、分片键用于路由查询。

      MongoDB不接受已进行collection级分片的collection上插入无分片键的文档(也不支持空值插入)

    参考文献    https://www.cnblogs.com/clsn/p/8214345.html

    我这里有一个问题还想请MongoDB大牛解答:

        如何提高MongoDB分片集群数据的插入速度:

        现在的插入速度为 :(10次的平均值)2分40秒插入数据67634条 每条数据3-4kb左右

            单机模式的插入速度是集群模式的两倍

            插入方式均为    insertOne

            暂不考虑            insertMany    因为可能导致数据丢失

            具体的请您联系我微信QQ同时在线:772590001

                !!!!谢谢

    相关文章

      网友评论

        本文标题:MongoDB 分片集群技术

        本文链接:https://www.haomeiwen.com/subject/mtqlbftx.html