MongoDB Sharded Cluster на Centos 6.5

в 10:05, , рубрики: mongodb, nosql, метки: ,

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

Распределенный кластер MongoDB состоит из следующих компонентов:

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

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

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

MongoDB Sharded Cluster на Centos 6.5

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

  • Сервер конфигурации + сервер маршрутизации
  • Шард

Допустим, для создания этих ролей мы имеем 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=<lo ip>,<eth ip>
configsvr=false

После чего запускаем сервис

# service mongod start

Настройка сервера маршрутизации

Прежде чем переходить к настройке сервера маршрутизации, необходимо убедиться что в системе установлен пакет mongodb-org-mongos

# rpm -qa | grep mongos
mongodb-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=<lo ip>,<eth 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: про ошибки и не точности просьба писать в личку,

Автор: garacio

Источник

Поделиться

* - обязательные к заполнению поля