
Это руководство описывает пошаговую установку и настройку реплики из 3 узлов mongoDB на базе движка WiredTiger. А также несколько полезных мелочей для людей, впервые столкнувшихся с MongoDB.
Важное уточнение:
- До начала установки необходимо понимание конечной архитектуры.
- Некоторые приятности требуют Enterprise лицензию.
Немного о движке WiredTiger
Engine WiredTiger — новый движок mongoDB, использующийся по умолчанию вместо MMAP, начиная с версии 3.4. Хорош тем, что работает с данными на уровне коллекций и отдельных документов, а не полностью базой. Также устраняет проблему Global lock по вышеуказанной причине, из-за чего и был выбран в продакшен.
Сказ о том, как WiredTiger хранит данные:
… находится по этому адресу на английском языке
Попытки внятно перевести механизм на русский язык провалились. Увы.
Попытки внятно перевести механизм на русский язык провалились. Увы.
Установка OS и компонентов
Ставим Debian любой удобной вам версии, у меня использовался 8.6.0.
Для упрощения масштабирования узлов и баз данных, рекомендую использовать lvm.
Из компонентов понадобится только ssh для более удобного доступа к серверу.
Установка MongoDB.
У меня используется бесплатная Community Edition, руководство будет на её основе.
По необходимости допишу Enterpise версию, т.к. она тоже крутилась и разбиралась.
Данное руководство описывается для варианта 3-х серверов (master, slave, arbiter).
Итак, поехали:
- Для начала нам необходимо импортировать публичный GPG ключ.
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 0C49F3730359A14518585931BC711F9BA15703C6 - Далее добавляем репозиторий MongoDB.
Открываем файл со списком репозиториев
nano /etc/apt/sources.list
Копируем репозиторий и сохраняем изменения.
deb http://repo.mongodb.org/apt/debian jessie/mongodb-org/3.4 main
Обновляем список доступных пакетов
sudo apt-get update - Устанавливаем MongoDB и зависимые пакеты.
sudo apt-get install -y mongodb-org
Повторяем процедуру для 3(трех) серверов,
На этом первоначальная настройка завершена.
Теперь переходим к настройке mongoDB.
Настройка и добавление серверов в Replica Set
Давайте для начала разберемся, что такое replica set.
Replica Set — это кластер серверов MongoDB, реализующий механизм репликации master-slave и автоматическое переключение между ними. Это рекомендуемый механизм репликации от разработчиков MongoDB. ссылка на офф. документацию.
Картинка:

Мы используем механизм репликации, приведенный на картинке:
мастер, два вторичных и арбитр.
Теперь по порядку:
Primary — основной сервер mongoDB.
Secondary — точные копии баз(ы) данных с real-time синхронизацией.
Arbiter — сервер выбора вторичной реплики с высшим приоритетом, которая станет главной в случае падения сервера.
ОЧЕНЬ ВАЖНО:
Arbiter отвечает только за выборы преемника, сам стать преемником он не может, поэтому рекомендуется отдавать под арбитра минимальные ресурсы.
ЕЩЁ БОЛЕЕ ВАЖНО:
Технически можно вообще жить без арбитра, однако с ним выборы будут происходить в разы быстрее, соответственно время простоя будет минимизировано. Плюс есть ненулевая вероятность потерять ReplicaSet целиком.
Primary
Настройки пишем в файл /etc/mongod.conf У меня файл выглядит следующим образом:
storage: engine: wiredTiger dbPath: /var/lib/mongodb journal: enabled: true systemLog: destination: file logAppend: true path: /var/log/mongodb/mongod.log replSetName: replicaname net: port: 27017 bindIp:0.0.0.0
Указываемые значения переменных:
dbPath — путь к базе данных. При указании на пустое место, создаст там базы. При разворачивании бэкапа подцепит существующую.
journal — включает журналирование.
replSetName — название реплики. Должно быть идентичным у всех узлов внутри реплики.
bindIp — список адресов, с которых можно принимать соединения по порту 27017.
Далее для конфигурирования я использовал саму mongoDB:
mongo
попадаем внутрь и первым делом проверяем статус:
rs.status()
Начальный статус должен быть 0 — startup. Означает что узел не является членом ни одной реплики.
Инициализируем реплику.
Выполняем в MongoShell на первичном узле
rs.initiate( { _id: "rs0", version: 1 members: [ { _id : 0, host : "<Primary server ip>:27017" } ] })
Проверяем конфигурацию:
rs.conf()
Сразу после добавления в реплику узел будет в статусе 5 — Startup2, это означает что он присоединился к реплике и в данный момент синхронизируется. Может занять продолжительное время.
Добавляем следующие узлы:
rs.add("<Secondary server ip>:27017")
Добавляем арбитра:
rs.addArb(“<arbiter server ip>:27017”)
либо
rs.add(“<arbiter server ip>:27017”, true)
Статусы в rs.status() будут:
1 — Primary
2 — Secondary
7 — Arbiter
Приоритеты
Варианты исполнения
Первый:
Необходимо проставить приоритеты (цифры member id берем из статуса):
cfg = rs.conf() cfg.members[0].priority = 2 cfg.members[1].priority = 3 cfg.members[2].priority = 1 rs.reconfig(cfg, {force : true})
Чем выше цифра приоритета, тем ниже сам приоритет при выборе Primary узла.
Второй:
Добавляем узлы с заранее прописанным приоритетом:
rs.add({host: “<secondary server ip:27017”, priority: 1})
Проверяем что все узлы доступны и выставлены с правильными приоритетами:
rs.status()
В моем случае конфиги и статусы приобрели следующий вид:
rs.status()
{ "set" : "<имя вашей реплики>", "date" : ISODate("2017-05-05T13:57:01.538Z"), "myState" : 2, "term" : NumberLong(1021), "syncingTo" : "<secondary server ip>:27017", "heartbeatIntervalMillis" : NumberLong(2000), "members" : [ { "_id" : 0, "name" : "<Secondary server ip>:27017", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 1908285, "optime" : { "ts" : Timestamp(1493992502, 1), "t" : NumberLong(1021) }, "optimeDate" : ISODate("2017-05-05T13:55:02Z"), "syncingTo" : ":27017", "configVersion" : 373058, "self" : true }, { "_id" : 1, "name" : "<Primary server ip>:27017", "health" : 1, "state" : 1, "stateStr" : "PRIMARY", "uptime" : 1688032, "optime" : { "ts" : Timestamp(1493992502, 1), "t" : NumberLong(1021) }, "optimeDate" : ISODate("2017-05-05T13:55:02Z"), "lastHeartbeat" : ISODate("2017-05-05T13:57:00.108Z"), "lastHeartbeatRecv" : ISODate("2017-05-05T13:57:00.895Z"), "pingMs" : NumberLong(0), "electionTime" : Timestamp(1492304555, 1), "electionDate" : ISODate("2017-04-16T01:02:35Z"), "configVersion" : 373058 }, { "_id" : 2, "name" : "<Arbiter server ip>:27017", "health" : 1, "state" : 7, "stateStr" : "ARBITER", "uptime" : 1680982, "lastHeartbeat" : ISODate("2017-05-05T13:56:59.812Z"), "lastHeartbeatRecv" : ISODate("2017-05-05T13:56:59.062Z"), "pingMs" : NumberLong(0), "configVersion" : 373058 } ], "ok" : 1 }
При добавлении узла в уже существующую реплику она какое-то время будет недоступна в связи с синхронизацией.
На этом установка и настройка MongoDB в режиме ReplicaSet завершена и можно с чистой совестью наполнять базу данными.
Другие полезные команды
Команды
Сбрасывание PRIMARY. Смена первичного узла и переназначение приоритетов
/var/lib/mongodb/ — Тут лежат файлы баз.
Восстановление из дампа:
Восстанавление базы в каталог по умолчанию. Если файл в с таким именем есть, то он перезаписывается:
Восстановление всех баз из указанного каталога:
Восстановление отдельной таблицы(коллекции):
Создание дампа
создание бэкапа всех баз в папку Backup:
создание бэкапа отдельной базы:
создание бэкапа отдельной таблицы:
Запуск от имени root, создание бэкапа указанной базы в указанный каталог + текущая дата:
60 секунд — время, в течение которого сервер, с которого запущено выполнение команды, не может стать Primary; 40 секунд — время перевыборов нового Primary.rs.stepDown(60,40)
30 секунд — время отключения Primary и перевыборы. Выполнение команды допустимо с любого из серверов mongoDB.db.adminCommand({replSetStepDown: 30, force: 1})
Узел, с которого запущена команда, в течение 60 секунд не сможет стать Primary.rs.stepDown(60)
/var/lib/mongodb/ — Тут лежат файлы баз.
Восстановление из дампа:
Восстанавление базы в каталог по умолчанию. Если файл в с таким именем есть, то он перезаписывается:
mongorestore <Имя БД>
Восстановление всех баз из указанного каталога:
mongorestore ./Backup
Восстановление отдельной таблицы(коллекции):
mongorestore --collection <коллекция> --db <Имя БД> dump/
Создание дампа
создание бэкапа всех баз в папку Backup:
mongodump --out /Backup
создание бэкапа отдельной базы:
mongodump --db <Имя БД> --out /Backup
создание бэкапа отдельной таблицы:
mongodump --db <Имя БД> --collection <Имя коллекции>--out /Backup
Запуск от имени root, создание бэкапа указанной базы в указанный каталог + текущая дата:
sudo mongodump --db newdb --out /var/backups/mongobackups/'date +"%m-%d-%y"'
Вот в общем-то и весь сказ о моем опыте разворачивания невиданной доселе системы в продакшен. Буду рад критике и дополнениям, если таковые появятся.