Вам бонус- начислено 1 монета за дневную активность. Сейчас у вас 1 монета

Паттерны индексирования Redis

Лекция



Привет, Вы узнаете о том , что такое Паттерны индексирования Redis, Разберем основные их виды и особенности использования. Еще будет много подробных примеров и описаний. Для того чтобы лучше понимать что такое Паттерны индексирования Redis , настоятельно рекомендую прочитать все из категории Redis DB Nosql.

Redis можно использовать бесчисленным количеством способов, однако, есть несколько паттернов, с помощью которых можно решать часто возникающие проблемы. Мы собрали коллекцию общих паттернов, которые мы считаем best practices для решения этих проблем. Эта коллекция не является исчерпывающей и не представляется как набор единственных способов использования Redis, но мы надеемся, она послужит отправной точкой для решения проблем с помощью Redis.

В этой статье рассмотрим способы выйти за рамки обычного доступа «ключ-значение» с Redis. Туда входят способы умного использования паттернов на ключах с использованием различных типов данных Redis, чтобы помочь не только в поиске данных, но и снизить сложность доступа;

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

Индексирование в Redis довольно сильно отличается от того, что представлено в других базах данных, поэтому ваши собственные сценарии использования и данные определят лучшую стратегию для индексирования. В этой главе мы рассмотрим некоторые общие стратегии поиска данных помимо простого получения по «ключу/значению»:

  • сортированные множества как индексы;
  • лексикографические индексы;
  • геопространственные индексы;
  • IP-геолокация;
  • полнотекстовый поиск;
  • партиционированные индексы.

Сортированные множества как индексы


Сортированные множества (ZSETs) — стандартный тип данных в Redis, который представляет множество уникальных объектов (повторения не сохраняются), где каждый объект закреплен за числом (называемое «счет»), которое выступает как естественный механизм сортировки. И хотя объекты не могут повторяться, любые несколько объектов могут иметь одинаковый счет. При относительно невысокой временной сложности на добавление, удаление и получение диапазона значений (по рангу или счету) сортированные множества вполне пригодны для того, чтобы быть индексами. В качестве примера возьмем страны мира, ранжированные по населению:

  Паттерны индексирования Redis


Получить топ-5 стран будет просто:

  Паттерны индексирования Redis


А получение стран с населением между 10000000 и 1000000000:

 Паттерны индексирования Redis


Можно создать несколько индексов, чтобы продемонстрировать разные способы сортировки данных. В нашем примере мы могли бы использовать те же объекты, но вместо количества людей взять плотность населения, географические размеры, количество пользователей Интернет и т.д. Это создаст высокопроизводительные индексы для разных аспектов. Кроме того, деля имя объекта с данными о нем, хранящимися либо в Redis (в Hash, например), либо в другом хранилище данных, вторичный процесс мог бы получить дополнительную информацию о каждом элементе по мере необходимости.

Лексикографические индексы


Сортированные множества (ZSETs) с ранжированием по счету имеют одно интересное свойство, которое может быть использовано для создания механизма грубой алфавитной сортировки. Свойство заключается в том, что объекты с одинаковым счетом могут быть возвращены в лексикографическом порядке и по граничным значениям. Возьмем следующие данные:

 Паттерны индексирования Redis 


Эта команда добавит нескольких животных к ключу animal-list. У каждый объекта счет 0. Выполнив команду ZRANGE с аргументами 0 и -1, увидим любопытный порядок:

  Паттерны индексирования Redis


Несмотря на то, что элементы были добавлены не в алфавитном порядке, они оказались возвращены отсортированными по алфавиту. Такой порядок является результатом двоичного сравнения строк, побайтового. Это значит, что ASCII-символы вернутся в алфавитном порядке. Это говорит о следующем:

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


Redis также предоставляет некоторые продвинутые возможности для дальнейшего сужения лексикографического поиска. Например, мы хотим вернуть животных, начинающихся с b и заканчивающихся на e. Мы можем использовать следующую команду:

  Паттерны индексирования Redis


Аргумент (f может немного смутить. Это важный момент, потому что Redis не имеет никакого понятия о буквальном понимании букв алфавита. Это значит, что мы должны учитывать, что все начинающееся с e всегда будет стоять до всего начинающегося с f, независимо от последующих букв. Другое примечание заключается в том, что квадратная скобка указывает на поиск с включением, а круглая на поиск без включения. В нашем случае, если мы запрашиваем с b, это будет включено в список, тогда как f не появится в выборке. Если вам нужны все элементы до конца, используйте закодированный последний символ (255 или 0xFF):

  Паттерны индексирования Redis 


Эту команду можно также ограничить, обеспечив тем самым постраничный вывод:

  Паттерны индексирования Redis


Единственный подводный камень, что временная сложность будет расти по мере увеличения отступа (первый аргумент после LIMIT). Об этом говорит сайт https://intellect.icu . Поэтому, если у вас 1 миллион объектов и вы пытаетесь получить последние два, это потребует обхода всего миллиона.

Геопространственные индексы


У Redis есть несколько команд, связанных с геопространственным индексированием (GEO команды), но, в отличие от других команд, у этих команд нет собственных типов данных. Эти команды на самом деле дополняют тип сортированного множества. Это достигается кодированием широты и долготы в счет (score) сортированного множества, используя алгоритм геохэша.
Добавить элементы к геоиндексу легко. Предположим, вы отслеживаете группу автомобилей, которые едут по дороге. Назовем это множество машин просто «cars». Скажем, что ваша особая машина может быть идентифицирована как объект «my-car» (мы используем термин «объект», потому что геоиндекс просто форма множества). Чтобы добавить машину ко множеству, мы можем выполнить команду:

 Паттерны индексирования Redis


Первый аргумент – множество, к которому добавляем, второй – широта, третий – долгота и четвертый – имя объекта.

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

 Паттерны индексирования Redis


Добавим вторую машину к «cars». На этот раз ведет ее Володя:

 Паттерны индексирования Redis


Взглянув на координаты, вы можете сказать, что это машины довольно недалеко друг от друга, но насколько? Вы можете определить это командой GEODIST:

  Паттерны индексирования Redis


Это значит, что два транспортных средства примерно в 151 метре друг от друга. Можно посчитать также в других единицах измерения:

  Паттерны индексирования Redis


Это вернуло то же самое расстояние в футах. Вы также можете использовать мили (ml) или километры (km).

Сейчас давайте посмотрим, кто есть в радиусе определенной точки:

 Паттерны индексирования Redis 


Это вернуло всех в радиусе 100 метров вокруг указанной точки. Можно также запросить всех в радиусе какого-либо объекта из множества:

  Паттерны индексирования Redis


Мы можем также включить дистанцию, добавив необязательный аргумент WITHDIST (это работает для GEORADIUS или GEORADIUSBYMEMBER):

  Паттерны индексирования Redis


Другой необязательный аргумент для GEORADIUS и GEORADIUSBYMEMBER – WITHCOORD, который возвращает координаты каждого объекта. WITHDIST и WITHCOORD можно использовать вместе или по отдельности:

  Паттерны индексирования Redis


Так как геопространственные индексы – это просто альтернатива сортированным множествам, можно пользоваться некоторыми операторами последних. Если мы хотим удалить «my-car» из множества «cars», можно использовать команду сортированного множества ZREM:

  Паттерны индексирования Redis


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

IP-геолокация


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

На IPv4 люди чаще всего ссылаются в десятичной нотации (74.1251.43.992, например). Однако сетевые сервисы видят этот же самый адрес как 32-битное число, причем каждый байт представляет одно из четырех чисел в десятичной форме. Пример выше будет 0x4A7D2B61 в шестнадцатеричном виде или 1249717090 в десятичном.

Наборы данных IP-геолокации широко доступны и обычно имеют форму простой таблицы с тремя колонками (начало, конец, местоположение). Начало и конец – десятичное представление IPv4. В Redis мы можем адаптировать сортированные множества под этот формат, потому что в диапазонах IP отсутствуют «дыры», следовательно, можно с уверенностью допустить, что конец одного диапазона – это начало другого.

Для простого примера добавим несколько диапазонов в сортированные множества:

 Паттерны индексирования RedisПаттерны индексирования Redis


Первый аргумент – ключ нашего множества, второй – десятичное предствление конца IP-диапазона, и последний – собственно, сам объект. Обратите внимание, что объект множества имеет число после двоеточия. Это просто для облегчения примера. В реальных IP-таблицах для каждого диапазона свои уникальные идентификаторы (и больше дополнительной информации, чем просто название страны).

Чтобы запросить таблицу к данному IP-адресу, мы можем использовать команду ZRANGEBYSCORE с несколькими дополнительными аргументами. Возьмем IP-адрес и конвертируем его в десятичный вид. Это можно сделать средствами вашего языка программирования. Для начала используем адрес из исходного примера 74.125.43.99 (1249717091). Если мы возьмем это число в качестве начало отсчета и не укажем максимум, а затем ограничим результат только до первого объекта, мы найдем его геоположение:

 Паттерны индексирования Redis 


Первый аргумент – ключ нашего сортированного множества, второй – десятичное представление IP-адреса, третий (+inf) говорит Redis запрашивать без верхней границы, и последние три аргумента просто указывают, что мы хотим получить только самый первый результат.

Полнотекстовый поиск


До появления модулей полнотекстовый поиск был реализован с использованием собственных команд Redis. Модуль RedisSearch намного более производительный, чем этот паттерн, однако, в некоторых окружениях он недоступен. Кроме того, этот паттерн очень интересен и может быть обобщен для других рабочих нагрузок, в которых RedisSearch будет не идеален.
Допустим, у нас есть несколько текстовых документов, по которым нужно произвести поиск. Это может быть неочевидный use-case для Redis, так как он осуществляет доступ по ключам, но, с другой стороны, Redis может быть использован как совершенно новый полнотекстовый поисковый движок.

Сначала возьмем несколько примерных текстов в документах:

Паттерны индексирования Redis
Разделим их на наборы слов, разделенных пробелом для простоты:

 Паттерны индексирования Redis 


Обратите внимание, что мы помещаем каждую строку в свое собственное множество. Может показаться, что мы просто добавляем всю строку – SADD является вариативным и принимает сразу несколько элементов в качестве аргументов. Мы также перевели все слова в нижний регистр.
Затем нам нужно инвертировать этот индекс и показать, какое слово в каком документе содержится. Для этого мы сделаем множество для каждого слова и поместим имя документа в качестве объекта:

 Паттерны индексирования Redis 


Для ясности мы разделили это на разные команды, но все команды обычно выполняются атомарно в блоке MULTI/EXEC.

Чтобы запросить наш крошечный полнотекстовый индекс, мы используем команду SINTER (пересечение множеств). Найти документы с «very» и «fast»:

  Паттерны индексирования Redis


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

  Паттерны индексирования Redis


Для логичности лучше использовать SUNION вместо SINTER:

 Паттерны индексирования Redis


Удаление объекта из индекса немного сложнее. Сначала получим индексированные слова из документа, затем удалим идентификатор документа от каждого слова:

  Паттерны индексирования Redis


В Redis нет отдельного оператора, чтобы выполнить все эти шаги одной командой, поэтому сначала придется запрашивать командой SMEMBERS, затем последовательно удалять каждый объект при помощи SREM.

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

Партиционированные индексы


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

Чтобы достичь равномерного распределения ключей, мы будем использовать некриптографический алгоритм хеширования. Подойдет любая быстрая функция хеширования, но мы используем известную CRC-32 для примера. В большинстве случаев эти алгоритмы возвращают результат в шестнадцатеричном виде (для «my-cool-document» CRC-32 выдаст F9FDB2C9). Шестнадцатеричное представление проще для машины, но это просто другое представление десятичных целых чисел, которое означает, что можно выполнять вычисления на этих значениях.
Далее нужно определить число партиций – это должно быть по крайней мере х2 от количества экземпляров. В дальнейшем это способствует масштабированию.

Допустим, у нас есть 3 экземпляра и 6 партиций. Вычислить партицию, на которую отправить документ, можно следующей операцией:

хеш_функция(идентификатор_документа) mod число_партиций

Паттерны индексирования Redis


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

idx:my-cool-document{5}

Затем у нас есть другой документ, который выдает партицию с номером 3, следовательно, ключ будет выглядеть так:

idx:my-other-document{3}

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

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

Вау!! 😲 Ты еще не читал? Это зря!

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

создано: 2021-03-14
обновлено: 2021-03-14
4



Рейтиг 9 of 10. count vote: 2
Вы довольны ?:


Поделиться:

Найди готовое или заработай

С нашими удобными сервисами без комиссии*

Как это работает? | Узнать цену?

Найти исполнителя
$0 / весь год.
  • У вас есть задание, но нет времени его делать
  • Вы хотите найти профессионала для выплнения задания
  • Возможно примерение функции гаранта на сделку
  • Приорететная поддержка
  • идеально подходит для студентов, у которых нет времени для решения заданий
Готовое решение
$0 / весь год.
  • Вы можите продать(исполнителем) или купить(заказчиком) готовое решение
  • Вам предоставят готовое решение
  • Будет предоставлено в минимальные сроки т.к. задание уже готовое
  • Вы получите базовую гарантию 8 дней
  • Вы можете заработать на материалах
  • подходит как для студентов так и для преподавателей
Я исполнитель
$0 / весь год.
  • Вы профессионал своего дела
  • У вас есть опыт и желание зарабатывать
  • Вы хотите помочь в решении задач или написании работ
  • Возможно примерение функции гаранта на сделку
  • подходит для опытных студентов так и для преподавателей

Комментарии


Оставить комментарий
Если у вас есть какое-либо предложение, идея, благодарность или комментарий, не стесняйтесь писать. Мы очень ценим отзывы и рады услышать ваше мнение.
To reply

Базы данных - Redis DB Nosql

Термины: Базы данных - Redis DB Nosql