NoSQL
MongoDB
February 2013 8

Репликация MongoDB на Amazon EC2

From Sandbox

system.indexes


  • Предисловие
  • Настройка Amazon EC2
  • Установка MongoDB
  • Настройка репликации
  • Что почитать

local.abstract


В этой статье я расскажу о том, как максимально безболезненно организовать репликацию MongoDB на базе Amazon EC2. Несомненно, существует отличная документация как по работе с Amazon EC2, так и по настройке MongoDB в целом и репликации в частности. Но, как известно, дьявол живёт в мелочах. И в этой статье я выделю те “мелочи”, которые более всего донимали меня.

{step: 1, title: «Amazon EC2 configure», devilCount: 2}


Начнём с начала – с настройки инстансов.

Первым делом надо создать две группы приватности: для web-инстансов и для инстансов базы данных.
Для web-инстансов откроем доступ для SSH, HTTP и HTTPS:


Для db-инстансов откроём всё тот же доступ по SSH, плюс доступ на порт 27017 для групп приватности web и db:


Теперь можем запускать сами инстансы: один small-инстанс для web-приложения, два large- и один micro- инстанс для базы данных. В качестве Amazon Machine Image (AMI) я выбрал Ubuntu Server 12. Важно: чтобы репликация MongoDB заработала, обязательным условием является нечётное количество инстансов. С этой целью мы и будем использовать 3й – микро-инстанс – в качестве арбитра. О том что такое арбитр, я расскажу ниже. Конечно, мы бы могли просто запустить и 5, 7 или 2n + 1 large-инстансов. Но данным примером я хочу показать хороший вариант того, как можно минимизировать затраты на Amazon EC2, и лишний раз акцентирую внимание на том, что инстансов в репликации должно быть нечётное количество.

Есть ещё один неочевидный, но достаточно весомый ньюанс – динамичность IP-адресов у инстансов. Соответственно завязываться на них при настройке репликации – не самый идеальный вариант. Лучше для этих целей воспользоваться алиасами, которые настраиваются в файле /etc/hosts. На каждом инстансе приведём файл hosts примерно к такому виду:
127.0.0.1 db1 localhost
10.40.120.30 db1
10.40.120.31 db2
10.40.120.32 db3

Теперь мы имеем готовые к дальнейшему использованию инстансы.

{step: 2, title: «MongoDB install», devilCount: 1}


Приступим к установке MongoDB. Процесс установки отлично описан в официальном мануале MongoDB, так что следуем чётко его указаниям. Создадим файл mongo_install.bash и запишем в него следующий скрипт:
apt-key adv --keyserver keyserver.ubuntu.com --recv 7F0CEB10
echo "deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen" | tee -a /etc/apt/sources.list.d/10gen.list
apt-get -y update
apt-get -y install mongodb-10gen

Выполняем наш скрипт:
sudo bash ./mongo_install.bash

Если всё прошло успешно, то мы увидим PID запущенного MongoDB:
mongodb start/running, process 2368

Теперь осталось запустить процесс mongod:
sudo service mongodb start

Маленькая хитрость напоследок: чтобы не проходить столь мучительный и однообразный путь установки софта на каждом инстансе, можно воспользоваться функциональностью Amazon EC2 Images.

{step: 3, title: «Replication», devilCount: 2}


Вот мы и подошли к главному пункту – настройке репликации. Сперва, определим в файлах конфигурации (/etc/mongodb.conf) на всех db-инстансах параметр replSet. Этот параметр должен содержать имя репликации:
replSet = myproject

После этого перезапускаем сервис:
sudo service mongodb restart

Далее подключаемся к Монге командой
mongo

Инициируем реплику:
rs.initiate()

Добавляем второй инстанс в нашу репликацию:
rs.add("db2:27017")

Третий же инстанс, и это важно, добавляем как арбитр:
rs.addArb("db3:27017")

Арбитр не хранит свою копию базы данных. Он не участвует ни в записи, ни в чтении данных. Предназначен исключтельно для голосования за Primary. Этим и обусловлен тот факт, что мы можем запускать арбитра на минимальном железе.

Посмотрим текущий статус реплики:
mydb:PRIMARY> rs.status()
{
        "set" : "myproject",
        "date" : ISODate("2013-02-04T12:17:42Z"),
        "myState" : 1,
        "members" : [
                {
                        "_id" : 0,
                        "name" : "db1:27017",
                        "health" : 1,
                        "state" : 1,
                        "stateStr" : "PRIMARY",
                        "uptime" : 1139012,
                        "optime" : Timestamp(1359738450000, 12),
                        "optimeDate" : ISODate("2013-02-01T17:07:30Z"),
                        "self" : true
                },
                {
                        "_id" : 1,
                        "name" : "db2:27017",
                        "health" : 1,
                        "state" : 2,
                        "stateStr" : "SECONDARY",
                        "uptime" : 1138953,
                        "optime" : Timestamp(1359738450000, 12),
                        "optimeDate" : ISODate("2013-02-01T17:07:30Z"),
                        "lastHeartbeat" : ISODate("2013-02-04T12:17:42Z"),
                        "pingMs" : 0
                },
                {
                        "_id" : 2,
                        "name" : "db3:27017",
                        "health" : 1,
                        "state" : 2,
                        "stateStr" : "SECONDARY",
                        "uptime" : 442498,
                        "optime" : Timestamp(1359738450000, 12),
                        "optimeDate" : ISODate("2013-02-01T17:07:30Z"),
                        "lastHeartbeat" : ISODate("2013-02-04T12:17:40Z"),
                        "pingMs" : 0
                }
        ],
        "ok" : 1
}

Узнать какое поле за что отвечает можно узнать здесь: docs.mongodb.org/manual/reference/replica-status/#fields

Проверим конфиг:
mydb:PRIMARY> rs.config()
{
        "_id" : "myproject",
        "version" : 12,
        "members" : [
                {
                        "_id" : 0,
                        "host" : "db1:27017"
                },
                {
                        "_id" : 1,
                        "host" : "db2:27017"
                },
                {
                        "_id" : 2,
                        "host" : "db3:27017",
                        "arbiterOnly" : true
                }
        ]
}

Видим, что всё выглядит именно так, как мы и задумали. Ура!

И на десерт ещё один момент. В настройках реплики у каждого участника среди прочих есть свойство priority. По умолчанию оно равняется 1 и, как дефолтное значение, не отображается в конфиге. Это значение влияет на вероятность того, что участник будет избран Primary. Сделаем так, чтобы db1 был гарантировано Primary (ну, например, у него больше памяти):
config = rs.config()
config.members[0].priority = 2
rs.reconfig(config)

Теперь конфиг будет выглядить следующим образом:
mydb:PRIMARY> rs.config()
{
        "_id" : "myproject",
        "version" : 12,
        "members" : [
                {
                        "_id" : 0,
                        "host" : "db1:27017",
		"priority" : 2
                },
                {
                        "_id" : 1,
                        "host" : "db2:27017"
                },
                {
                        "_id" : 2,
                        "host" : "db3:27017",
                        "arbiterOnly" : true
                }
        ]
}

Очень важное замечание от StamPit:
Проблема: Не указан размер oplog. Для 64bit систем по умолчанию он составляет 5% от доступного дискового пространства, но не менее 1Gb. Если диск большой и средняя активность insert/update — стоит ограничить размер в конфиге, 2000Mb вполне достаточно:
oplogSize = 2000

Если данных не так много, а количество insert/update не слишком велико, можно слегка уменьшить дисковую активность следующим образом:
1) Отключить preallocate noprealloc = true
2) Уменьшить размер файлов (уменьшатся как файлы данных, так и журнала) smallfiles = true

Пожалуй, это и всё, что понадобится для того, чтобы настроить репликацию Монги на базе Amazon EC2. При необходимости вы сможете легко добавлять новые инстансы в такую конфигурацию.

local.links


  1. Amazon EC2 aws.amazon.com/documentation/ec2
  2. MongoDb Installation docs.mongodb.org/manual/tutorial/install-mongodb-on-ubuntu
  3. MongoDB docs.mongodb.org/manual/tutorial/getting-started
  4. MongoDb Replication docs.mongodb.org/manual/replication
  5. MongoDb Replica Set Arbiters docs.mongodb.org/manual/administration/replica-sets/#replica-set-arbiters
  6. MongoDb Replica Set Configuration docs.mongodb.org/manual/reference/replica-configuration
+21
12.9k 113
Comments 14