Memcached установка · 6 min read · Jan 20, 2026

Как установить Memcached с помощью repcached "встроенной серверной репликации" на Debian Lenny

Как установить Memcached с помощью repcached “встроенной серверной репликации” на Debian Lenny

Люди, вероятно, знают о memcached (http://memcached.org/) и его высокопроизводительном интерфейсе кэширования объектов в памяти на основе пар “имя-значение”. Его основная цель - предоставить простой в использовании распределенный кэширующий движок в многонодовой среде. Вы когда-нибудь хотели, чтобы memcached обрабатывал репликацию?

Если вы хотите добавить возможности высокой доступности, вам рекомендуется позволить клиенту (-библиотеке) обрабатывать репликацию ваших данных по всем узлам. Допустим, использование memcached в качестве бэкенда для хранения php-сессий настроено следующим образом:

# конфигурация для модуля php memcache
extension=memcache.so
session.save_handler = memcache
session.save_path = "tcp://192.168.168.61:11211?persistent=1,tcp://192.168.168.62:11211?persistent=1"

Теперь сессии распределяются (не реплицируются) между обоими узлами. Как только один узел выходит из строя, вы потеряете все эти данные. Пока вы используете memcached только как ускоритель производительности и распределитель некоторых “кэшируемых” данных, это не должно повредить: потерянные данные заполняются так же, как они были созданы при создании записей кэша.

Чтобы реплицировать ваши данные сессий, вам нужно будет использовать пользовательский обработчик сессий, который подключается к каждому из этих узлов самостоятельно… для репликации. То же самое, если вы хотите записать некоторые собственные кэшированные объекты в ваш любимый memcached. Тем не менее, ваше приложение должно знать обо всех узлах, к которым нужно записывать.

Упрощение репликации, позволяя memcached справляться с этим как repcached

Эти проблемы могут сбивать с толку разработчиков, которые просто хотят сосредоточиться на своем приложении и не хотят слишком беспокоиться о высокой доступности, балансировке нагрузки и масштабируемости. С помощью repcached, по крайней мере, можно легко и прозрачно настроить решение высокой доступности с 2 узлами.

Простой патч добавляет модную репликацию мастер-мастер к вашему memcached. Теперь вам нужно только подключиться к вашему локальному memcached, который затем самостоятельно обрабатывает репликацию.

Таким образом, ваше приложение может оставаться простым и понятным, используя вашу локальную файловую систему POSIX (которая может быть реплицирована с помощью DRBD, GlusterFS и т. д.), вашу локальную базу данных (вы угадали: “которая обрабатывает репликацию самостоятельно”) и подключаясь к локальному экземпляру вашего “кластера memcached”. Эта настройка открывает некоторые более простые и прозрачные варианты для легкой и легковесной масштабируемости высокой доступности.

Установка, конфигурация и тестирование кластера из 2 узлов

Сначала получите копию патча repcached или даже загрузите предварительно запатченный исходный код memcached с http://repcached.lab.klab.org/. Существует зависимость от libevent, которую может потребоваться разрешить перед установкой.

root@ha-01 ~ # apt-get install libevent-dev

Теперь распакуйте и перейдите в директорию:

root@ha-01 ~ # tar xvf memcached-1.2.8-repcached-2.2.tar
root@ha-01 ~ # cd memcached-1.2.8-repcached-2.2/

Настройте с параметром –enable-repcached.

root@ha-01 ~/memcached-1.2.8-repcached-2.2 # ./configure –enable-replication
root@ha-01 ~/memcached-1.2.8-repcached-2.2 # make
root@ha-01 ~/memcached-1.2.8-repcached-2.2 # make install

Не беспокойтесь слишком сильно о ранее установленном пакете memcached.dep. Эта ручная установка просто установит бинарный файл в /usr/local/bin/memcached, оставив ваш “оригинальный” memcached нетронутым в /usr/bin/memcached.

В отличие от пакета debian, вы можете предоставить параметры командной строки, используя простую конфигурацию по умолчанию в /etc/default/memcachedrep (rep => ‘репликация’), т.е.:

конфигурация по умолчанию

## дополнительные параметры командной строки для запуска memcached в режиме репликации
# -x < ip_addr > имя хоста или IP-адрес сервера мастер-репликации
# -X < num > номер TCP-порта мастера (по умолчанию: 11212)
DAEMON_ARGS="-m 64 -p 11211 -u root -P /var/run/memcachedrep.pid -d -x 192.168.168.2"

С этим на месте, скрипт инициализации настраивается довольно легко, используя и модифицируя скелет debian:

скрипт инициализации

#! /bin/sh
### BEGIN INIT INFO
# Provides:             memcached
# Required-Start:       $syslog
# Required-Stop:        $syslog
# Should-Start:         $local_fs
# Should-Stop:          $local_fs
# Default-Start:        2 3 4 5
# Default-Stop:         0 1 6
# Short-Description:    memcached - Демон кэширования памяти, реплицированный
# Description:          memcached - Демо кэширования памяти, реплицированный
### END INIT INFO
# Автор: Marcus Spiegel <[email protected]>
#
# Пожалуйста, удалите строки "Автор" выше и замените их
# своим именем, если вы копируете и модифицируете этот скрипт.
# Не "set -e"
# PATH должен включать только /usr/*, если он запускается после скрипта mountnfs.sh
PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="memcachedrep"
NAME=memcached
DAEMON=/usr/local/bin/$NAME
DAEMON_ARGS="--options args"
PIDFILE=/var/run/memcachedrep.pid
SCRIPTNAME=/etc/init.d/$DESC
VERBOSE="yes"
# Выход, если пакет не установлен
[ -x "$DAEMON" ] || exit 0
# Чтение файла переменных конфигурации, если он присутствует
[ -r /etc/default/$DESC ] && . /etc/default/$DESC
# Загрузка настройки VERBOSE и других переменных rcS
. /lib/init/vars.sh
# Определение функций LSB log_*.
# Зависит от lsb-base (>= 3.0-6), чтобы гарантировать, что этот файл присутствует.
. /lib/lsb/init-functions
#
# Функция, которая запускает демон/службу
#
do_start()
{
    # Возврат
    #   0, если демон был запущен
    #   1, если демон уже работал
    #   2, если демон не может быть запущен
    start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
        || return 1
    start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \
        $DAEMON_ARGS \
        || return 2
    # Добавьте код здесь, если необходимо, который ждет, пока процесс будет готов
    # обрабатывать запросы от служб, запущенных впоследствии, которые зависят
    # от этого. В качестве последнего средства, подождите некоторое время.
}
#
# Функция, которая останавливает демон/службу
#
do_stop()
{
    # Возврат
    #   0, если демон был остановлен
    #   1, если демон уже был остановлен
    #   2, если демон не может быть остановлен
    #   другой, если произошла ошибка
    start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
    RETVAL="$?"
    [ "$RETVAL" = 2 ] && return 2
    # Ждите, пока дети тоже закончат, если это демон, который форкается
    # и если демон запускается только из этого скрипта инициализации.
    # Если вышеуказанные условия не выполнены, добавьте другой код
    # который ждет, пока процесс освободит все ресурсы, которые могут быть
    # необходимы службам, запущенным впоследствии. Последним средством является
    # подождать некоторое время.
    start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
    [ "$?" = 2 ] && return 2
    # Многие демоны не удаляют свои pid-файлы, когда они выходят.
    rm -f $PIDFILE
    return "$RETVAL"
}
#
# Функция, которая отправляет SIGHUP демону/службе
#
do_reload() {
    #
    # Если демон может перезагрузить свою конфигурацию без
    # перезапуска (например, когда ему отправляется SIGHUP),
    # тогда реализуйте это здесь.
    #
    start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
    return 0
}
case "$1" in
  start)
    [ "$VERBOSE" != no ] && log_daemon_msg "Запуск $DESC" "$NAME"
    do_start
    case "$?" in
        0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; 
        2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
    esac
    ;;
  stop)
    [ "$VERBOSE" != no ] && log_daemon_msg "Остановка $DESC" "$NAME"
    do_stop
    case "$?" in
        0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; 
        2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
    esac
    ;;
  #reload|force-reload)
    #
    # Если do_reload() не реализована, то оставьте это закомментированным
    # и оставьте 'force-reload' как псевдоним для 'restart'.
    #
    #log_daemon_msg "Перезагрузка $DESC" "$NAME"
    #do_reload
    #log_end_msg $?
    #;;
  restart|force-reload)
    #
    # Если опция "перезагрузка" реализована, то удалите
    # 'force-reload' как псевдоним
    #
    log_daemon_msg "Перезапуск $DESC" "$NAME"
    do_stop
    case "$?" in
      0|1)
        do_start
        case "$?" in
            0) log_end_msg 0 ;;
            1) log_end_msg 1 ;; # Старый процесс все еще работает
            *) log_end_msg 1 ;; # Не удалось запустить
        esac
        ;;
      *)
        # Не удалось остановить
        log_end_msg 1
        ;;
    esac
    ;;
  *)
    #echo "Использование: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
    echo "Использование: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
    exit 3
    ;;
esac
:

Тестирование

После настройки repcached на обоих узлах вам, вероятно, следует это протестировать. Вы можете подключиться к memcached на каждом узле через telnet:

root@ha-01 ~ # telnet 127.0.0.1 11211

Пытаемся 127.0.0.1…
Подключено к 127.0.0.1.
Символ выхода - ‘^]’.

Теперь выполните команду set, чтобы записать некоторые тестовые значения только на одном узле:

set foo 0 0 3
bar
STORED

перейдите на другой узел, подключитесь и попробуйте прочитать:

root@ha-02 ~ # telnet 127.0.0.1 11211

Пытаемся 127.0.0.1…
Подключено к 127.0.0.1.
Символ выхода - ‘^]’.
get foo
VALUE foo 0 3
bar
END

Попробуйте наоборот и получайте удовольствие! И наконец, отключите один из этих узлов после того, как вы добавили еще несколько значений в память. Рабочий узел все еще отвечает со всеми данными - отлично.

Настоящая интересная часть заключается в том, что как только вы снова запустите недоступный узел, он получит все “потерянные” данные от другого мастера. Попробуйте сами. То же самое произойдет, если вы сейчас отключите другой узел и снова его включите. Даже данные, которые были установлены на одном узле, пока другой узел был отключен, будут добавлены к вновь запущенному узлу после старта.

Эта настройка способна на репликацию только с 2 узлами - пока. Подумайте о создании кластера из 4 узлов с неким RAID10, где репликация и распределение комбинируются… или что-то в этом роде. Ну, по крайней мере, в этой настройке с 2 узлами repcached работает как часы.

Лично я хотел бы попробовать круг из 3 узлов в следующий раз :) (возможно, вместе с heartbeat, чтобы закрыть любые недостатки в этом круге).

Share: X/Twitter LinkedIn

Get new posts in your inbox

No spam. Unsubscribe anytime.