我一直在研究在AWS中创建自己的mongodb集群.Aws mongodb template提供了一些很好的起点.但是,它不包括自动zoom 或 node 关闭时.例如,如果我有1个主 node 和2个辅助 node .主电路下降,自动zoom 开始.如何将新启动的mongodb实例添加到副本集中?

如果查看模板,它使用init.sh脚本,以判断正在启动的 node 是否是主 node ,并等待所有其他 node 存在,然后在主 node 上创建一个具有它们的ip地址的副本集.初始配置副本集时,所有 node 都已存在.

不仅如此,我的 node 应用程序使用mongoose.数据库连接的一部分允许您指定多个 node .我如何跟踪当前正在运行的程序(我想我可以使用DynamoDB,但不确定).

如果实例失败,通常的流程是什么?如果出现这种情况,人们通常会手动重新配置集群吗?

有什么 idea 吗?谢谢

推荐答案

这是一个非常好的问题,我最近也经历了这段非常痛苦的旅程.我在这里写了一个相当广泛的答案,希望通过CloudFormation运行MongoDB集群的一些 idea 对其他人有用.

我假设您正在创建一个MongoDB生产集群,如下所示:-

  • 3台配置服务器(micros/smalls实例可以在这里使用)
  • 至少1个分片,由2个(主和辅助)分片实例(最小或较大)组成,并配置了用于数据/日志(log)/日志(log)磁盘的大型磁盘.
  • 用于投票的仲裁机(micro可能还可以).

i、 e.https://docs.mongodb.org/manual/core/sharded-cluster-architectures-production/

和你一样,我最初try 了你在链接(https://s3.amazonaws.com/quickstart-reference/mongodb/latest/templates/MongoDB-VPC.template)中发布的AWS MongoDB CloudFormation模板,但老实说,它太复杂了,即9300行长,并设置了多个服务器(即副本碎片、配置、仲裁器等).运行CloudFormation模板花了很长时间,而且一直失败(例如,15分钟后),这意味着服务器再次终止,我不得不再次try ,这真的很令人沮丧/耗时.

我最终 Select 的解决方案(我非常满意)是为集群中的每种类型的MongoDB服务器创建单独的模板,例如:.

  1. MongoDbConfigServer.template (template to create config servers - run this 3 times)
  2. MongoDbShardedReplicaServer.template (template to create replica - run 2 times for each shard)
  3. MongoDbArbiterServer.template (template to create arbiter - run once for each shard)

NOTE: templates available at 100

然后,我们的 idea 是分别启动集群中的每个服务器,即3个配置服务器、2个分片副本服务器(用于1个分片)和一个仲裁器.然后,您可以将自定义参数添加到每个模板中,例如,副本服务器的参数可能包括:-

  • InstanceTypet2.micro
  • ReplicaSetNames1r (shard 1 replica)
  • ReplicaSetNumber例如2 (used with 102 to create name e.g. name becomes 103)
  • VpcIdvpc-e4ad2b25 (not a real VPC obviously!)
  • SubnetIdsubnet-2d39a157 (not a real subnet obviously!)
  • GroupId (name of existing MongoDB group Id)
  • Route53 (boolean to add a record to an internal DNS - best practices)
  • Route53HostedZone (if boolean is true then ID of internal DNS using Route53)

CloudFormation最酷的一点是,这些自定义参数可以(a)对运行它的人有一个有用的描述,(b)特殊类型(例如,运行时创建一个预过滤的组合框,因此更难出错)和(c)默认值.下面是一个例子:-

    "Route53HostedZone": {
        "Description": "Route 53 hosted zone for updating internal DNS (Only applicable if the parameter [ UpdateRoute53 ] = \"true\"",
        "Type": "AWS::Route53::HostedZone::Id",
        "Default": "YA3VWJWIX3FDC"
    },

这使得运行CloudFormation模板成为一件轻而易举的事,因为在很多时候,我们可以依赖默认值,只需要根据我们正在创建(或替换)的服务器实例调整几件事情.

除了参数之外,前面提到的3个模板中的每一个都有一个创建实例的"Resources"部分.我们也可以通过"AWS::CloudFormation::Init"部分做一些很酷的事情.例如

"Resources": {

    "MongoDbConfigServer": {
        "Type": "AWS::EC2::Instance",
        "Metadata": {
            "AWS::CloudFormation::Init": {
                "configSets" : {
                    "Install" : [ "Metric-Uploading-Config", "Install-MongoDB", "Update-Route53" ]
                },

上一个示例中的"configSets"表明,创建MongoDB服务器不仅仅是创建一个AWS实例并在其上安装MongoDB,我们还可以(a)安装CloudWatch磁盘/内存度量(b)更新Route53 DNS等.其 idea 是,您希望尽可能地自动化DNS/监控等事情.

在我看来,为每台服务器创建一个模板和一个堆栈具有非常好的优势,可以通过CloudFormation web控制台极快地替换服务器.此外,因为我们有一个server-per-template,所以很容易一点一点地构建MongoDB集群.

关于创建模板,我的最后一点建议是从其他GitHub MongoDB CloudFormation模板复制适合您的模板,例如,我使用以下方法创建副本服务器,以使用RAID10(而不是更昂贵的AWS配置的IOPS磁盘).

https://github.com/CaptainCodeman/mongo-aws-vpc/blob/master/src/templates/mongo-master.template

在你的问题中,你提到了自动伸缩——我的首选是手动添加一个碎片/替换一个损坏的实例(对于Tomcat/Apache等web容器,自动伸缩是有意义的,但是MongoDB集群应该随着时间慢慢增长).但是,监视非常重要,尤其是碎片服务器上的磁盘大小,以便在磁盘填满时提醒您(因此您可以添加新的碎片以删除数据).使用AWS CloudWatch度量/alert 或使用MongoDB MMS服务可以相当轻松地实现监控.

如果一个 node 发生故障,例如碎片中的一个副本,那么您可以简单地杀死服务器,使用CloudFormation模板重新创建它,磁盘将自动同步.如果一个实例发生故障,通常不需要重新配置,这就是我的正常流程.过go 我花了太多时间试图修复服务器——有时幸运,有时不幸运.我现在的备份策略是每天通过crontabzip up运行mongodump个重要的数据库集合,并上传到AWS S3.这意味着,如果出现核选项(数据库完全损坏),我们可以在一两个小时内重新创建整个数据库和mongorestore.

However, if you create a new shard (because you're running out of space) configuration is necessary. For example, if you are adding a new Shard 3 you would create 2 replica nodes (e.g. primary with name => mongo-s3r1 / secondary with name => mongo-s3r2) and 1 arbitor (e.g. with name mongo-s3r-arb) then you'd connect via a MongoDB shell to a mongos (MongoDB router) and run this command: -

sh.addShard("s3r/mongo-s3r1.internal.mycompany.com:27017,mongo-s3r2.internal.mycompany.com:27017")

101 - This commands assumes you are using private DNS via Route53 (best practice). You can simply use the private IPs of the 2 replicas in the 100 command but I have been very badly burned with this in the past (e.g. serveral months back all the AWS instances were restarted and new private IPs generated for all of them. Fixing the MongoDB cluster took me 2 days as I had to reconfigure everything manually - whereas changing the IPs in Route53 takes a few seconds ... ;-)

你可能会说,我们还应该将addShard命令添加到另一个CloudFormation模板中,但在我看来,这增加了不必要的复杂性,因为它必须知道一个服务器有一个MongoDB路由(mongos),并连接到该服务器才能运行addShard命令.因此,我只是在创建了新MongoDB碎片中的实例之后运行它.

不管怎样,这是我对这件事的漫无边际的 idea .最重要的是,一旦你有了合适的模板,你的生活就会变得更加轻松,迪福值得付出努力!祝你好运!:-)

Mongodb相关问答推荐

使用查询参数过滤MongoDB Go驱动程序时出现问题

Mongo DB-如果一个特定字段有多个文档匹配,则更新文档字段

如何在Mongodb Mongoose Nodejs中提取不等于一组值的字段

从 Amazon S3(Next.js、Mongodb、Mongoose)删除图像

Mongodb,在一个查询中用正则表达式更新部分字符串

在 MongoDB 中加入多个集合

如何聚合过滤器嵌套文档并从其他字段中获取值

NodeJS + MongoDB:使用 findOne () 从集合中获取数据

当属性确实存在时,为什么mongoose模型的 hasOwnProperty 返回 false?

Mongoose 架构引用和未定义类型ObjectID

更新 mongoengine 中的嵌入文档列表

MongoDB 文档操作是原子的和隔离的,但它们是否一致?

为什么 PyMongo 会抛出 AutoReconnect?

如何使用 java 驱动程序更新 mongo db 中的文档字段?

将 JSON 与 MongoDB 一起使用?

Cannot connect to MongoDB errno:61

Mongo: query by key one level deep

有人在 Google App Engine 上try 过 MongoDB 吗?

Mongodb $lookup 使用 _id 无效果

将日期从毫秒转换为 ISODate 对象