Translate

пʼятниця, 4 січня 2013 р.

Реплікація MongoDB: ReplicaSet

Зовсім нещодавно, я писав про реплікацію MySQL, тож хотілося б продовжити традицію. Цього разу мова піде про реплікацію MongoDB.

MongoDB підтримує два типи реплікацій Master-Slave (на кшталт такої в MySQL) та ReplicaSet. Остання - це прогресивніший варант, так як по-суті одразу забезпечує failover: обирання майстра, у разі відмови попереднього проходить "голосуванням" наявних інстансів (копій).  Це вже не кажучи про те, що ReplicaSet забезпечує читання зі слейвів (або як кажуть secondary-серверів), тим самим підвищуючи швидкість читання. Запити на запис відбуваються лише на головному (primary) сервері. Коротше кажучи, все вищесказане гарно ілюструє цей малюнок:


Приступимо до конфігурації. 3 інстанси демона MongoDB будуть запущені на локалхості, проте на різних портах.
Перед налаштуванням не забуваємо встановити базу данних.
Щоб не захламлювати систему створимо папку mongodb, а вже в ній папки 1, 2, 3 для кожної копії:

mkdir mongodb
cd mongodb
mkdir 1 2 3 

Запускаємо 3 копії демону mongod на портах 2700(1|2|3):

$ mongod --replSet test --dbpath 1 --port 27001 --smallfiles --oplogSize 50 --logpath 1.log --fork
forked process: 18922
all output going to: /media/other/mongodb/replication/1.log
child process started successfully, parent exiting

$ mongod --replSet test --dbpath 2 --port 27002 --smallfiles --oplogSize 50 --logpath 2.log --fork
forked process: 18983
all output going to: /media/other/mongodb/replication/2.log
child process started successfully, parent exiting

$ mongod --replSet test --dbpath 3 --port 27003 --smallfiles --oplogSize 50 --logpath 3.log --fork
forked process: 19029
all output going to: /media/other/mongodb/replication/3.log
child process started successfully, parent exiting


Якщо у вас вивід інакший - то розумно буде почитати логи. Також не забуваємо виставити вірні права на директорії. Опишу трохи значення ключів з якими запущено демони:

--replSet - назва реплікасету. Якщо інстанс входить в одну групу - відповідно назва має бути такою ж.
--dbpath - шлях до директорії, де MongoDB буде зберігати свої дані.
--smallfiles - обмеження розміру файлів, щоб директорія з данними і журналами не розрослась до об'єму розділу диску.
--oplogSize - максимальний розмір логу в мегабайтах.
--logpath - шлях до директорії, де MongoDB буде зберігати свої логи.
--fork - відв'язка виводу від терміналу де було запущено демон.

Заходимо в консоль Монги, котру ми плануємо зробити майстром:

$mongo --port 27001

MongoDB shell version: 2.2.2
connecting to: 127.0.0.1:27001/test
Welcome to the MongoDB shell.
For interactive help, type "help".
For more comprehensive documentation, see
http://docs.mongodb.org/
Questions? Try the support group
http://groups.google.com/group/mongodb-user


Ініціалізуємо сервери:

>cfg = {
... _id: "test",
... members: [
... {_id: 0, host: "localhost:27001"},
... {_id: 1, host: "localhost:27002"},
... {_id: 2, host: "localhost:27003"}
... ]
... }

Якщо запит виконано вірно - буде такий результат:

{
             "_id" : "test",
             "members" : [
            {
                       "_id" : 0,
                       "host" : "localhost:27001"
             },
             {
                       "_id" : 1,
                       "host" : "localhost:27002"
              },
             {
                       "_id" : 2,
                       "host" : "localhost:27003"
              }
              ]
}


Далі пишемо задля збереження конфігу:

> rs.initiate(cfg)
{
  "info" : "Config now saved locally. Should come online in about a minute.",
  "ok" : 1
}


Виходимо з консолі MongoDB:

> exit
bye


Тепер необхідно виконати на кожному із майбутніх secondary серверів rs.slaveOk():

$ mongo --port 27002
MongoDB shell version: 2.2.2
connecting to: 127.0.0.1:27002/test
test:RECOVERING> rs.slaveOk()
test:SECONDARY> exit
Для третього інстанса на порту 27003 все повністю аналогічно.
Перевірити статус реплікації можна виконавши таку команду на будь-якому сервері/інстансі  mongo:

test:SECONDARY> rs.status()
{
        "set" : "test",
        "date" : ISODate("2013-01-02T00:26:14Z"),
        "myState" : 2,
        "syncingTo" : "localhost:27001",
        "members" : [
                {
                        "_id" : 0,
                        "name" : "localhost:27001",
                        "health" : 1,
                        "state" : 1,
                        "stateStr" : "PRIMARY",
                        "uptime" : 85,
                        "optime" : Timestamp(1357086283000, 1),
                        "optimeDate" : ISODate("2013-01-02T00:24:43Z"),
                        "lastHeartbeat" : ISODate("2013-01-02T00:26:13Z"),
                        "pingMs" : 0
                },
                {
                        "_id" : 1,
                        "name" : "localhost:27002",
                        "health" : 1,
                        "state" : 2,
                        "stateStr" : "SECONDARY",
                        "uptime" : 85,
                        "optime" : Timestamp(1357086283000, 1),
                        "optimeDate" : ISODate("2013-01-02T00:24:43Z"),
                        "lastHeartbeat" : ISODate("2013-01-02T00:26:13Z"),
                        "pingMs" : 0
                },
                {
                        "_id" : 2,
                        "name" : "localhost:27003",
                        "health" : 1,
                        "state" : 2,
                        "stateStr" : "SECONDARY",
                        "uptime" : 420,
                        "optime" : Timestamp(1357086283000, 1),
                        "optimeDate" : ISODate("2013-01-02T00:24:43Z"),
                        "self" : true
                }
        ],
        "ok" : 1
}
test:SECONDARY> 

Для практичної перевірки реплікації  можна записати щось в базу на primary сервер і перевірити її наявність на secondary. 

Немає коментарів:

Дописати коментар