MongoDB Sharded Cluster на Centos 6.5

В этой статье мы рассмотрим только конфигурацию MongoDB, не затрагивая вопросы подключения репозитория монги и установки пакетов в систему.Распределенный кластер MongoDB состоит из следующих компонентов:

ШардШард — это инстанс mongod, который хранит часть данных шардированной коллекции. Для использования в production, каждый шард должен быть набором реплик (replicaSet).

Сервер конфигурацийТак же экземпляр mongod, который хранит метаданные кластера. Метаданные указывают какие данные хранятся на каком шарде.

Сервер маршрутизацииЭкземпляр mongos. Его задача — маршрутизация запросов от приложений к шардам.Ниже приведена схема работы шардированного кластера MongoDB

e0331f205133e7dd5a7e79fb9f660fe3.pngУдобнее всего необходимые роли группировать следующим образом:

Сервер конфигурации + сервер маршрутизации Шард Допустим, для создания этих ролей мы имеем 3 сервера:

mongos01 mongos02 mongos03 Настройка сервера конфигурацийДля того, что бы mongod работал как сервер конфигураций, приводим /etc/mongod.conf к следующему виду: logpath=/var/log/mongodb/mongod.log logappend=true fork=true dbpath=/opt/mongocfg pidfilepath=/var/run/mongodb/mongod.pid bind_ip=, configsvr=false После чего запускаем сервис

# service mongod start

Настройка сервера маршрутизации Прежде чем переходить к настройке сервера маршрутизации, необходимо убедиться что в системе установлен пакет mongodb-org-mongos # rpm -qa | grep mongosmongodb-org-mongos-2.6.2–1.x86_64

Для начала, создадим файл конфигурации для сервиса mongos /etc/mongos.conf и приведем его к следующему виду:

configdb=mongos01:27019, mongos02:27019, mongos03:27019 # Mongo config servers addresses port = 27017 logpath = /var/log/mongodb/mongos.log logappend = true fork = true bind_ip=, verbose = false Mongo не включили в свой пакет init script для mongos, посему создадим его

cat > /etc/init.d/mongos << TheEnd

#!/bin/bash

# mongos — Startup script for mongos

# chkconfig: 35 85 15 # description: Mongo Router Process for sharding # processname: mongos # config: /etc/mongos.conf # pidfile: /var/run/mongos.pid

. /etc/rc.d/init.d/functions

# mongos will read mongos.conf for configuration settings

# Add variable to support multiple instances of mongos # The instance name is by default the name of this init script # In this way another instance can be created by just copying this init script # and creating a config file with the same name and a .conf extension # For Example: # /etc/init.d/mongos2 # /etc/mongos2.conf # Optionally also create a sysconfig file to override env variables below # /etc/sysconfig/mongos2 INSTANCE=`basename $0`

# By default OPTIONS just points to the /etc/mongod.conf config file # This can be overriden in /etc/sysconfig/mongod OPTIONS=» -f /etc/${INSTANCE}.conf»

PID_PATH=/var/run/mongo PID_FILE=${PID_PATH}/${INSTANCE}.pid MONGO_BIN=/usr/bin/mongos MONGO_USER=mongod MONGO_GROUP=mongod MONGO_ULIMIT=12000 MONGO_LOCK_FILE=/var/lock/subsys/${INSTANCE}

# Source sysconfig options so that above values can be overriden SYSCONFIG=»/etc/sysconfig/${INSTANCE}» if [ -f »$SYSCONFIG» ]; then .»$SYSCONFIG» || true fi

# Create mongo pids path if it does not exist if [ ! -d »${PID_PATH}» ]; then mkdir -p »${PID_PATH}» chown »${MONGO_USER}:${MONGO_GROUP}» »${PID_PATH}» fi

start () { echo -n $«Starting ${INSTANCE}:» daemon --user »$MONGO_USER» --pidfile $PID_FILE $MONGO_BIN $OPTIONS --pidfilepath=$PID_FILE RETVAL=$? echo [ $RETVAL -eq 0 ] && touch $MONGO_LOCK_FILE return $RETVAL }

stop () { echo -n $«Stopping ${INSTANCE}:» killproc -p $PID_FILE -t30 -TERM $MONGO_BIN RETVAL=$? echo [ $RETVAL -eq 0 ] && rm -f $MONGO_LOCK_FILE [ $RETVAL -eq 0 ] && rm -f $PID_FILE return $RETVAL }

restart () { stop start }

ulimit -n $MONGO_ULIMIT RETVAL=0

case »$1» in start) start ;; stop) stop ;; restart|reload|force-reload) restart ;; condrestart) [ -f $MONGO_LOCK_FILE ] && restart || : ;; status) status -p $PID_FILE $MONGO_BIN RETVAL=$? ;; *) echo «Usage: $0 {start|stop|status|restart|reload|force-reload|condrestart}» RETVAL=1 esac

exit $RETVAL TheEnd Сделаем его исполняемым

chmod +x /etc/init.d/mongos

Теперь можно запускатьservice mongos startИ не забыть

# chkconfig mongod on # chkconfig mongos on Теперь нужно повторить эти действия на остальных серверах.

Настройка шардов Первое что необходимо помнить при настройке шардов для production среды — каждый шард это replica set.Более подробно про репликацию в MongoDB можно прочесть в официальной документацииМы же не будем на этом подробно останавливаться, а приступим к насройке.У нас будет 4 сервера:

Master для первого шарда (mongo01-rs01) Slave для первого шарда (mongo02-rs01) Master для второго шарда (mongo01-rs02) Slave для второго шарда (mongo02-rs02) Допустим, на всех четырех серверах уже установлена система и установлен mongodbВ /etc/mongodb.conf на mongo01-rs01 и mongo02-rs01 нужно задать имя для набора реплик, которое будет использовать этот шард

replSet=rs01 Сохраняем и запускаем mongod.Далее заходим в консоль mongo на сервере который планируем сделать Master # mongo

И инициализируем набор реплик > rs.initiate ()

Что бы убедиться что набор реплик инициализирован посмотрим его конфиг rs01: PRIMARY> rs.conf ()

Вывод должен показать что-то подобное: { »_id» : «rs01», «version» : 7, «members» : [ { »_id» : 0, «host» : «mongo01-rs01:27017» } ] } Далее добавляем наш второй сервер в этот набор

rs01: PRIMARY> rs.add («mongo02-rs01»)

И проверяем конфиг rs01: PRIMARY> rs.conf ()

{ »_id» : «rs01», «version» : 7, «members» : [ { »_id» : 0, «host» : «mongo01-rs01:27017» }, { »_id» : 1, «host» : «mongo02-rs01:27017», } ] } Для повышения отказоустойчивости MongoDB рекомендуется количество машин в наборе делать не четным.Так как мы не хотим создавать еще одну копию данных, мы можем создать Арбитра

Арбитр — это экземпляр mongod, который является членом набора реплик, но не хранит никаких данных. Он участвует в выборе нового мастера.Про то как устроены выборы, очень подробно написано в официальной документацииДля того, чтобы не выделять под него отдельную машину — воспользуемся одной из ранее созданных — mongos01Как мы помним, там по service mongod start запускается экземпляр mongod который является сервером конфигураций.Что бы не запускать арбитра руками мы должны сделать для него init script

cat > /etc/init.d/mongo-rs01-arb << TheEnd #!/bin/bash

# mongod — Startup script for mongod

# chkconfig: 35 85 15 # description: Mongo is a scalable, document-oriented database. # processname: mongod # config: /etc/mongod.conf # pidfile: /var/run/mongodb/mongod.pid

. /etc/rc.d/init.d/functions

# things from mongod.conf get there by mongod reading it

# NOTE: if you change any OPTIONS here, you get what you pay for: # this script assumes all options are in the config file. CONFIGFILE=»/etc/mongod-rs01-arb.conf» OPTIONS=» -f $CONFIGFILE» SYSCONFIG=»/etc/sysconfig/mongod-rs01-arb»

# FIXME: 1.9.x has a --shutdown flag that parses the config file and # shuts down the correct running pid, but that’s unavailable in 1.8 # for now. This can go away when this script stops supporting 1.8. DBPATH=`awk -F= '/^dbpath[[: blank:]]*=[[: blank:]]*/{print $2}' »$CONFIGFILE»` PIDFILE=`awk -F= '/^pidfilepath[[: blank:]]*=[[: blank:]]*/{print $2}' »$CONFIGFILE»` mongod=${MONGOD-/usr/bin/mongod}

MONGO_USER=mongod MONGO_GROUP=mongod

if [ -f »$SYSCONFIG» ]; then .»$SYSCONFIG» fi

# Handle NUMA access to CPUs (SERVER-3574) # This verifies the existence of numactl as well as testing that the command works NUMACTL_ARGS=»--interleave=all» if which numactl >/dev/null 2>/dev/null && numactl $NUMACTL_ARGS ls / >/dev/null 2>/dev/null then NUMACTL=«numactl $NUMACTL_ARGS» else NUMACTL=» fi

start () { # Recommended ulimit values for mongod or mongos # See http://docs.mongodb.org/manual/reference/ulimit/#recommended-settings # ulimit -f unlimited ulimit -t unlimited ulimit -v unlimited ulimit -n 64000 ulimit -m unlimited ulimit -u 32000

echo -n $«Starting mongod:» daemon --user »$MONGO_USER» »$NUMACTL $mongod $OPTIONS >/dev/null 2>&1» RETVAL=$? echo [ $RETVAL -eq 0 ] && touch /var/lock/subsys/mongod-rs01-arb }

stop () { echo -n $«Stopping mongod:» killproc -p »$PIDFILE» -d 300 /usr/bin/mongod RETVAL=$? echo [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/mongod-rs01-arb }

restart () { stop start }

RETVAL=0

case »$1» in start) start ;; stop) stop ;; restart|reload|force-reload) restart ;; condrestart) [ -f /var/lock/subsys/mongod ] && restart || : ;; status) status $mongod RETVAL=$? ;; *) echo «Usage: $0 {start|stop|status|restart|reload|force-reload|condrestart}» RETVAL=1 esac

exit $RETVAL TheEnd Делаем его исполняемым

# chmod+x /etc/init.d/mongo-rs01-arb

Создадим для него BaseDir и файл конфигурации # mkdir /opt/mongo-rs01-arb; chown mongod: mongod /opt/mongo-rs01-arb# cp -av /etc/mongod.conf /etc/mongod-rs01-arb.conf

Далее в файле /etc/mongod-rs01-arb.conf редактируем следующие строки port=27020 dbpath=/opt/mongo-rs01-arb pidfilepath=/var/run/mongodb/mongod-rs01-arb.pid И удаляем/комментируем строку configsvr=true Сохраняем файл и запускаем сервис # service mongo-rs01-arb start

Далее возвращаемся на наш Master для rs01, и в консоли mongo добавляем арбитра в набор реплик > rs.addArb («mongos01:27020»)

Проверяем конфиг

rs01: PRIMARY> rs.conf ()

{ »_id» : «rs01», «version» : 7, «members» : [ { »_id» : 0, «host» : «mongo01-rs01:27017» }, { »_id» : 1, «host» : «mongo02-rs01:27017», }, { »_id» : 2, «host» : «mongos01:27020», «arbiterOnly» : true } ] } Повторяем эту процедуру с оставшимися двумя серверами под второй набор реплик который будет вторым шардом в нашем кластере (mongo01-rs02 и mongo02-rs02)

И так, мы создали 2 набора реплик, которые теперь надо добавить в наш распределенный кластер.Для этого идем на mongos01 и заходим в консоль mongo (Следует помнить, что, в данном случае, мы подключаемся к сервису mongos)

> sh.addShard («rs01//mongo01-rs01:27017, mongo02-rs01:27017»)> sh.addShard («rs02/mongo01-rs02:27017, mongo02-rs02:27017»)

Проверяем: > sh.status ()

Вывод должен содержать следующие строки: shards: { »_id» : «rs01», «host» : «rs01/mongo01-rs01:27017, mongo02-rs01:27017» } { »_id» : «rs02», «host» : «rs02/mongo01-rs02:27017, mongo02-rs02:27017» } Это означает что в наш кластер успешно добавлены 2 шарда

Теперь добавим в наш распределенный кластер базу которую будем шардировать.В нашем случае это будет база содержащая файловую систему GridFS

> use filestore> sh.enableSharding («filestore»)> sh.shardCollection («filestore.fs.chunks», { files_id: 1, n: 1 })

Проверяем статус > sh.status ()

Вывод должен быть примерно таким: shards: { »_id» : «rs01», «host» : «rs01/mongo01-rs01:27017, mongo02-rs01:27017» } { »_id» : «rs02», «host» : «rs02/mongo01-rs02:27017, mongo02-rs02:27017»} databases: { »_id» : «admin», «partitioned» : false, «primary» : «config» } { »_id» : «test», «partitioned» : false, «primary» : «rs02» } { »_id» : «filestore», «partitioned» : true, «primary» : «rs01» } filestore.fs.chunks shard key: { «files_id» : 1, «n» : 1 } chunks: rs01 1363 rs02 103 too many chunks to print, use verbose if you want to force print Вот и все, теперь можем использовать наш распределенный GridFS в приложении обращаясь к экземплярам mongos

PS: про ошибки и не точности просьба писать в личку,

© Habrahabr.ru