我在docker-compose中尝试验证MongoDB的自动恢复(故障切换)功能

首先

过去,对于紧急性不高的项目,我们一直使用Standalone(单机结构)的MongoDB。不过,这一次我们尝试使用MongoDB来验证在发生故障时的自动故障转移(从Primary自动切换到Secondary)机制。

故障转移是什么意思?

故障转移是指在主用计算机服务器/系统/网络发生异常情况时,自动切换到冗余的备用计算机服务器/系统/网络的功能。相对于此,手动切换的操作被称为切换。引自维基百科。

replica-set-trigger-election.bakedsvg.png

环境构建的前提条件。

已安装好了Docker Compose,在实验中使用的是版本为v2.2.1的Docker Compose进行验证。

故障转移验证过程

使用docker-compose下载源代码

请从Github(mongo-replicaset-docker-compose)上克隆源代码。
克隆完成后,请执行$ docker-compose up -d以进行环境配置。

确认副本设置

    Primaryのコンテナに接続します。
$ docker exec -it mongodb-primary bash

使用mongo命令连接到Primary成员。

$ mongo -u root -p toor

使用rs.status命令来查看副本集的状态。

replset:PRIMARY> rs.status();
{
        ...
    "members" : [
        {
            "_id" : 0,
            "name" : "mongodb-primary:27017",
            "health" : 1, -- 1/稼働, 2/停止
            "stateStr" : "PRIMARY",
                        ...
        },
        {
            "_id" : 1,
            "name" : "mongodb-secondary1:27018",
            "health" : 1,
            "stateStr" : "SECONDARY", -- データの読み書き可能なメンバー
                        ...
        },
        {
            "_id" : 2,
            "name" : "mongodb-secondary2:27019",
            "health" : 1,
            "stateStr" : "SECONDARY", -- データの読み書き可能なメンバー
                        ...
        },
        {
            "_id" : 3,
            "name" : "mongodb-arbiter:27020",
            "health" : 1,
            "stateStr" : "ARBITER", -- SECONDAYが偶数の場合に投票数を奇数にするための仕組み、データストアは持ちませんです。データは持ちません。

                        ...
        }
    ],
        ...
}

验证从主要到次要的复制。

我将电影数据写入主要位置。

replset:PRIMARY> use movie;
replset:PRIMARY> db.movie.find();
replset:PRIMARY> db.movie.find({});
replset:PRIMARY> db.movie.insert({title: "千と千尋の神隠し"});
WriteResult({ "nInserted" : 1 })
replset:PRIMARY> db.movie.insert({title: "となりのトトロ"});
WriteResult({ "nInserted" : 1 })
replset:PRIMARY> db.movie.insert({title: "ハウルの動く城"});
WriteResult({ "nInserted" : 1 })
replset:PRIMARY> db.movie.insert({title: "もののけ姫"});
WriteResult({ "nInserted" : 1 })
replset:PRIMARY> db.movie.find();
{ "_id" : ObjectId("61cb1bee1484b6d46186ac15"), "title" : "千と千尋の神隠し" }
{ "_id" : ObjectId("61cb1c061484b6d46186ac16"), "title" : "となりのトトロ" }
{ "_id" : ObjectId("61cb1c141484b6d46186ac17"), "title" : "ハウルの動く城" }
{ "_id" : ObjectId("61cb1c201484b6d46186ac18"), "title" : "もののけ姫" }
replset:PRIMARY> exit
bye
root@mongodb-primary:/# exit
exit

确认有在Secondary上复制的数据

$ docker exec -it mongodb-secondary1 bash                                                
root@mongodb-secondary1:/# mongo -u root -p toor --port 27018
replset:SECONDARY> db.getMongo().setSecondaryOk(); <<-- ここ忘れずに実行しないとクエリが実行できません。
replset:SECONDARY> use movie;
switched to db movie
replset:SECONDARY> db.movie.find();
{ "_id" : ObjectId("61cb1bee1484b6d46186ac15"), "title" : "千と千尋の神隠し" }
{ "_id" : ObjectId("61cb1c061484b6d46186ac16"), "title" : "となりのトトロ" }
{ "_id" : ObjectId("61cb1c141484b6d46186ac17"), "title" : "ハウルの動く城" }
{ "_id" : ObjectId("61cb1c201484b6d46186ac18"), "title" : "もののけ姫" }
replset:SECONDARY> exit
bye
root@mongodb-secondary1:/# exit
exit

我们确认了Primary和Secondary的数据是相同的!

暫時停用主要容器進行故障切換確認。

$ docker stop mongodb-primary     <<-- プライマリのコンテナの一時停止                                                         
mongodb-primary

$ docker ps -a
CONTAINER ID   IMAGE                                                COMMAND                  CREATED          STATUS                        PORTS                                 NAMES
bb5f739bbcb5   mongo-express:latest                                 "tini -- /docker-ent…"   43 minutes ago   Up 40 minutes                 0.0.0.0:8081->8081/tcp                mongo-express
e7f47e42ec32   mongo-replicaset-docker-compose_mongo-connector      "docker-entrypoint.s…"   43 minutes ago   Exited (0) 43 minutes ago                                           mongo-connector
1c69595e200e   mongo-replicaset-docker-compose_mongodb-arbiter      "docker-entrypoint.s…"   44 minutes ago   Up 44 minutes (healthy)       27017/tcp, 0.0.0.0:27020->27020/tcp   mongodb-arbiter
fa6683c69b79   mongo-replicaset-docker-compose_mongodb-secondary2   "docker-entrypoint.s…"   44 minutes ago   Up 44 minutes (healthy)       27017/tcp, 0.0.0.0:27019->27019/tcp   mongodb-secondary2
09fad2c160e7   mongo-replicaset-docker-compose_mongodb-secondary1   "docker-entrypoint.s…"   44 minutes ago   Up 44 minutes (healthy)       27017/tcp, 0.0.0.0:27018->27018/tcp   mongodb-secondary1
a63d3f8bf48d   mongo-replicaset-docker-compose_mongodb-primary      "docker-entrypoint.s…"   44 minutes ago   Exited (137) 24 seconds ago   <<-- プライマリのコンテナが停止されたこと確認

我要确认mongo-replicaset-docker-compose_mongodb-primary的状态是否为Exited。

在Secondary上查看复制集合的情况。

$ docker exec -it mongodb-secondary1 bash                                               
root@mongodb-secondary1:/# mongo -u root -p toor --port 27018
replset:PRIMARY> rs.status();
{
        ...
    "members" : [
        {
            "_id" : 0,
            "name" : "mongodb-primary:27017",
            "health" : 0,   <<--- 停止状態になってる
            "stateStr" : "(not reachable/healthy)",
                        ...
        },
        {
            "_id" : 1,
            "name" : "mongodb-secondary1:27018",
            "health" : 1,
            "stateStr" : "PRIMARY",  <<--- secondaryから投票によりPrimaryに昇格されました!!
                        ...
        },
        {
            "_id" : 2,
            "name" : "mongodb-secondary2:27019",
            "health" : 1,
            "stateStr" : "SECONDARY",
                        ...
        },
        {
            "_id" : 3,
            "name" : "mongodb-arbiter:27020",
            "health" : 1,
            "stateStr" : "ARBITER",
                        ...

        }
    ],
        ...
}
replset:PRIMARY> exit
bye
root@mongodb-secondary1:/# exit
exit

在处理主服务器的故障恢复方面,将主服务器恢复为原始状态。

$ docker start mongodb-primary                                                           
mongodb-primary

$ docker exec -it mongodb-secondary1 bash                                                
root@mongodb-secondary1:/# mongo -u root -p toor --port 27018
replset:SECONDARY> rs.stepDown()   <<---- 自分自身を降格させる(Secondaryになる)
replset:SECONDARY> rs.status();
{
        ...
    "members" : [
        {
            "_id" : 0,
            "name" : "mongodb-primary:27017",
            "health" : 1,
            "stateStr" : "PRIMARY",
                        ...
        },
        {
            "_id" : 1,
            "name" : "mongodb-secondary1:27018",
            "health" : 1,
            "stateStr" : "SECONDARY",
                        ...
        },
        {
            "_id" : 2,
            "name" : "mongodb-secondary2:27019",
            "health" : 1,
            "stateStr" : "SECONDARY",
                        ...
        },
        {
            "_id" : 3,
            "name" : "mongodb-arbiter:27020",
            "health" : 1,
            "stateStr" : "ARBITER",
                        ...
        }
    ],
        ...
}

最终

使用docker-compose构建副本集,并确认主服务器的数据被复制到副本服务器上,当主服务器出现故障时,通过投票选举将副本服务器升级为主服务器,实现自动故障转移而不停止服务。

不建议在生产环境中继续使用此方法。建议将其配置为微服务,并将它们分别作为不同的服务器。

广告
将在 10 秒后关闭
bannerAds