Глава 1. Приступая к Redis

В данной главе мы рассмотрим следующие рецепты:

  • Выгрузку и установку Redis

  • Запуск и останов Redis

  • Подключение к Redis при помощи redis-cli

  • Получение информации сервера

  • Общее понимание Модели событий Redis

  • Общее понимание протокола Redis

Введение

Redis является очень популярной, основанной на работе в оперативной памяти, базы данных ключ- значение с малым весом. Строго говоря, Redis является неким сервером структуры данных, в соответствии с Matt Stancliff (@mattsta), одним из наиболее важных основателей Redis (https://matt.sh/thinking-in-redis-part-one). Сам автор Redis, Salvatore Sanfilippo (@Antirez) вначале назвал её Redis, что является сокращением от REmote DIctionary Server, поскольку Redis естественным образом реализует различные виды структур данных в оперативной памяти и предоставляет различные API для манипуляции этими структуруми данных. Более важно, что Redis поддерживает обработку высокопроизводительных команд, архитектуры Высокой доступности/ масштабирования, а также свойства постоянства данных пока запущена служба хранения данных.

При разработке систем с высокой согласованностью и низкой латентностью, использование Redis становится всё более и более широко распространённым. В 2017 Redis попала в полный рейтинг первых десяти механизмов DB (https://db-engines.com/en/ranking). До этого она доавольно продолжительное время пребывал в топ- рейтинге хранилищ ключ- значение (https://db-engines.com/en/ranking/key-value+store).

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

Загрузка и установка Redis

Redis имеет активное сообщество в GitHub. Было выполнено большое число запросов и переработано с годами, а её автор, Antirez, всегда давал своевременный ответ в общем разделе проблем GitHub. Таким образом, получаемые циклы выпуска Redis очень быстрые. Начиная с самых первых версий, 2.6/ 2.8 до 3.0/ 3.2, которые очень широко применялись, а затем к самой последней версии 4.x, каждый из выпусков Redis предлагал некие существенные улучшения и исправления ошибок. Поэтому наилучшей практикой является использование самой последней версии Redis, если это возможно. В данной книге мы принимаем самую последнюю версию Redit 4.0.1 {Прим. пер.: На момент перевода, конец августа 2018, последней является версия 4.0.11.}

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

Подготовка...

Вы можете отыскать необходимую ссылку загрузки и основные шаги по установке на https://redis.io/download. Если у вас есть желание построить Redis скомпилировав исходный код в Linux/Unix/macOS, в вашей среде понадобятся и сам компилятор gcc, и C Standard Library libc. Если речь заходит обустановке из репозитория ОС, всё что вам понадобится, это подключение к интернету и правильная настройка репозитория.

{Прим. пер.: для желающих ознакомиться с установкой Redis в контейнерах отсылаем к своему переводу Docker для разработчиков Rails Роба Айзенберга, The Pragmatic Programmers, LLC., февраль 2019.}

Как это сделать...

Мы продемонстрируем весь процесс установки с компиляцией Redis в Ubuntu 16.04.2 LTS (Xenial Xerus). Шаги по выгрузке и построению таковы:

  1. Настроим инструменты построения:

    
    $ sudo apt-get install build-essential
     	   
  2. Создадим некий каталог и войдём в него для Redis:

    
    $ mkdir /redis
    $ cd /redis
     	   
  3. После этого выгрузим Redis:

    
    $ wget http://download.redis.io/releases/redis-4.0.1.tar.gz
     	   
  4. Раскроем его и войдем в его каталог:

    
    $ tar zxvf redis-4.0.1.tar.gz
    $ cd redis-4.0.1
     	   
  5. Создадим некий каталог для файла настройки Redis и скопируем в него файл настроек по умолчанию:

    
    $ mkdir /redis/conf
    $ cp redis.conf /redis/conf/
     	   
  6. Выстроим зависимости:

    
    $ cd deps
    $ make hiredis lua jemalloc linenoise
    $ cd ..
     	   
    [Совет]Совет

    Из- за различий между разнообразными операционными системами и установленными в них библиотеками, определённые перечисленные выше шаги потребуются если возникающие ошибки указывающие на неудовлетворительность неких зависимостей. К примеру, вы можете столкнуться со следующим сообщением об ошибке:

    
    zmalloc.h:50:31: fatal error: jemalloc/jemalloc.h: No such file or directory.
     	   

    Этот шаг не является обязательным для большинства сред, если в зависимостях не происходит ничего предосудительного.

  7. Выполните компиляцию:

    
    $ make
     	   

    Если всё пройдёт успешно, будет отображено приводимое ниже сообщение. Оно означает, что процесс компиляции был успешно завершён:

    
    It's a good idea to run 'make test' ;)
    make[1]: Leaving directory '/redis/redis-4.0.1/src'
     	   
  8. Установите Redis:

    
    $ make PREFIX=/redis install
     	   

    Приводимые далее сообщения представляют полный успех установки:

     

    Рисунок 1-1



  9. Войдите в каталог /redis и убедитесь что необходимые двоичные файды Redis были сгенерированы:

    
    $ ls /redis/bin
    redis-benchmark redis-check-aof redis-check-rdb redis-cli redis-sentinel redis-server
     	   

Наши поздравления! Вы выполнили установку Redis путём компиляции.

В сопоставлении с пройденной установкой компиляцией, применение apt-get в Ubuntu для установки Redis намного проще. Давайте посмотрим:

  1. Для начала обновим индекс репозитория программного обеспечения:

    
    $ sudo apt-get update
     	   
  2. А затем запустим установку:

    
    $ sudo apt-get install redis-server
     	   
  3. Когда она завершится, проверим что Redis был установлен в вашей среде:

    
    $ which redis-server
     	   

Как это работает...

Когда дело доходит до выбора необходимой версии Redis, держите в уме, что Redis следует установленной стандартной практике ведения версий, которой является главная.вспомогательная.исправление. Некое чётное значение вспомогательного значения версии устанавливается для стабильной версии, в то время как нечётные вспомогательные значения относятся к нестабильным версиям, хотя и существует несколько версий для Redis с нечётными вспомогательными значениями.

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

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

Таблица 1-1.
Название файла Описание Замечания

redis-server

Сервер Redis

 

redis-sentinel

Redis Sentinel

Мягкая (soft) ссылка для redis-server

redis-cli

Инструментарий консоли Redis

 

redis-check-rdb

Инструмент проверки RDB Redis

 

redis-check-aof

Инструмент проверки AOF (Append Only Files) Redis

 

redis-benchmark

Инструментарий эталонного тестирования Redis

 

Также ознакомьтесь...

Для Windows вы можете получить редакцию Windows Redis, которую группа Microsoft Open Technologies применяла для сопровождения в https://github.com/MicrosoftArchive/redis/releases.

Просто выгрузите имеющийся исполняемый файл .msi и кликните по нему дважды для установки, оставив настройки по умолчанию.

Для macOS нет большой разницы в сравнении с приведённой процедурой для Linux. Вы можете установить Redis, запустив в macOS команду brew install redis.

Дополнительно

  • Для ознакомления с воздействием различных вариантов компиляции на производительности отсылаем вас к оценкам производительности для различных версий Matt Stancliff при применении различных опций компиляции.

  • Исходя из причин безопасности, для Redis следует применять пользователя, не являющегося root, подробнее мы рассматриваем это в рецепте безопасности в Главе 8, Развёртывание промышленной среды

  • Для получения дополнительной информации вы может обратиться к https://github.com/antirez/redis

Запуск и останов Redis

Прежде чем выполнять доступ к Redis, его Сервер Redis должен быть запущен надлежащим образом. Аналогично, при определённых обстоятельствах, вам придётся останавливать свою службу Redis. Данный рецепт покажет вам как запускать и останавливать Сервере Redis.

Подготовка...

Вам требуется завершить установку своего Сервера Redis, как это было описано в рецепте Загрузка и установка Redis данной главы.

Как это сделать...

Необходимые этапы для запуска и останова Сервера Redis таковы:

  1. Вы можете запустить некий Сервер Redis с настройками по умолчанию:

    
    $ bin/redis-server
     	   

    Ваш сервер теперь должен запуститься как это показано на следующем снимке экрана:

     

    Рисунок 1-2



  2. Чтобы запустить некий Сервер Redeis при помощи какого- то файла настроек, такого как тот, что мы скопировали из своего исходного пакета кода в своём рецепте установки, наберите следующее:

    
    $ bin/redis-server conf/redis.conf
     	   
  3. Если вы установили Redis из определённого репозитория некоторой операционной системы, вы можете запустить Redis при помощи сценария init.d:

    
    $ /etc/init.d/redis-server start
     	   
  4. Для запуска redis-server в качестве демона в фоновом режиме при запуске, вы можете изменить свой файл настроек и кстановить значение параметра daemonize в yes и запустить с данной конфигурацией:

    
    $ vim conf/redis.conf
    daemonize yes
    $ bin/redis-server conf/redis.conf
     	   

    Получаемое сообщение Configuration loaded, отображаемое на приводимом ниже снимке экрана указывает, что данная настройка уже применена:

     

    Рисунок 1-3



  5. Соответственно, вы можете воспользоваться Ctrl + C (если Redis запущен в приоритетном режиме), или примените Kill + PID (если Redis запущен в фоновом режиме) чтобы остановить определённую службу Redis:

    
    $ kill `pidof redis-server`
     	   
  6. Более аккуратный и рекомендуемый способ для остановки Redis состоит в вызове конкретной команды останова в redis-cli:

    
    $ cd /redis
    $ bin/redis-cli shutdown
     	   
  7. Redis может также быть остановлен самим сценарием init.d, в случае когда вы установили его из определённого репозитория вашей операционной системы:

    
    $ /etc/init.d/redis-server stop
     	   

Как это работает...

Применяемый термин экземпляр (instance) в Redis представлен неким процессом redis-server. В одном и том же хосте может запускаться множество экземпляров Redis, пока они применяют различные настройки, например, различные порты связывания, пути постоянных данных, пути журналов и тому подобное.

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

Основная причина зачем настоятельно рекомендуется применять команду shutdown для остановки Redis состоит в том, что если вы заботитесь в целостности данных и уже имеете постоянный набор для сохранения Redis ваших данных в оперативной памяти на диск (механизм постоянности Redis будет обсуждаться в Главе 6, Постоянство), выполняя соответствующую команду shutdown не только для завершения определённого процесса, но также предпринимать некую последовательность прочих действий.

Во- первых, сам redis-server остановит всех своих клиентов, а затем будет выполнено одно постоянное действие если было включено Постоянство. После этого он очистит имеющиися файл .pid и файл socket, если они имеются и, наконец, выйти из этого процесса. Адаптируя данную стратегию, Redis предпринимает всё возможное для предотвращения утраты любых данных. И наоборот, если г рубо применяется команда kill для прекращения запущенного процесса redis-server, данные могут теряться, поскольку они не становятся постоянными до того как этот сервер остановлен.

Следует заметить что применение kill или иных инструментов управления процессами для отправки некоторого сигнала SIGTERM (сигнала 15) в запущенный процесс Redis в своей основе эквивалентен рассматриваемой команде shutdown для аккуратного останова запущенного redis-server.

Также ознакомьтесь...

При запуске самой команды redis-server можно добавлять параметры настройки, что достаточно удобно при развёртывании множества экземпляров в некотором отдельном хосте. Мы можем иметь некий отдельный файл настроек, используемый множеством экземпляров в одном и том же хосте. Тем временем, необходимые уникальные параметры настройки каждого экземпляра могут передаваться в командной строке при запуске. Таким образом, мы избавляемся от стоимости сопровождения множества файлов настройки, а экземпляры могут легко различаться через ps или иные системные команды.

Кроме того, вы можете управлять своим экземпляром Redis используя инструменты управления процессами, такими как systemd, supervisord или Monit, которые могут также могут избавлять вас от беспорядка при развёртывании ножества экземпляров некотором отдельном хосте. Всё что нам требуется, это уделять внимание своим упомянутым ранее параметрам настройки запуска и механизмам обработки сигналов выхода.

Дополнительно

  • Для получения дополнительных сведений о том как Redis обрабатывает различные виды сигналов обратитесь к https://redis.io/topics/signals, в особенности в обнаружении небольших, но существенных отличий между этими механизмами обработки сигналов. Кроме того, для более глубокого знакомства с аккуратным остановом экземпляра Redis обратитесь к https://redis.io/commands/shutdown

  • https://git.io/v5chR выступает неким примером настройки Сервера Redis systemd в качестве инструмента управления процессом при управлении запуском/ остановом Redis.

  • Более того, вы можете обратиться к Главе 6, Постоянство относительно неизменности Redis.

Подключение к Redis посредством redis-cli

При разработке и сопровождении Redis redis-cli в каталоге bin является наиболее часто применяемым инструментом. Данный раздел предоставляет его краткое описание с тем,чтобы читатель смог получить лаконичное представление того как подключаться к Redis и применять его с помощью redis-cli.

Подготовка...

Вам требуется поднятый и исполняющийся Сервер Redis, согласно нашему описанию в рецепте Запуск и останов Redis этой главы.

Как это сделать...

Для подключения к Redis при помощи redis-cli применяется следующая последовательность шагов:

  1. Откройте Терминал и подключитесь к редис с помощью redis-cli:

    
    $ bin/redis-cli
    127.0.0.1:6379>
     	   

    Шаблоном предыдущего приглашения является IP:port, что указывает на то, что redis-cli успешно подключился к данному экземпляру Redis.

  2. Для проверки отправим несколько простых команд. В последующих главах мы обсудим дополнительные типы данных и функции.

  3. Для начала установим две строковые пары ключ- значение, foo value1 и bar value2:

    
    127.0.0.1:6379> set foo value1
    OK
    127.0.0.1:6379> set bar value2
    OK
     	   
  4. После этого выполним выборку только что установленных нами значений:

    
    127.0.0.1:6379> get foo
    "value1"
    127.0.0.1:6379> get bar
    "value2"
     	   
  5. Наконец, мы прекратим выполнение Redis, отправив соответствующую команду shutdown:

    
    $ bin/redis-cli
    127.0.0.1:6379> shutdown
    not connected>
     	   
  6. После останова наше приглашение Командной строки изменилось на not connected. Затем мы покидаем redis-cli и выполняем подключение к redis-cli вновь. Будет отображено следующее сообщение:

    
    not connected>quit
    $ bin/redis-cli
    Could not connect to Redis at 127.0.0.1:6379: Connection refused
    Could not connect to Redis at 127.0.0.1:6379: Connection refused
    not connected>
     	   

Как это работает...

По умолчанию redis-cli подключается к некоторому экземпляру Redis запущенному на локальном хосте с портом по умолчанию 6379. Вы также можете определить значение имени хоста/ IP адреса соответствующего Сервера Redis, запуская команду с параметром -h. Просто убедитесь что имеется подключение между вашей стороной redis-cli и стороной самого Сервера Redis и в нём нет проблем.

redis-cli позволяет определять вам порт при помощи параметра -p в случае, когда ваш Сервер Redis не запущен с портом по умолчанию 6379. Этот параметр таже полезен когда вы желаете выполнять подключение с множеством экземпляров Redis с различными портами привязки в одном и том же хосте.

Кроме того, некий экземпляр Redis защищается при помощи пароля, для установки пароля при подключении к Redis моежет применяться соответствующий параметр -a.

Кроме того, если в Redis доступен некий файл socket, вы можете просто подключаться к Серверу Redis с применением параметра -a.

Также ознакомьтесь...

Зачастую имеется некая потребность выполнения проверки какого- то прототипирования прежде чем прицеплять ваше приложение к Redis. Для этого очень полезным инструментом является redis-cli. Он предоставляет некий интерфейс командной строки с тем, чтобы вы могли быстро проверить архитектуру своих данных. Для повседневного сопровождения Сервера Redis redis-cli также предоставляет некое множество команд, в том числе получение соответствующих замеров, манипулирование состояниями системы и установкой настроек производительности.

Дополнительно

Получение информации о сервере

При помощи команды INFO redis-cli может быть получена наиболее всеобъемлющая и важная информация об экземпляре Redis. В данном разделе мы рассмотрим как применять команду INFO для выборки таких существенных статистических данных.

Подготовка...

Вам требуется поднятый и исполняющийся Сервер Redis, согласно нашему описанию в рецепте Запуск и останов Redis этой главы.

Как это сделать...

Для получения информации о Redis придерживайтесь следующих шагов:

  1. Подключитесь к некому экземпляру Redis и затем воспользуйтесь командой INFO:

    
    $ bin/redis-cli
    127.0.0.1:6379> INFO
     	   

    Получаемые результаты выглядят следующим образом:

    
    # Server
    redis_version:4.0.1
    ...
    # Clients
    connected_clients:1
    ...
    # Memory
    used_memory:828352
    used_memory_human:808.94K
    used_memory_rss:9420800
    used_memory_rss_human:8.98M
    ...
    # Persistence
    loading:0
    rdb_changes_since_last_save:0
    rdb_bgsave_in_progress:0
    rdb_last_save_time:1504223311
    ...
    # Stats
    total_connections_received:1
    total_commands_processed:1
    instantaneous_ops_per_sec:0
    ...
    # Replication
    role:master
    connected_slaves:0
    ...
    # CPU
    used_cpu_sys:0.01
    used_cpu_user:0.00
    ...
    # Cluster
    cluster_enabled:0
     	   
  2. Вы можете выбирать определённый раздел, добавляя некий необязательный параметр <section>. Например, мы получаем измерения памяти отправляя в redis-cli команду INFO memory:

     

    Рисунок 1-4



  3. Другим способом получения информации от экземпляра Redis является применение redis-cli INFO непосредственно в командной строке. Таким образом достаточно удобно организовывать конвейер вывода в некий сценарий для анализа измерений или мониторинга производительности.

Как это работает...

Команда INFO предоставляет вам все текущие измерения Redis и определённый шаблон каждого измерения в виде metric-name: metric-value, с которым в последующем может быть запросто можно выполнить синтаксический разбор.

Приводимая ниже таблица суммирует общие описания каждого раздела, возвращаемого INFO:

Таблица 1-2.
Название раздела Описание

Server

Основная информация о Сервере Redis

Clients

Состояние и измерения соединений клиента

Memory

Измерения общего потребления памяти

Persistence

Состояния и измерения, относящиеся к постоянным данным

Stats

Общие статистические данные

Replication

Состояние и измерения репликации хозяин- подчинённый

CPU

Потребление ЦПУ

Cluster

Состояние Кластера Redis

Keyspace

Статистические данные, относящиеся к базе данных

Также ознакомьтесь...

Построение некоего приложения мониторинга путём получения информации из периодически выполняемой команды INFO является распространённой практикой.

Дополнительно

Общее представление о модели событий Redis

Redis, знаменитый своей высокой производительностью, для быстрой обработки запросов заставляет большинство отдельных потоков придерживаться модели неблокируемого ввода/ вывода. Следовательно, существенным является понимание общей модели событий Redis. В качестве пробного образца для понимания читающим такой модели, данный рецепт вначале показывает некую демо программу echo server, которая строится на библиотеке асинхронных событий Redis (библиотека ae). Затем мы предоставляем важные сущностные моменты имеющейся модели обработки событий Redis анализируя определённый фрагмент исходного кода Redis.

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

Подготовка...

Данный рецепт затрагивает построение и отладку исходного кода. Поэтому вам вначале требуется завершить рецепт Загрузка и установка Redis из этой главы. Для лучшей иллюстрации необходим некие IDE, который поддерживает язык программирования C. Применяемым нами IDE является CLion в Ubuntu Desktop 16.04.3 LTS. Хотя CLion IDE и не является свободно распространяемым, нам будет достаточно 30- дневного пробного срока.

Вам также следует подготовить соответствующий компилятор C и среду разработки. В Ubuntu мы можем воспользоваться следующей командой для установки относящихся к этому пакетов:


$ sudo get update && apt-get install build-essential
		

После установки вам следует убедиться, что CMake имеет версию 3.5 или выше:


$ cmake --version
cmake version 3.5.1
CMake suite maintained and supported by Kitware (kitware.com/cmake).
		

Как это сделать...

Для получения представления о Модели событий Redis выполните следующую последовательность:

  1. Раскройте необходимый пакет исходного кода Redis и постройте некие необходимые зависимости вручную вместо того, чтобы применять CMake:

    
    ~$ mkdir coding; cd coding
    ~/coding$ tar xzvf redis-4.0.1.tar.gz
    ~/coding$ cd redis-4.0.1/deps/
    ~/coding/redis-4.0.1/deps$ make lua linenoise hiredis
     	   

    Приводимый ниже снимок экрана указывает, что все зависимости были построены успешно:

     

    Рисунок 1-5



  2. Выгрузите пакет CLion IDE и раскройте его в каталоге /redis/coding/:

    
    ~/coding$ wget https://download.jetbrains.8686c.com/cpp/CLion-2017.2.2.tar.gz
    ~/coding$ tar zxvf CLion-2017.2.2.tar.gz
     	   
  3. Загрузите наш демонстрационный пакет пакет для построения и отладки redis-server.

  4. Раскройте его в каталоге redis-4.0.1:

    
    ~/coding$ tar xzvf echodemo.tar.gz -C redis-4.0.1/
     	   

    Убедитесь что следующие файлы, CMakeLists.txt и echodemo присутствуют в каталоге redis-4.0.1:

     

    Рисунок 1-6



  5. Зарегистрируйтесь на своём рабочем столе Ubuntu и откройте Терминал для запуска CLion:

    
    ~/coding/clion-2017.2.2$ bin/clion.sh
     	   
  6. После подтверждения лицензионного соглашения вам следует проверить, что и CMake и отладчик готовы, как это показано ниже:

     

    Рисунок 1-7



  7. Продолжайте с установленными по умолчанию значениями, пока вы не достигните следующего снимка экрана:

     

    Рисунок 1-8



    Кликните по Import Project from Sources и выберите в каталоге coding подкаталог redis-4.0.1.

    Кликните по кнопке OK button, а затем выберите Open Project чтобы открыть проект Redis.

  8. Выберите соотвествующую конфигурацию Build All из своего верхнего правого угла и кликните по кнопке Run:

     

    Рисунок 1-9



    Проигнорируйте появившуюся ошибку того, что не определена некая исполняемая цель, и кликните Run.

    Следующие регистрационные записи отобразят что вы управляли построением и демонстрационной программы echo-server/client, и redis-server (в данном примере my-redis-server):

    
    /redis/coding/clion-2017.2.2/bin/cmake/bin/cmake --build
    /redis/coding/redis-4.0.1/cmake-build-debug --target all -- -j 6
    Scanning dependencies of target ae
    Scanning dependencies of target my-redis-server
    [ 1%] Building C object CMakeFiles/ae.dir/src/zmalloc.c.o
    ...
    [ 17%] Building C object CMakeFiles/my-redis-server.dir/src/blocked.c.o
    Scanning dependencies of target echo-server
    ...
    [ 25%] Built target echo-server
    [ 26%] Building C object CMakeFiles/my-redis-server.dir/src/config.c.o
    ...
    [ 31%] Building C object CMakeFiles/my-redis-server.dir/src/defrag.c.o
    [ 32%] Linking C executable echo-client
    [ 32%] Built target echo-client
    [ 98%] Building C object CMakeFiles/my-redis-server.dir/src/zmalloc.c.o
    [100%] Linking C executable my-redis-server
    [100%] Built target my-redis-server
     	   
  9. В том случае,если вы в первую очередь желаете использовать командную строку для компиляции демонстраций, вы можете выполнить следующие шаги:

    
    /redis/coding/redis-4.0.1$ cmake
    -- The C compiler identification is GNU 5.4.0
    ...
    -- Configuring done
    -- Generating done
    -- Build files have been written to: /redis/coding/redis-4.0.1
    /redis/coding/redis-4.0.1$ make
    Scanning dependencies of target my-redis-server
    [ 1%] Building C object CMakeFiles/my-redis-server.dir/src/adlist.c.o
    [ 2%] Building C object CMakeFiles/my-redis-server.dir/src/ae.c.o
    ...
    [ 85%] Building C object CMakeFiles/my-redis-server.dir/src/zmalloc.c.o
    [ 86%] Linking C executable my-redis-server
    [ 86%] Built target my-redis-server
    Scanning dependencies of target ae
    ...
    [ 92%] Built target ae
    Scanning dependencies of target echo-server
    ...
    [ 96%] Built target echo-server
    Scanning dependencies of target echo-client
    ...
    [100%] Built target echo-client
     	   
  10. В каталоге cmake-build-debug под redis-4.0.1 вы можете обнаружить echo-server, echo-client и my-redis-server:

     

    Рисунок 1-10



    В правом верхнем углу выберите конфигурацию echo-server и кликните по кнопке правой стрелки для её исполнения:

     

    Рисунок 1-11



  11. Откройте некий Терминал и затем подключитесь к echo-server при помощи nc (Netcat):

    
    ~/coding/redis-4.0.1/cmake-build-debug$ nc 127.0.0.1 8000
    		
  12. В случае, когда ваш сервер стартовал успешно, будет отображено сообщение Hello Client!:

     

    Рисунок 1-12



    Вот регистрационные записи данного подключения:

     

    Рисунок 1-13



  13. В nc наберите Hello, please echo! и нажмите на Enter для отправки текста. То же самое сообщение должно вернуться к вам эхом:

     

    Рисунок 1-14



    На стороне сервера будут зарегистрированы те данные, которые были отосланы обратно к клиенту позднее:

     

    Рисунок 1-15



  14. Откройте другой Терминал и осуществите другое подключение к своему echo-server. Аналогичный результат будет получен и на стороне nc, и на стороне сервера, что отображено на приводимом ниже снимке экрана:

     

    Рисунок 1-16



  15. Вы можете выполнять отладку этого сервера по своему желанию:

     

    Рисунок 1-17



  16. Для более глубокого погружения в исходный код вы можете построить и отладить сервер redis-server (именуемый в данном примере my-redis-server) почти тем же самым способом, что и в нашем примере echo-server. Единственный момент,который вам следует изменить, это выбрать my-redis-server в профиле конфигурации run/debug:

     

    Рисунок 1-18



Как это работает...

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

Redis содержит в себе простую, но мощную библиотеку асинхронных событий, именуемую ae для обёртывания функций опроса различных операционых систем, таких как epoll, kqueue, select и тому подобных. {Прим. пер.: подробнее, например, в нашем переводе главы API Epoll из руководства Микаэля Керниска "Интерфейс программирования Linux".}

Итак, что такое функциональность опроса в некоторой операционной системе? Для иллюстрации этого давайте воспользуемся примером из реальной жизни. Представим себе,что вы заказали пять блюд в некотором ресторане. Вам придётся получать свои блюда самостоятельно в каком- то окне ожидания, причём вы желаете получать их настолько быстро, насколько это возможно, как только эти блюда будут готовы, так как вы очень голодны. При таком развитии событию у вас имеются три стратегии:

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

  • Вы нанимаете пятерых людей. каждый из них подходит к окну выдачи для проверки того, что одно из блюд по вашему списку приготовлено.

  • Вы просто сидите за столом, ожидая соответствующего уведомления. Специально обученный уведомлению о готовности член службы ресторана сделает вам уведомление, что означает, что официант сообщит вам какое из блюд готово, как только оно будет приготовлено. Как только вы получаете такое уведомление, вы получаете блюдо самостоятельно.

Принимая во внимание те время и усилия, которые они потребуют, очевидно, что третий вариант является наилучшим.

Функциональность опроса (polling) аналогично тому, как это делается в третьем варианте. Для упрощения данного раздела в качестве примера мы рассмотрим только метод epoll API Linux. Вначале вы можете вызвать epoll_create чтобы сообщить своему ядру, что вы желаете применять epoll. Затем вы вызываете epoll_ctl для информирования своего ядра о необходимых файловых дескрипторах (FD) и о том, какой тип события вас интересует, когда произойдёт некое обновление. После этого epoll_wait выполняет вызов ожидания определённого события с тем FD, который вы назначили в epoll_ctl. Само ядро отправит вам некое уведомление при обновлении вашего FD. Единстенный момент, который вам следует осуществить, это создать обработчики для определённых событий.

Весь процесс мультиплексирования целиком выглядит следующим образом:

 

Рисунок 1-19


Модель мультиплекирования ввода/ вывода

В целом, имеющаяся в Redis библиотека ae при обработке всех запросов следует приведённой выше процедуре. В своём примере echo-server мы создаём некий цикл событий вызывая вначале aeCreateEventLoop. Затем посредством anetTcpServer строится какой- то сервер TCP для привязки к сетевой среде и организации процесса ожидания. Для настройки некоторого неблокируемого действия в данном FD сокета мы делаем вызов anetNonBlock. После этого мы определяем соответствующий обработчик события acceptProc для данного FD сокета при помощи того цикла событий, который создан в aeCreateEventLoop. Когда соединение TCP установлено, наш сервер переключит своё действие в acceptProc. В acceptProc мы применяем anetTcpAccept для приёма соответствующего запроса на подключение и регистрации событий считывания с данного FD сокета для readProc. Затем readProc получает вызов, в котором мы считываем те данные, которые отправлены в наш сервер и регистрируем соответствующее событие для записи в свой FD сокета. Наш цикл событий затем получает соответствующее событие записи чтобы зажечь необходимый writeProc для отправки полученных данных обратно в сокет клиента.

Redis работает во многом аналогично тому, как это делает echo-server. В функции main server.cв соответствующем методе initServer для инициализации нашего сервера вызываются aeCreateEventLoop, anetTcpServer и anetNonBlock:

 

Рисунок 1-20



Соответствующий обработчик приёма также устанавливается в этом методе initServer, как это показано в следующем снимке экрана:

 

Рисунок 1-21



После того как наш сервер установлен, получает вызов соответствующий метод aeMain:

 

Рисунок 1-22



Для непрерывной обработки возникающих событий в нашем методе aeMain вызывается asProcessEvents:

 

Рисунок 1-23



Также ознакомьтесь...

Ясно, что в данном процессе опроса не порождается ни какой поток или подчинённый процесс и не выполняется никакое взаимодействие. Таким образом, основным ключевым преимуществом данной модели является то, что она выступает яркой моделью контекстного переключения ввода/ вывода, поэтому переключение контекста не является затратным. Для данной модели следует рассматривать ряд ограничений. Наиболее распространённой проблемой, с которой вы можете сталкиваться является проблема задержек. В данной модели опроса Redis не будет обрабатывать никакие иные команды, пока не завершится обрабатываемая. Поэтому, начиная с данного момента держите на уме, что некая неожиданная латентность будет самой первой головной болью для вас при использовании Redis.

Прочие методы опроса, такие как poll, select и тому подобные, не обсуждаются здесь в силу их ограниченной применимости. Если вы работаете с иными нежели Linux платформами, вы можете пройти отладку соответствующего исходного кода с тем, чтобы дополнительно изучить возможности опроса в этой платформе.

Дополнительно

Общее представление о протоколе Redis

Как мы уже обсуждали в нашем предыдущем рецепте, Radis всего навсего некий TCP сервер неблокируемого ввода/ вывода с мулитиплексированием, которые принимает от клиентов запросы и обрабатывает их. Другими словами, несмотря на сложность организации самого Сервера Redis, вы можете общаться с Rdeis поверх подключения TCP на различных языках программирования. Термин протокол применяется для того языка, который применяется между некими сервером и клиентом при сетевом взаимодействии. Что касается Redis, таким протоколом является RESP (REdis Serialization Protocol). В данном рецепте мы рассмотрим как RESP работает в Redis.

Стоит отметить один момент: Даже на первый взгляд слегка самонадеянно для новичков ознакомиться с данным рецептом. Однако мы на самом деле полагаем, что изучение основ RESP, на базовом уровне, не настолько сложно и сулит для вас преимущества в таком понимании в таком понимании различных видов клиентов и посредников (прокси), реализуемых в разнообразных языках программирования, которое больше не будет представлять для вас мистики.

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

{Прим. пер.: на самом деле, Redis не обязан ограничиваться исключительно протоколом TCP/IP, он прекрасно может быть реализован, например, поверх RDMA, см. например Using RDMA Efficiently for Key-Value Services Anuj Kalia, Michael Kaminsky, David G. Andersen, CMU, 2014; Accelerating Redis with RDMA Over InfiniBand Wenhui Tang, Yutong Lu, Nong Xiao, Fang Liu, Zhiguang Chen, DMBD 2017. или обратитесь к нам относительно применения RDMA over Ангара.}

Подготовка...

Вам требуется поднятый и исполняющийся Сервер Redis, согласно нашему описанию в рецепте Запуск и останов Redis этой главы.

Должен быть установлен необходимый инструмент, netcat (nc). В этом рецепте у нас есть команды для nc в Ubuntu 16.04.3 LTS для netcat. Если вы работаете под Windows, вы можете воспользоваться Cygwin для установки netcat.

Как это сделать...

Для знакомства с протоколом Redis сделайте следующие шаги:

  1. При помощи netcat отправьте в свой Сервер Redis командуPING.

    Вместо отправки команды PING в redis-cli, давайте построим соответствующую команду при помощи RESP:

    
    $ echo -e "*1\r\n\$4\r\nPING\r\n" | nc 127.0.0.1 6379
    +PONG
     	   
  2. Для установки целого значения и уго приращения на единицу воспользуйтесь командами SET и INCR:

    
    $ echo -e "*3\r\n\$3\r\nset\r\n\$5\r\nmykey\r\n\$1\r\n1\r\n" | nc 127.0.0.1 6379
    +OK
    $ echo -e "*2\r\n\$4\r\nINCR\r\n\$5\r\nmykey\r\n" | nc 127.0.0.1 6379:2
     	   

    При отправке не существующей команды вы можете столкнуться со следующей ошибкой:

    
    $ echo -e "*2\r\n\$3\r\ngot\r\n\$3\r\nfoo\r\n" | nc 127.0.0.1 6379
    -ERR unknown command 'got'
     	   

    Можно комбинировать несколько команд и отправлять их в свой Сервер Redis в единой сетевой передаче:

    
    $ echo -e "*3\r\n\$3\r\nset\r\n\$3\r\nfoo\r\n\$3\r\nbar\r\n*2\r\n\$3\r\nget\r\n\$3\r\nfoo\r\n" | nc 127.0.0.1 6379
    +OK
    $3
    bar
     	   

Как это работает...

Имеется большая вероятность, что ознакомившись с этими командами , вы испытаете большое смятение. Как мы уже постулировали в разделе предисловии этого рецепта, эти команды являются тем языком, на котором Сервер Redis и клиент общаются друг с другом. Вам будет просто изучить его, так как в RESP имеется всего пять типов.

Давайте рассмотрим все команды.

Вначале мы отправляем в свой Сервер Redis *1\r\n\$4\r\nPING\r\n. Данная команда начинается со звёздочки, которая означает, что она представляет тип массива.

Рассмотрим по очереди:

  • 1 устанавливает размер данного массива.

  • \r\n (CRLF) является необходимым терминатором для каждой части в RESP.

  • Знак косой черты перед $4 является экранирующим символом для идущего следом символа $. $4 сообщает, что вслед за ним следует пакет строкового типа длиной в четыре символа.

  • PING является собственно этой строкой.

  • +PONG является той строкой, которую возвращает команда PING.

Следующий тип, о котором мы поговорим, это соответствующий тип целых. Взгляните на :2, что является результатом, возвращаемым командой INCR. Установленное перед самим численным значением двоеточие указывает на то, что это некое целое значение.

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

Кроме того, из соображений производительности вы можете отправлять при помощи RESP множество команд в отдельном вызове в Сервер Redis.

Суммируя, ваш клиент отправляет в некий Сервер Redis команды как массив кипы строк. Затем сервер отвечает соответствующим образом одним из пяти упомянутых выше типов RESP.

Дополнительно

  • Для получения дополнительных подробностей о протоколе RESP обратитесь к https://redis.io/topics/protocol .

  • Различные виды клиентов и посредников можно получить в GitHub. Например, для Java Netty реализации RESP вы можете обратиться к https://github.com/tonivade/resp-server.