在圣诞之夜,使用docker-compose与MongodbDB玩耍
经过
我通常在Rails中使用MongoDB,但对于分片(sharding)完全不了解,因此我使用docker-compose进行验证。我想调查一下是否可以解决当前运营中的问题。(由于可能存在错误,请帮我提出修改请求或指正,谢谢。)
现状的组成和问题
构成
在使用MongoDB进行分片(sharding)时,发现运维工作非常艰难。因此,目前我们没有采用sharding的方式,而是仅使用了复制集(replica set)进行部署。我们使用了著名的Rails ODM(对象文档映射)工具Mongoid,并按照以下方式配置连接信息。
production:
clients:
default:
database: mongodb_database
hosts:
- primary:27017
- secondary1:27017
- secondary2:27017
问题
(Note: “问题” can be used as a translation for “issue” or “problem”, depending on the context.)
当进行扩展或遇到AWS基础设施维护时,我们会进行副本集成员的更换。但是,在执行更换操作时,我们需要更新连接信息并进行应用程序的部署,这非常麻烦且容易出错。
解决方案
通过只使用一个sharding系统,并将mongod的连接转为通过mongos进行连接,可以使应用程序无需保存数据库连接等信息。
production:
clients:
default:
database: mongodb_database
hosts:
- localhost:27017
在考虑中,可以使用像monit这样的监控工具来监视并重新启动mongos。
验证环境
mac
docker-for-mac
Rails应用程序在主机上运行,中间件在docker上运行。
目录结构
mongodb
└── docker-compose.yml
除了MongoDB之外的中间件都在Rails应用的docker-compose文件中声明。
为了进行验证,我们将Rails应用docker-compose文件中MongoDB的声明注释掉,
并创建了一个新目录,使得MongoDB可以单独进行验证。
version: '2'
services:
s1:
image: mongo:3.2
ports:
- "27017:27017"
command: mongos --configdb confRep1/c1:27019,c2:27019,c3:27019
links:
- d1
- d2
- d3
- d4
- d5
- d6
- c1
- c2
- c3
s2:
image: mongo:3.2
ports:
- "27018:27017"
command: mongos --configdb confRep1/c1:27019,c2:27019,c3:27019
links:
- d1
- d2
- d3
- d4
- d5
- d6
- c1
- c2
- c3
c1:
image: mongo:3.2
command: mongod --configsvr --replSet confRep1
links:
- d1
- d2
- d3
- d4
- d5
- d6
- c2
- c3
c2:
image: mongo:3.2
command: mongod --configsvr --replSet confRep1
links:
- d1
- d2
- d3
- d4
- d5
- d6
- c3
c3:
image: mongo:3.2
command: mongod --configsvr --replSet confRep1
links:
- d1
- d2
- d3
- d4
- d5
- d6
d1:
image: mongo:3.2
command: mongod --replSet rep1
links:
- d2
- d3
- d4
- d5
- d6
d2:
image: mongo:3.2
command: mongod --replSet rep1
links:
- d3
- d4
- d5
- d6
d3:
image: mongo:3.2
command: mongod --replSet rep1
links:
- d4
- d5
- d6
d4:
image: mongo:3.2
command: mongod --replSet rep1
links:
- d5
- d6
d5:
image: mongo:3.2
command: mongod --replSet rep1
links:
- d6
d6:
image: mongo:3.2
command: mongod --replSet rep1
对以下内容进行验证
使用 d1、d2、d3 组成一个副本集,并将应用程序的示例数据注入其中。
将 d4、d5、d6 加入副本集,并升级 d4 为主节点。
将 d1、d2、d3 从副本集中移除,并确保应用程序的连接信息未更改和正常运行。
验证步骤
由于配置服务器的副本集未设置成功,mongos服务器出现异常并输出日志。
设置配置服务器的副本集
docker exec -it mongodb_c1_1 mongo --port 27019
# mongo shell
rs.initiate()
rs.add("c2:27019")
rs.add("c3:27019")
# configサーバーはデフォルトでport:27019を使うらしい
设置MongoDB副本集
docker exec -it mongodb_d1_1 mongo
# mongo shell
rs.initiate()
rs.add("d2")
rs.add("c3")
访问mongos并注册shard。
docker exec -it mongodb_s1_1 mongo
# mongo shell
sh.addShard("rep1/d2")
# レプリカセットに所属しいるサーバーを1台指定すればいい感じにやってくれる
在Rails应用程序中输入示例数据,并提供连接信息。
development:
clients:
default:
database: development
hosts:
- localhost:27017
在完成数据导入之后,尝试连接到mongos2
development:
clients:
default:
database: development
hosts:
- localhost:27018 #←portを変えた
bin/spring stop
bin/rails c
我已经成功连接了。
即使之前在不同的mongos上工作,由于信息在mongoc上共享,所以可以以相同的方式运行。
当检查shard状态时,还可以查看活动的mongos数量。
mongos> sh.status()
--- Sharding Status ---
sharding version: {
"_id" : 1,
"minCompatibleVersion" : 5,
"currentVersion" : 6,
"clusterId" : ObjectId("585d48811b8e027da3d3da28")
}
shards:
{ "_id" : "rep1", "host" : "rep1/8d106239ab63:27017,d2:27017,d3:27017" }
active mongoses:
"3.2.11" : 2
balancer:
Currently enabled: yes
Currently running: no
Failed balancer rounds in last 5 attempts: 0
Migration Results for the last 24 hours:
No recent migrations
databases:
{ "_id" : "development", "primary" : "rep1", "partitioned" : false }
从这里开始,我们将验证在替换复制品集的内容后,是否可以在保持rails console会话的同时进行操作。
docker exec -it mongodb_d1_1 mongo
# mongo shell
# 本番環境ではレプリカセットに追加する時に参照されないようなオプションをつける必要があります。
# データが追いついてないのにアプリケーションから整合性がないデータが参照されてしまうからです。
# データが追いついたことを確認して、参照できるように情報を書き換えます。今回は検証なのでめんどくさいのでやっていません。
rs.add("d4")
rs.add("d5")
rs.add("d6")
更换主服务器
# mongo shell
conf = rs.conf()
conf.members[3].priority = 2
rs.reconfig(conf)
将mongod d1、d2和d3从复制集中移除。
这将完全替换容器中的数据。
docker exec -it mongodb_d4_1 mongo
# mongo shell
rs.remove("8d106239ab63:27017")
rs.remove("d2:27017")
rs.remove("d3:27017")
读取和写入都成功了。
我想要验证一下,在运行环境中只有一个shard的情况下,是否需要备份config服务器。
当杀掉mongos和config服务器并重新搭建时,是否能够正确地进行引用。
如果只备份mongod服务器的数据,那将是非常理想的情况。
# {}の部分は他のshellでできたか自信ないです。
docker kill mongodb_s{1,2}_1
docker rm mongodb_s{1,2}_1
docker kill mongodb_c{1,2,3}_1
docker rm mongodb_c{1,2,3}_1
重新启动mongos和config服务器
使用docker-compose up -d命令
重新构建config服务器
docker exec -it mongodb_c1_1 mongo --port 27019
# mongo shell
rs.initiate()
rs.add("c2:27019")
rs.add("c3:27019")
docker exec -it mongodb_s1_1 mongo
# mongo shell
sh.addShard("rep1/d4")
总结
1. 如果将MongoDB的分片设置为1,似乎可以在应用程序端不改变连接信息(无需部署)的情况下进行MongoDB的维护。
2. 如果保持在shard1上,即使配置服务器损坏了也可以重新建立,可以应付一些情况(无需mongoc备份)。
(关于第二点我不太确定,如果您要尝试,请自行承担责任。)
用docker-compose在本地,可以方便地进行副本集等验证,感觉非常方便。
对于elastic search、redis、memcached等集群验证也可能很不错。
我认为它非常适合进行mongodb升级验证(由于3.2=>3.4的升级步骤比较多,所以在本文中未涉及。如果只涉及副本集,应该会简单一些)。
特别是以前台方式运行时,可以观察每个docker的输出,非常直观易懂。
后来完全没有关系,我换了台新的Mac,并且更新了GIF动画截图软件。
这个叫做GIPHY Capture的应用非常好。
它可以免费使用,可以剪切开头和结尾,还可以改变帧率和分辨率,非常适合贴在步骤手册、Qiita之类的地方使用。