предисловие
Для обеспечения высокой доступности базы данных одного узла часто бывает недостаточно.В производственной среде обычно применяется кластерное развертывание, которое может не только обеспечить избыточность данных, но и обеспечить высокую доступность базы данных. В MongoDB есть два основных типа кластеров: наборы реплик и сегментированные кластеры.Первый обеспечивает избыточность и доступность данных, а второй может повысить пропускную способность системы. В этой статье в основном представлены концепция и конфигурация наборов реплик.
Описание набора копий репликации
элемент набора реплик
Содержимое, связанное с набором реплик, можно прочитатьофициальная документация.
Набор реплик (Репликация) — это группа, которая поддерживает один и тот же набор данныхmongod
пример. Набор реплик содержит несколько узлов данных и узел-арбитр (Arbiter). В узле данных есть один и только один элемент — первичный узел (Primary), а остальные узлы — вторичные узлы (Secondary).
The minimum recommended configuration for a replica set is a three member replica set with three data-bearing members: one primary and two secondary members. In some circumstances (such as you have a primary and a secondary but cost constraints prohibit adding another secondary), you may choose to include an arbiter. An arbiter participates in elections but does not hold data (i.e. does not provide data redundancy).
Фигура самая классическая из 3-узловой архитектуры (есть ресурсы, которые можно развернуть с двух узлов, тогда ни один не может быть преобразован в арбитражный узел).
- Первичный узел (основной)
Единственный узел в наборе реплик, поддерживающий операции чтения и записи. Операции записи обычно записываются в oplog.
- Вторичный узел
Узел данных имеет ту же копию данных, что и главный узел, и обычно доступен только для чтения. Подчиненный узел будет асинхронно синхронизировать данные из оплога главного узла. Ведомые узлы не могут участвовать в голосовании (приоритет: 0)
- Узел арбитра (Арбитр)
Узел, который используется только для голосования, не хранит копии данных и может быть развернут при нехватке ресурсов.Не рекомендуется, когда ресурсов достаточно.
Архитектура набора реплик
- Официальная рекомендуемая минимальная конфигурация для производственной среды — 3 узла, 1 основной и 2 вторичных.В случае нехватки ресурсов 1 вторичный узел можно преобразовать в арбитр.
- Набор реплик может содержать до 50 элементов, но только 7 членов с правом голоса.
- при наличии более 2 узлов. Рекомендуется иметь нечетное количество членов набора реплик без использования кворума (для предотвращения разделения мозгов, вызванного аномалиями сети в удаленных центрах обработки данных).
- Количество узлов с правом голоса превышает половину от общего числа узлов для голосования, а официальное число отказоустойчивых узлов обеспечено.
количество узлов | Выборам нужен новый узел | Количество узлов, которые могут терпеть неудачи |
---|---|---|
3 | 2 | 1 |
4 | 3 | 1 |
5 | 3 | 2 |
6 | 4 | 2 |
Автоматический переход на другой ресурс (HA)
MongoDB работает в соответствии с архитектурой набора реплик, когда основной узел выходит из строя, набор реплик переключается на другой, а оставшиеся узлы выбирают новый основной узел. Выбранный главный узел продолжает предоставлять услуги.После восстановления исходного вышедшего из строя главного узла он автоматически присоединяется к набору реплик в качестве подчиненного узла.
- После отказа основного узла (
electionTimeoutMillis
Он не может взаимодействовать с другими узлами внутриleaseTime
Выбор узла завершается в течение (по умолчанию 30 с). - До MongoDB r3.2.0 протокол выборов основывался на алгоритме Bully, начиная с r3.2.0 по умолчанию используется стратегия выборов на основе алгоритма Raft.
- Количество узлов, участвующих в выборах, превышает половину от общего числа узлов в наборе реплик.
- Набор реплик не может обрабатывать записи до тех пор, пока выборы не будут успешными. Если запрос на чтение настроен для выполнения наподчиненный узел, набор реплик может продолжать обрабатывать эти запросы, когда основной узел отключается.
Операция чтения узла
- Главный узел может выполнять операции чтения и записи, а подчиненный узел может только читать данные.
- По умолчанию, когда главный узел работает правильно, клиент MongoDB может только считывать данные с главного узла.
- Если вам нужно прочитать данные с ведомого узла, вы можете передать
slaveOk
а такжеReadPreference
настроить.- Установить на ведомом узле
rs.slaveOk()
После этого клиент может считывать данные с ведомого узла. - Более подробная конфигурация чтения данных, которую можно настроить с помощью
ReadPreference
. исполняемая команда оболочки mongodb.getMongo().setReadPref('secondary')
настраивать.
- Установить на ведомом узле
модель | описывать |
---|---|
primary | Только читать данные с основного узла, это настройка по умолчанию |
primaryPreferred | Сначала прочитайте с первичного, первичный не исправен, прочитайте с вторичного |
secondary | Только считывать данные со второстепенных узлов |
secondaryPreferred | Сначала читайте из вторичного элемента и читайте из первичного, когда нет вторичного члена. |
nearest | Чтение согласно сетевому расстоянию |
Сборка набора реплик в среде Docker
основная среда
- Ubuntu16.04
- Docker19.03
- Docker-Compose1.25.1-rc1
- MongoDB4.2.8
Поскольку для настройки набора реплик требуется несколько узлов, для быстрой установки здесь используется Docker. За исключением способа установки, конфигурация других MongoDB такая же, как и локальная установка. Для локальной установки см.официальная документация.
Процесс настройки
- Запустите 3 экземпляра MongoDB с помощью команды docker.
docker run -d \
--name mongo1 \
-p 37017:27017 \
-v /home/mongodb/replset/mongo1/mongod.conf:/data/configdb/mongod.conf \
-v /home/mongodb/replset/mongo1/data:/data/db \
mongo:4.2.8 --config /data/configdb/mongod.conf
docker run -d \
--name mongo2 \
-p 37018:27017 \
-v /home/mongodb/replset/mongo2/mongod.conf:/data/configdb/mongod.conf \
-v /home/mongodb/replset/mongo2/data:/data/db \
mongo:4.2.8 --config /data/configdb/mongod.conf
docker run -d \
--name mongo3 \
-p 37019:27017 \
-v /homer/mongodb/replset/mongo3/mongod.conf:/data/configdb/mongod.conf \
-v /home/mongodb/replset/mongo3/data:/data/db \
mongo:4.2.8 --config /data/configdb/mongod.conf
конфигурационный файл
# mongod.conf
# for documentation of all options, see:
# http://docs.mongodb.org/manual/reference/configuration-options/
# Where and how to store data.
storage:
dbPath: /data/db # 配置数据存放的位置
journal:
enabled: true
# engine:
# mmapv1:
# wiredTiger:
# where to write logging data.
systemLog:
destination: file
logAppend: true
path: /var/log/mongodb/mongod.log # 日志文件
# network interfaces
net:
port: 27017
bindIp: 0.0.0.0 # 配置网络
# how the process runs
processManagement:
timeZoneInfo: /usr/share/zoneinfo
#security:
#keyFile:
#operationProfiling:
#replication:
replication:
replSetName: rs # 定义副本集的名称
#sharding:
## Enterprise-Only Options:
#auditLog:
#snmp:
- Предполагая, что mongo1 является главным узлом, введите главный узел, выполните mongo и войдите в оболочку mongo.
rs.initiate({
"_id": "rs",
"members": [
{
"_id": 1,
"host": "172.17.218.94:37017"
},
{
"_id": 2,
"host": "172.17.218.94:37018"
},
{
"_id": 3,
"host": "172.17.218.94:37019"
}
]
})
Если содержимое возвращается, это доказывает, что конфигурация прошла успешно.
{
"ok" : 1,
"$clusterTime" : {
"clusterTime" : Timestamp(1596456560, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
},
"operationTime" : Timestamp(1596456560, 1)
}
Подождав более десяти секунд, можно обнаружить, что терминал изменился:
rs:PRIMARY>
воплощать в жизньrs.status()
Чтобы просмотреть статус текущего набора реплик:
# 忽略部分参数
{
"set": "rs",
"members": [
{
"_id": 1,
"name": "172.17.218.94:37017",
"health": 1,
"state": 1,
"stateStr": "PRIMARY"
},
{
"_id": 2,
"name": "172.17.218.94:37018",
"health": 1,
"state": 2,
"stateStr": "SECONDARY"
},
{
"_id": 3,
"name": "172.17.218.94:37019",
"health": 1,
"state": 2,
"stateStr": "SECONDARY"
}
],
"ok": 1
}
Все в порядке.
Проверка набора реплик
- Проверка синхронизации данных с подчиненных узлов
Вставьте данные на основной узел
rs:PRIMARY> db.col.insert({"name":"test"})
WriteResult({"nInserted" : 1})
rs:PRIMARY> db.col.find()
{"_id" : ObjectId("5f290145f350f0ccb3e03622"), "name" : "test" }
При запросе с подчиненного узла он предложит неглавный узел, данные не читаются, установитеSlaveOk
Данные мгновенно читаются.
rs:SECONDARY> db.col.find()
Error: error: {
"operationTime" : Timestamp(1596522843, 1),
"ok" : 0,
"errmsg" : "not master and slaveOk=false",
"code" : 13435,
"codeName" : "NotMasterNoSlaveOk",
"$clusterTime" : {
"clusterTime" : Timestamp(1596522843, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
rs:SECONDARY> db.setSlaveOk()
rs:SECONDARY> db.col.find()
{"_id" : ObjectId("5f290145f350f0ccb3e03622"), "name" : "test" }
- Проверить отказоустойчивость
Вручную остановите Mongo1 и введите контейнер Mongo2, чтобы проверить состояние узла. В это время Mongo2 был избран в качестве главного узла.
rs:PRIMARY> rs.status()
{
"members": [
{
"_id": 1,
"name": "172.17.218.94:37017",
"health": 0,
"state": 8,
"stateStr": "(not reachable/healthy)",
"uptime": 0
},
{
"_id": 2,
"name": "172.17.218.94:37018",
"health": 1,
"state": 1,
"stateStr": "PRIMARY"
},
{
"_id": 3,
"name": "172.17.218.94:37019",
"health": 1,
"state": 2,
"stateStr": "SECONDARY"
}
]
}
Шаг вперед: использование Compose
Очевидно, что использование Docker для непосредственного развертывания конфигурации требует множества ручных команд, а адаптироваться к Compose гораздо проще.
version: '3'
services:
mongo-1:
image: mongo:4.2.8
hostname: mongo-1
restart: always
ports:
- 37017:27017
volumes:
- /home/mongodb/replset/mongo1/mongod.conf:/data/configdb/mongod.conf
- /home/mongodb/replset/mongo1/data:/data/db
command:
- --config
- /data/configdb/mongod.conf
mongo-2:
image: mongo:4.2.8
hostname: mongo-2
restart: always
ports:
- 37018:27017
volumes:
- /home/mongodb/replset/mongo2/mongod.conf:/data/configdb/mongod.conf
- /home/mongodb/replset/mongo2/data:/data/db
command:
- --config
- /data/configdb/mongod.conf
mongo-3:
image: mongo:4.2.8
hostname: mongo-3
restart: always
ports:
- 37019:27017
volumes:
- /home/mongodb/replset/mongo3/mongod.conf:/data/configdb/mongod.conf
- /home/mongodb/replset/mongo3/data:/data/db
command:
- --config
- /data/configdb/mongod.conf
mongo-init:
image: mongo:4.2.8
depends_on:
- mongo-1
- mongo-2
- mongo-3
restart: on-failure:5
command:
- mongo
- mongodb://@mongo-1:37017/admin
- --eval
- 'rs.initiate({_id:"rs", members: [{_id:1,host:"172.17.218.94:37017"},{_id:2,host:"172.17.218.94:37018"},{_id:3,host:"172.17.218.94:37019",}]});cfg = rs.conf();cfg.members[0].priority=2;rs.reconfig(cfg)'
На основе использования команд Docker код для настройки набора реплик также записывается в файл конфигурации Compose, а mongo-1 по умолчанию устанавливается в качестве главного узла (приоритет = 2).
Затем выполните:
root@localhost:# docker-compose up -d
После входа в mongo-1 введитеrs.status()
Вы можете видеть, что набор реплик настроен и готов к использованию из коробки.
Дальнейшая настройка
- создание пользователя базы данных
Войдите в оболочку mongo и выполните следующие команды.
use admin
db.createUser({
user: 'root',
pwd: '123456',
roles:[{
role: 'root',
db: 'admin'
}]
})
Измените файл конфигурации, чтобы включить обязательную аутентификацию.
security:
authorization: enabled
Перезапустите службу монгод. Служба mongod не может быть перезапущена в докере, а контейнер может быть перезапущен после непосредственного изменения файла конфигурации.
Снова войдите в оболочку mongo и выполнитеrs.conf()
Подскажут несанкционированные, в это время мыadmin
База данныхdb.auth("root","123456")
Вот и все.
- Контроль доступа между узлами
Для настройки keyFile см.официальная документация.
Суммировать
Эта статья подробно описывает содержимое, связанное с набором копирования Mongodb. Набор копий копии может улучшить доступность базы данных в одной точке, обеспечивая избыточность для данных, приоритет в производственной среде. Для некоторых более сложных ситуаций вы можете настроить разделение чтения и записи на основе копии. Если сумма данных велика, единственная точка не может быть сохранена, а кластер Slice может быть дополнительно настроен.
Приложение: Общий порядок
show dbs
show collections
show users
db.auth("root","123456")
db.stats()
db.getUser("root")
rs.conf()
rs.status()
db.adminCommand({getParameter:"*"})
db._adminCommand({getCmdLineOpts: 1})