您的位置:首页 > 数据库 > Mongodb

MongoDB实战-生产环境中分片的部署与配置

2017-09-12 15:30 274 查看
在生产环境里部署分片集群时,面前会出现很多选择和挑战。下面会介绍几个推荐的拓扑结构。

1.部署拓扑

要运行示例MongoDB分片集群,你一共要启动九个进程(每个副本集三个mongod,外加三个配置服务器)。咋一看,这个数字有点吓人。一开始用户会假设在生产环境里运行两个分片集群要有九台独立的机器。幸运的是,实际需要的机器要少很多,看一下集群中各组件所要求的资源就知道为什么了。

首先考虑下副本集,每个成员都包含分片的完整数据副本,可能是主节点,也可能是从节点。这些进程总是要求有足够的磁盘空间来保存数据,要有足够的内存高效得提供服务。因此,复制mongod是分片集群中最资源密集型的进程,必须占有独立的机器。

那副本集的仲裁节点呢?这些进程值保存副本集的配置数据,这些数据就放在一个文档里。所以,仲裁节点的开销最小,当然也就不需要自己的服务器了。

接下来是配置服务器,它们同样只保存相对较少的数据。举例来说,配置服务器上管理示例副本集的数据一共也就大约30KB。如果假设这些数据会随着分片集群的增长而线性增长。那么1TB的分片集群可能对对应30MB的数据。也就是说配置服务器同样不需要有自己的机器。但是,考虑到配置服务器所扮演的重要角色,一些用户更倾向于为他们提供一些机器(或虚拟机)。

根据你对副本集合分片集群的了解,可以列出部署分片集群的最低要求:

(1)副本集的每个成员,无论是完整的副本节点还是仲裁节点,都需要放在不同的机器上;

(2)每个用于复制的副本集成员都需要有自己的机器

(3)副本集的仲裁节点时很轻量级的,和其他进程共用一台机器就可以了;

(4)配置服务器也可以选择与其他进程共用一台机器,唯一的要求是配置急群众的所有配置服务器都必须放在不同的机器上。

下面我们将运用这些规则,针对示例的量分片集群,你会看到两个合理的部署拓扑。第一个拓扑只需要四台机器,下图描述了进程的分布情况



这个配置满足了刚才所说的所有规则。在每台机器上占主导地位的是各分片的复制节点。剩下的进程经过了精心的安排,所有的三个配置服务器和每个副本集的仲裁节点都部署在不同的机器上。说起容错性,该拓扑能容忍任何一台机器发生故障。无论哪台机器发生了故障,集群都能继续处理读写请求。如果发生故障的机器正好运行了一个配置服务器,那么所有的块拆分和迁移都会暂停。幸运的是,暂停分片操作基本不会影响分片集群的工作;在损失的机器恢复后,就能进行拆分和迁移了。

这是两份片集群的最小推荐配置。但是,那些要求最高可用性和最快恢复途径的应用程序需要一些更强健的东西。正如前面所述,包含两个副本集合一个仲裁节点的副本集在恢复的是很脆弱的。如果有三个节点,就能降低恢复时的脆弱程度,还能让你在从数据中心里部署一个节点,用于灾难恢复。下图是一个强壮的两分片集群拓扑。每个分片都包含三节点的副本集,每个节点都包含完整的数据副本。为了进行灾难恢复,从每个分片中抽一个节点,加上一个配置服务器,部署在从数据中心:要保证那些节点不会成为主节点,可以将它们的优先级设置为0



用了这个配置,每个分片会被复制两次,非仅一次。此外,当主数据中心发生故障时,从数据中心拥有重建分片集群所需的全部数据。哪种分片拓扑最适合你的应用程序,这种决策总是基于一系列与你能容忍的停机时间有关的考虑。比如根据MTR(Mean Time To Recovery,平均恢复时间)进行评估。考虑潜在的故障场景,并模拟它们。如果一个数据中心发生故障,考虑一下它对应用程序的影响。

2. 配置注意事项

下面是一些与配置分片集群相关的注意事项:

(1)估计集群大小

用户经常想知道要部署多少个分片,每个分片应该有多大。当然这个问题的答案取决于所在的环境。如果是部署在亚马逊的EC2上,在超过最大的刻印实例前都不应该进行分片。如果运行在自己的硬件上,你还可以拥有更大的机器,在数据达到100GB之前都不进行分片,这是很合理的。

当然,每增加一个分片都会引入额外的复杂性,每个分片都要求进行复制。所以说,少数大分片比大量小分片更好。

(2)对现有集合进行分片

你可以对现有集合进行分片,如果花了很多时间才将数据分布到各分片里,请不要大惊小怪的。每次只能做一轮均衡,迁移过程中每分钟只能移动大约100-200MB数据。因此,对一个50GB的集合进行分片大约需要八个小时,其中还可能牵涉到一定的磁盘活动。此外,在对这样大集合进行初始分片时,可能还要手动拆分以加速分片过程,因为拆分时由插入触发的。

说到这里,应该已经很清楚了,在最后时候对一个集合进行分片并不是处理性能问题的好办法。如果你计划在未来某个时刻对集合进行分片,考虑到可以预见的性能下降,应该提前分片。

(3)在初始加载时预拆分块

如果你有一个很大的数据集需要加载到分片集合里,并且知道数据分布的规律,那么可以通过对块的预拆分和预迁移节省很多时间。举个例子,假设你想要把电子表格导入到一个新的MongoDB分片集群里。可以在导入时先拆分块,随后将它们迁移到分片里,借此保证数据是均匀分布的。你能用split和moveChunk命令实现这个目标,它们的辅助方法分别是sh.splitAt()和sh.moveChunks().

下面是一个手动拆分的例子,你发出的split命令,指定你想要的集合,随后指明拆分点:
sh.splitAt("cloud-docs.spreadsheets",{"username":"Chen","_id":ObjectId("4d6b59db1d1c8536f001453")})
命令运行时会定位到某个块,而这个块逻辑上包含username是Chen并且_id是对应ObjectId的文档。该命令随后会根据这个点来拆分块,最后得到两个块。你能像这样继续拆分,知道拥有数据良好分布的块集合。你还要确保创建足够数量的块,让平均块大小保持在64MB的拆分阈值以内。所以,如果要加载1GB的数据,应该计划创建大约20个块。

第二步是确定所有分片都拥有数量相当的块。因为所有的块最初都在一个分片上,你需要移动它们。可以使用moveChunk命令来移动块,比如下面的语句的含义是将包含文档{username:"Chen"}的块迁移到分片B上。

sh.moveChunk("cloud-docs.spreadsheets",{username:"Chen"},"shardB")
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息