Спецификация протокола Redis (перевод)

Java Redis задняя часть сервер

Оригинальный адрес:Блог HaifeiWu
адрес блога:www.hchstudio.cn
Добро пожаловать в перепечатку, пожалуйста, указывайте автора и источник, спасибо!

Клиенты Redis взаимодействуют с серверами Redis, используя протокол RESP (протокол сериализации Redis). Хотя этот протокол разработан для Redis, его можно использовать в качестве протокола связи для других программных проектов CS.

RESP – это рассмотрение следующих аспектов:

  • Легко реализовать
  • Быстрый парсинг
  • высокая читаемость

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

Resp является двоично-безопасным, нет необходимости обрабатывать пакетные данные от одного процесса к другому, поскольку он использует длину префикса для передачи больших объемов данных.

Уведомление:Описанный здесь протокол предназначен только для связи клиент-сервер. Redis Cluster использует разные бинарные протоколы для обмена сообщениями между узлами.

Сетевой уровень

Клиент подключается к серверу Redis, создавая TCP-соединение с портом 6379. Хотя RESP технически не зависит от TCP, в контексте Redis этот протокол используется только для TCP-соединений (или аналогичных потоковых соединений, таких как сокеты Unix).

модель запрос-ответ

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

  • Redis поддерживает трубопровод (описанный позже в этом документе). Следовательно, клиент может пригласить несколько команд одновременно и дождаться ответа позже.
  • Когда клиент Redis Pub/Sub, семантический протокол изменится и станет протоколом push, по которому клиентам больше не нужно отправлять команды, потому что сервер трендов из нижней части клиента, когда они получили команду, отправляет новое сообщение.

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

Описание протокола RESP

Протокол RESP был представлен в Redis 1.2, но стал стандартным способом связи с серверами Redis в Redis 2.0. Это протокол, который должен быть реализован в каждом клиенте Redis.

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

  • Клиент отправляет команду на сервер Redis в виде массива строк.
  • Сервер отвечает данными типа RESP в соответствии с реализацией команды.

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

  • Однострочный ответ: первый байт ответа "+"

  • Сообщение об ошибке: первый байт ответа "-"

  • Целое число: первый байт ответа ":"

  • Многострочная строка: первый байт ответа — «$».

  • Массив: первый байт ответа — «*».

Кроме того, RESP могут представлять значения Null, используя специальные варианты Bulk Strings или Arrays, указанные позже. В RESP разные части протокола всегда заканчиваются на "\r\n" (CRLF).

RESP однострочная строка (простая строка)

Простые строки кодируются следующим образом: символ плюса, за которым следует строка, которая не может содержать символы CR или LF (перевод строки не допускается), завершается символом CRLF (т. е. "\r\n").
Простые строки используются для передачи недвоичных безопасных строк с минимальными издержками. Например, многие команды Redis имеют только «ОК» при успешном ответе, потому что однострочные строки RESP кодируются следующими 5 байтами:

"+OK\r\n"

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

Сообщение об ошибке RESP

Resp имеет ошибочные определенные типы данных. На самом деле ошибка точно такая же, как и в одиночной строке RESP, но первым символом является минус '-' вместо знака плюс.

Настоящая разница между однострочной строкой и ошибкой в ​​RESP заключается в том, что клиент рассматривает ошибку как исключение, а строка, составляющая тип ошибки, является самим сообщением об ошибке. Основной формат следующий:

"-Error message\r\n"

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

Вот пример ответа об ошибке:

-ERR unknown command 'foobar'
-WRONGTYPE Operation against a key holding the wrong kind of value

Первое слово после «-» до первого пробела или новой строки указывает на тип возвращаемой ошибки. Это просто соглашение, используемое Redis, и оно не является частью формата ошибки RESP.

Например, ERR — это общая ошибка, а WRONGTYPE — более конкретная ошибка, означающая, что клиент попытался выполнить операцию с неправильным типом данных. Это называется префиксом ошибки и позволяет клиентам понять тип ошибки, возвращаемой сервером, независимо от точного сообщения, которое может меняться со временем.

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

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

Соответственно целочисленные данные

Этот тип представляет собой просто строку с символом CRLF в конце, представляющую целое число с префиксом байта ":". Например, ":0\r\n" или ":1000\r\n" являются целочисленными ответами. Многие команды Redis возвращают целые числа RESP, такие как INCR, LLEN и LASTSAVE.

Возвращаемое целое не имеет особого значения, это просто число приращения для INCR, время UNIX для LASTSAVE и т. д. Однако должно быть гарантировано, что возвращенное целое число находится в диапазоне 64-битных целых чисел со знаком.

Целочисленные ответы также широко используются для возврата true или false. Например, такие команды, как EXISTS или SISMEMBER, вернут 1 в случае истинности и 0 в случае ложности.

Другие команды, такие как SADD, SREM и SETNX, вернут 1, если операция действительно выполнена, и 0 в противном случае.

Следующие команды будут возвращать целочисленные ответы: SETNX, DEL, EXISTS, INCR, INCRBY, DECR, DECRBY, DBSIZE, LASTSAVE, RENAMENX, MOVE, LLEN, SADD, SREM, SISMEMBER, SCARD.

Многострочная строка RESP

Многострочные строки используются для представления одной двоично-безопасной строки длиной до 512 МБ.

Многострочные строки кодируются следующим образом:

  • Байт "$", за которым следует количество байтов, составляющих строку (длина префикса), завершается CRLF.
  • Строковые данные.
  • Окончательный CRLF.

Итак, строка «foobar» кодируется следующим образом:

"$6\r\nfoobar\r\n"

Когда просто пустая строка:

"$0\r\n\r\n"

Многострочные строки RESP также могут использоваться для обозначения отсутствия значения с использованием специального формата для представления нулевых значений. В этом специальном формате длина равна -1 и данных нет, поэтому Null представляется как:

"$-1\r\n"

Когда сервер отвечает многострочной строкой Null, API клиентской библиотеки должен возвращать не пустую строку, а нулевой объект. Например, библиотека Ruby должна возвращать 'nil', а библиотека C должна возвращать NULL (или устанавливать специальный флаг в объекте ответа) и так далее.

Массив RESP

Клиент отправляет команды на сервер Redis, используя массив RESP. Точно так же некоторые команды Redis возвращают клиенту набор элементов, используя массив RESP, который является типом ответа. Примером может служить команда LRANGE, которая возвращает элементы списка.

Массивы RESP отправляются в следующем формате:

  • * Символ в качестве первого байта, за которым следует количество элементов в массиве в виде десятичного числа, за которым следует CRLF.
  • Дополнительный тип RESP каждого элемента массива.

Итак, пустой массив — это просто следующее:

"*0\r\n"

Тогда кодировка массива двух пакетных строк RESP «foo» и «bar» будет следующей:

"*2\r\n$3\r\nfoo\r\n$3\r\nbar\r\n"

Как вы можете видеть, после префикса массива с частью *CRLF другие типы данных, составляющие массив, будут конкатенированы один за другим. Например, массив из трех целых чисел кодируется следующим образом:

"*3\r\n:1\r\n:2\r\n:3\r\n"

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

*5\r\n
:1\r\n
:2\r\n
:3\r\n
:4\r\n
$6\r\n
foobar\r\n

Первая строка, которую отправляет сервер, это *5\r\n, чтобы указать, что последуют пять ответов. Затем отправляется каждый ответ, составляющий элемент множественного ответа.

Концепция нулевых массивов также существует и является альтернативой нулевой цене (обычно использует нулевые многорядные строки, но у нас есть два формата из-за исторических причин).

Например, по истечении времени ожидания команды BLPOP она возвращает массив Null со значением -1, как показано в следующем примере:

"*-1\r\n"

Когда Redis отвечает массивом Null, API клиентской библиотеки должен возвращать пустой объект вместо пустого массива. Это необходимо, чтобы различать пустые списки и различные условия (например, условия тайм-аута для команд BLPOP).

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

*2\r\n
*3\r\n
:1\r\n
:2\r\n
:3\r\n
*2\r\n
+Foo\r\n
-Bar\r\n

Второй элемент — Null. Клиентская библиотека должна вернуть что-то вроде этого:

["foo",nil,"bar"]

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

Отправить команды на сервер Redis

Теперь, когда вы знакомы с форматом сериализации RESP, вам будет легко написать реализацию клиентской библиотеки Redis. Мы можем пойти немного дальше о том, как работает взаимодействие между клиентом и сервером:

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

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

Клиент отправляет команду LLEN mylist, чтобы получить длину списка, хранящегося в ключе mylist, и сервер отвечает целочисленным ответом, как в примере ниже (C: клиент, S: сервер).

C: *2\r\n
C: $4\r\n
C: LLEN\r\n
C: $6\r\n
C: mylist\r\n
S: :48293\r\n

Обычно мы разделяем разные части протокола символами новой строки для упрощения, но фактическое взаимодействие заключается в том, что клиент отправляет *2\r\n4 \ r \ nLLEN \ r \ n6\r\nmylist\r\n Общий.

резюме

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

Ссылка на ссылку