Настройка master->slave репликации MongoDB на Debian 7 (Wheezy)

Для реализации приложения, которое очень активно пишет в базу, потребовалось развернуть кластер из баз MongoDB, ранее я в принципе не имел опыта работы с этой СУБД, поэтому сделал маленькую заметку. Маны которые попадались мне в сети не содержали всех мелочей с которыми мне пришлось провозиться, например:
  • В кластере mongo должно быть минимум 3 базы mongo (например 3 физических или виртуальных компьютера)
  • В случае возникновения ошибок работы со слейвами их нужно добавить в список разрешённых командой rs.slaveOk()
Данное решение разворачивалось на 3х серверах под управлением Debian 7 (Wheezy).

Нужно выполнить на всех серверах

Первым делом нужно установить самую свежую сборку базы, для этого добавим репозиторий:
mcedit /etc/apt/sources.list.d/mongodb.list
В нём такую строку запишем:
deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen
Обновим пакеты:
apt-get update
Далее выполним установку
apt-get install mongodb-10gen
Будет ошибка запуска базы, связано это с тем, что убунтовский скрипт /etc/init.d/mongodb ссылается на скрипт upstart, который есть в убунте, но отсутствует в дебиан. Вот заготовка, которую я использую:
https://drive.google.com/file/d/0BwtFihi86jHaQ0N6OVVySXBENkU/edit?usp=sharing
Нужно удалить ссылку на upstart из /etc/init.d:
rm -v /etc/init.d/mongodb
Затем скопировать тот файл, что Вы скачали из гугл-диска, в инициализацонные скрипты:
cp -v mongodb /etc/init.d/
И исправить права запуска:
chmod 755 /etc/init.d/mongodb
Повторим установку (должно пройти без ошибок):
apt-get install mongodb-10gen
Откроем в любом редакторе конфигурацию mongodb:
mcedit /etc/mongodb.conf
Тут добавим строку вида (она задаёт общее для всех хостов имя реплики):
replSet = rs0
Перезапустим на всех серверах:
/etc/init.d/mongodb restart
После этого можно приступать к настройкам мастера.

Нужно выполнить только на PRIMARY сервере

Подключимся к управляющей консоли (что-то вроде sqlplus или bash):
mongo
Проинициализируем реплику на мастере:
rs0:PRIMARY> rs.initiate()
Смотрим конфигурацию:
rs0:PRIMARY> rs.conf()
{
        "_id" : "rs0",
        "version" : 3,
        "members" : [
                {
                        "_id" : 0,
                        "host" : "db-00:27017"
                }
        ]
Проверим статус:
rs0:PRIMARY> rs.status()
{
        "set" : "rs0",
        "date" : ISODate("2014-01-28T10:34:20Z"),
        "myState" : 1,
        "members" : [
                {
                        "_id" : 0,
                        "name" : "db-00:27017",
                        "health" : 1,
                        "state" : 1,
                        "stateStr" : "PRIMARY",
                        "uptime" : 48,
                        "optime" : Timestamp(1390905202, 90),
                        "optimeDate" : ISODate("2014-01-28T10:33:22Z"),
                        "self" : true
                }
        ],
        "ok" : 1
}
Добавим слейвы:
rs0:PRIMARY> rs.add("db-01")
{ "ok" : 1 }
rs0:PRIMARY> rs.add("db-02")
{ "ok" : 1 }
Смотрим конфигурацию:
rs0:PRIMARY> rs.conf()
{
        "_id" : "rs0",
        "version" : 3,
        "members" : [
                {
                        "_id" : 0,
                        "host" : "db-00:27017"
                },
                {
                        "_id" : 1,
                        "host" : "db-01:27017"
                },
                {
                        "_id" : 2,
                        "host" : "db-02:27017"
                }
        ]
Сразу после добавления будет отображаться что начат процесс синхронизации:
rs0:PRIMARY> rs.status()
{
        "set" : "rs0",
        "date" : ISODate("2014-01-28T10:34:56Z"),
        "myState" : 1,
        "members" : [
                {
                        "_id" : 0,
                        "name" : "db-00:27017",
                        "health" : 1,
                        "state" : 1,
                        "stateStr" : "PRIMARY",
                        "uptime" : 84,
                        "optime" : Timestamp(1390905275, 1),
                        "optimeDate" : ISODate("2014-01-28T10:34:35Z"),
                        "self" : true
                },
                {
                        "_id" : 1,
                        "name" : "db-01:27017",
                        "health" : 1,
                        "state" : 5,
                        "stateStr" : "STARTUP2",
                        "uptime" : 23,
                        "optime" : Timestamp(0, 0),
                        "optimeDate" : ISODate("1970-01-01T00:00:00Z"),
                        "lastHeartbeat" : ISODate("2014-01-28T10:34:55Z"),
                        "lastHeartbeatRecv" : ISODate("2014-01-28T10:34:55Z"),
                        "pingMs" : 2,
                        "lastHeartbeatMessage" : "initial sync cloning db: testdb"
                },
                {
                        "_id" : 2,
                        "name" : "db-02:27017",
                        "health" : 1,
                        "state" : 5,
                        "stateStr" : "STARTUP2",
                        "uptime" : 21,
                        "optime" : Timestamp(0, 0),
                        "optimeDate" : ISODate("1970-01-01T00:00:00Z"),
                        "lastHeartbeat" : ISODate("2014-01-28T10:34:55Z"),
                        "lastHeartbeatRecv" : ISODate("2014-01-28T10:34:55Z"),
                        "pingMs" : 1,
                        "lastHeartbeatMessage" : "initial sync cloning db: testdb"
                }
        ],
        "ok" : 1
}
Через некоторое время команда покажет:
rs0:PRIMARY> rs.status()
{
        "set" : "rs0",
        "date" : ISODate("2014-01-28T10:35:04Z"),
        "myState" : 1,
        "members" : [
                {
                        "_id" : 0,
                        "name" : "db-00:27017",
                        "health" : 1,
                        "state" : 1,
                        "stateStr" : "PRIMARY",
                        "uptime" : 92,
                        "optime" : Timestamp(1390905275, 1),
                        "optimeDate" : ISODate("2014-01-28T10:34:35Z"),
                        "self" : true
                },
                {
                        "_id" : 1,
                        "name" : "db-01:27017",
                        "health" : 1,
                        "state" : 2,
                        "stateStr" : "SECONDARY",
                        "uptime" : 31,
                        "optime" : Timestamp(1390905275, 1),
                        "optimeDate" : ISODate("2014-01-28T10:34:35Z"),
                        "lastHeartbeat" : ISODate("2014-01-28T10:35:03Z"),
                        "lastHeartbeatRecv" : ISODate("2014-01-28T10:35:03Z"),
                        "pingMs" : 2,
                        "syncingTo" : "db-00:27017"
                },
                {
                        "_id" : 2,
                        "name" : "db-02:27017",
                        "health" : 1,
                        "state" : 2,
                        "stateStr" : "SECONDARY",
                        "uptime" : 29,
                        "optime" : Timestamp(1390905275, 1),
                        "optimeDate" : ISODate("2014-01-28T10:34:35Z"),
                        "lastHeartbeat" : ISODate("2014-01-28T10:35:03Z"),
                        "lastHeartbeatRecv" : ISODate("2014-01-28T10:35:03Z"),
                        "pingMs" : 2,
                        "syncingTo" : "db-00:27017"
                }
        ],
        "ok" : 1
}
Ну вроде всё, сервера синхронизировались.

В случае если SECONDARY сервера не хотят синхрониться

Выполним команду:
rs0:PRIMARY> rs.slaveOk()

Комментариев нет:

Отправить комментарий