Управление репликами и клиентами в Redis

Redis – это открытое in-memory хранилище типа «ключ-значение». Одна из наиболее востребованных функций в Redis – поддержка репликации: любой сервер Redis может копировать свои данные на любое количество реплик, что обеспечивает высокую масштабируемость при чтении и высокую избыточность данных. Кроме того, Redis изначально разработан для поддержки большого количества клиентов (по умолчанию до 10000). Клиенты могут подключаться и взаимодействовать с данными, что делает Redis хорошим вариантом для тех случаев, в которых многим пользователям необходим доступ к одному и тому же набору данных.

В этом мануале мы рассмотрим команды для управления клиентами и репликами Redis.

Как работать с этим мануалом

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

Команды, использованные в этом мануале, были протестированы на сервере Ubuntu 18.04 и экземпляре Redis версии 4.0.9. Чтобы настроить аналогичную среду, вы можете следовать разделу 1 руководства Установка и защита Redis в Ubuntu 18.04. Мы покажем, как эти ведут себя команды в redis-cli, интерфейсе командной строки Redis. Обратите внимание, что если вы используете другой интерфейс Redis — например, Redli – то вывод некоторых команд будет отличаться.

Примечание: В документации Redis используются понятия «master» и «slave» серверов. В данном мануале мы будем называть их ведущим и ведомым сервером (или репликой) соответственно.

1: Управление репликами

Одна из отличительных особенностей Redis – встроенная репликация. При этом Redis создает точные копии данных с основного экземпляра. Вторичные экземпляры будут повторно подключаться к первичному, когда их соединения прервутся. Они всегда будут стремиться оставаться как можно более точной копией первичного экземпляра.

Если вы не знаете, какую роль играет экземпляр Redis, к которому вы в данный момент подключен, вы можете проверить это с помощью команды role:

role

Эта команда вернет master или slave (либо sentinel, если вы используете Redis Sentinel).

Чтобы настроить экземпляр Redis в качестве реплики другого экземпляра, выполните команду replicaof. Эта команда принимает в качестве аргументов имя хоста или IP-адрес и порт предполагаемого ведущего сервера:

replicaof hostname_or_IP port

Если сервер уже является репликой другого ведущего сервера, он прекратит реплицировать данные старого сервера и немедленно начнет синхронизацию с новым. Также он сбросит старый набор данных.

Чтобы сделать реплику ведущим сервером, выполните следующую команду replicaof:

replicaof no one

После этого экземпляр перестанет реплицировать данные первичного сервера, но при этом сохранит набор данных, который он уже реплицировал. Этот синтаксис полезен в случаях, когда исходный первичный сервер отказывает. После запуска команды replicaof no one прежняя реплика может использоваться в качестве новой первичной ноды и иметь свои собственные реплики (для отказоустойчивости).

Примечание: До версии 5.0.0 вместо replicaof Redis использовал другую версию этой команды, slaveof.

2: Управление клиентами

Клиент – это любая машина или программное обеспечение, которое подключается к серверу для доступа к сервису. Redis поставляется с несколькими командами, которые помогают отслеживать и управлять клиентскими подключениями.

Команда client list возвращает набор удобочитаемой информации о текущих клиентских подключениях:

client list
"id=18165 addr=[2001:db8:0:0::12]:47460 fd=7 name=jerry age=72756 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=ping
id=18166 addr=[2001:db8:0:1::12]:47466 fd=8 name= age=72755 idle=5 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=info
id=19381 addr=[2001:db8:0:2::12]:54910 fd=9 name= age=9 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=26 qbuf-free=32742 obl=0 oll=0 omem=0 events=r cmd=client
"

Вот что значат эти поля:

  • id: уникальный 64-битный ID клиента.
  • name: имя клиентского соединения, которое определяется командой client setname.
  • addr: адрес и порт, по которому подключается клиент.
  • fd: файловый дескриптор, что отвечает за сокет, по которому подключается клиент.
  • age: общая продолжительность клиентского соединения (в секундах).
  • flags: набор из одного или нескольких односимвольных флагов, которые предоставляют более детальную информацию о клиентах (см. документацию команды client list).
  • db: текущий идентификационный номер базы данных, к которому подключен клиент (от 0 до 15).
  • sub: количество каналов, на которые подписан клиент.
  • psub: количество клиентских подписок, соответствующих шаблону.
  • mutli: количество команд, которые клиент поставил в очередь в транзакции (покажет -1, если клиент не начал транзакцию, или 0, если он только начал транзакцию и не поставил в очередь никаких команд).
  • qbuf: длина буфера запроса клиента, где 0 означает, что ожидающих запросов нет.
  • qbuf-free: количество свободного места в клиентском буфере запросов, где 0 означает, что буфер запросов заполнен.
  • obl: длина выходного буфера клиента.
  • oll: длина выходного списка клиента (ответы помещаются в очередь, когда буфер заполнен).
  • omem: память, используемая выходным буфером клиента.
  • events: события файлового дескриптора клиента (где r значит «readable», w значит «writable»).
  • cmd: последняя команда, запущенная клиентом.

Читайте также: Запуск транзакций в Redis

Установка имен клиентов полезна для отладки утечек соединения в любом приложении, использующем Redis. Каждое новое соединение изначально не имеет имени, но команда client setname может присвоить имя текущему соединению клиента. На длину имен клиентов нет никаких ограничений, хотя Redis обычно ограничивает длину строки до 512 МБ. Обратите внимание, имена клиентов не могут содержать пробелы:

client setname elaine

Чтобы узнать имя клиентского соединения, используйте команду client getname:

client getname
"elaine"

Чтобы узнать идентификатор подключения клиента, используйте команду client id:

client id
(integer) "19492"

Идентификаторы клиентов Redis никогда не повторяются и являются инкрементными. То есть, если идентификатор первого клиента больше, чем второго, то первый был установлен позднее.

3: Блокировка клиентов и закрытие клиентских подключений

Системы репликации обычно делятся на синхронные или асинхронные. При синхронной репликации каждый раз, когда клиент добавляет или изменяет данные, он должен получать от определенного числа реплик подтверждение, чтобы изменение зафиксировалось. Это помогает предотвратить конфликты данных между нодами, но и приводит к задержке, поскольку другие операции должны подождать, пока клиент получит ответ от определенного числа реплик.

При асинхронной репликации клиент убеждается, что операция завершена, как только данные записываются в локальное хранилище. Однако между этим моментом и моментом, когда реплики фактически записывают данные, может быть разрыв. Если одна из реплик выходит из строя до того, как она записала изменение, эта запись будет потеряна навсегда. То есть асинхронная репликация позволяет клиентам продолжать выполнять операции без задержки на ожидание ответов от других реплик, однако это может привести к конфликтам данных между нодами (что, соответственно, потребует дополнительной работы со стороны администратора базы данных для разрешения этих конфликтов).

Из-за своего фокуса на производительности и малой задержке Redis по умолчанию реализует асинхронную репликацию. Однако вы можете симулировать синхронную репликацию с помощью команды wait. Она блокирует текущее клиентское соединение в течение указанного промежутка времени (в миллисекундах), пока все предыдущие команды записи не будут успешно приняты указанным числом реплик. Эта команда использует следующий синтаксис:

wait number_of_replicas number_of_milliseconds

Например, если вы хотите заблокировать клиентское соединение до тех пор, пока все предыдущие записи не будут зарегистрированы как минимум 3 репликами в течение 30 миллисекунд, синтаксис будет выглядеть следующим образом:

wait 3 30

Команда wait возвращает целое число, которое отображает количество реплик, подтвердивших запись (даже если не каждая реплика делает это):

2

Чтобы разблокировать клиентское соединение, которое было ранее заблокировано с помощью команды wait, brpop или xread, вы можете выполнить команду client unblock:

client unblock client_id

Чтобы временно приостановить работу каждого клиента, подключенного в данный момент к серверу Redis, вы можете использовать команду client pause. Она полезна в тех случаях, когда вам нужно внести изменения в настройки Redis контролируемым образом. Например, если вы собираетесь сделать одну из своих реплик ведущим сервером, вы можете заранее приостановить работу каждого клиента, чтобы повысить реплику до ведущего и сделать так, чтобы клиенты подключались к ней с учетом изменений роли, не теряя при этом операций записи.

Команда client pause требует указать количество времени (в миллисекундах), на которое нужно приостановить клиентов. В следующем примере все клиенты будут приостановлены на одну секунду:

client pause 1000

Команда client kill позволяет закрыть одно соединение или набор определенных соединений на основе определенных фильтров. Синтаксис этой команды выглядит так:

client kill filter_1 value_1 ... filter_n value_n

В версиях Redis 2.8.12 и новее доступны следующие фильтры:

  • addr: позволяет закрыть клиентское соединение по указанному IP-адресу и порту
  • client-id: позволяет закрыть клиентское соединение на основе его уникального ID
  • type: закрывает все клиенты указанного типа (normal, master, slave или pubsub).
  • skipme: значениями этого фильтра являются yes и no:
    • если указано значение no, клиент, вызывающий команду kill, не будет пропущен, он будет удален, если к нему применяются другие фильтры.
    • если указано значение yes, клиент будет пропущен, и команда kill не будет влиять на него. skipme всегда имеет значение yes по умолчанию

Заключение

В этом мануале мы подробно рассмотрели ряд команд, используемых для управления клиентами и репликами Redis.

Tags: , , ,