MongoDB Sharded Cluster на Centos 6.5
В этой статье мы рассмотрим только конфигурацию MongoDB, не затрагивая вопросы подключения репозитория монги и установки пакетов в систему.Распределенный кластер MongoDB состоит из следующих компонентов:
ШардШард — это инстанс mongod, который хранит часть данных шардированной коллекции. Для использования в production, каждый шард должен быть набором реплик (replicaSet).
Сервер конфигурацийТак же экземпляр mongod, который хранит метаданные кластера. Метаданные указывают какие данные хранятся на каком шарде.
Сервер маршрутизацииЭкземпляр mongos. Его задача — маршрутизация запросов от приложений к шардам.Ниже приведена схема работы шардированного кластера MongoDB
Удобнее всего необходимые роли группировать следующим образом:
Сервер конфигурации + сервер маршрутизации Шард Допустим, для создания этих ролей мы имеем 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=
# 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=
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: про ошибки и не точности просьба писать в личку,