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=<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: про помилки і не точності прохання писати в личку,
    
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.