Опубликован: 12.03.2016 | Уровень: для всех | Доступ: платный
Лекция 2:

Основы

< Лекция 1 || Лекция 2 || Лекция 3 >

Почему же Redis такой особенный? Какие задачи он решает? На что следует обращать внимание разработчикам? Перед тем, как ответить на все эти вопросы, мы должны понять, чем же все-таки является Redis.

Очень часто Redis описывают как персистентное (то есть сохраняющееся после окончания работы создавшего его процессса - прим. перев.) хранилище данных типа ключ-значение в оперативной памяти. Я не думаю, что это совсем точное определение. Redis, \linebreak действительно, держит все данные в памяти (позже мы вернемся к этому), и он сохраняет данные на диск для обеспечения персистентности. Но он не просто хранилище данных типа ключ-значение. Очень важно разобраться в этом неточном определении, иначе у вас сложится впечатление, что спектр решаемых Redis проблем весьма узок.

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

Если мы применим эту концепцию к реляционному миру, мы можем сказать, что базы данных предоставляют один тип структур данных - таблицы. Таблицы одновременно сложные и гибкие. Существует очень мало вещей, которые нельзя смоделировать, \linebreak сохранить и которыми нельзя управлять с помощью таблиц. Тем не менее, они не идеальны. А именно, они не на столько простые, или не на столько быстрые, как хотелось бы. Что, если вместо универсальной структуры мы бы использовали специализированные структуры? В этом случае, наверное, найдутся проблемы, которые мы не сможем решить (или, по крайней мере, не сможем решить достаточно хорошо). Однако, в любом случае, мы выиграем на простоте и скорости.

Использование специфичных структур данных для специфичных задач? Разве это не тот подход, который мы постоянно используем при программировании? Вы не используете хеш-таблицы для всех данных программы, то же самое и со скалярными переменными. (Скалярные типы данных: строки, целые числа, дроби, булев тип - прим. перев.) Я считаю, в этом и состоит подход Redis. Если вы работаете со скалярами, списками, или множествами, почему бы не хранить их как скаляры, списки, хеши и множества? Почему проверка на существование должна быть сложнее чем просто вызов exists(key) или медленнее чем O(1) (постоянное время выполнения выражения, которое не зависит от количества записей в хранилище)?

Составные Кирпичики

Базы Данных

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

В Redis база данных идентифицируется просто числом, которое по умолчанию равняется 0. Если вы хотите сменить базу данных, то вы можете сделать это командой select. В командной строке просто введите select 1. Redis должен ответить сообщением OK и в терминале вы должны увидеть что-то типа redis 127.0.0.1:6379[1]>. Если вы хотите переключиться обратно на базу по умолчанию, просто введите в командной строке select 0.

Команды, Ключи и Значения

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

Ключ - это то, чем мы помечаем части информации. Мы будем пользоваться ключами часто, но пока достаточно знать, что ключ может выглядеть вот так: users:leto. Под таким ключом можно ожидать информацию о пользователе под именем leto. Двоеточие не имеет никакого особого значения, но использование подобных разделителей является хорошим тоном.

Значение - это данные, которые ассоциированы с ключом. Это может быть что угодно. Иногда это строки, иногда числа, а иногда там хранятся сериализованные объекты (в виде JSON, XML или любых других форматов). В основном, Redis рассматривает значение как массив байт и не интересуется тем, что они собой представляют. Обратите внимание, что разные драйверы производят сериализацию по-разному. Поэтому, здесь мы будем говорить только о строках (string), целых числах (integer) и JSON.

Давайте попрактикуемся. Выполните следующие команды:

set users:leto "{name: leto, planet: dune, likes: [spice]}"

Почти все команды Redis выглядят подобным образом. Сначала идет сама команда, в нашем случае set, а потом параметры. Команда set принимает два параметра: ключ, который мы сохраняем, и значение, которое связано с ним. Многие, но не все, команды принимают ключ (это обычно первый параметр). А теперь угадайте, как получить это значение? Надеюсь, что вы догадались (не расстраивайтесь, если это не так):

get users:leto

Попробуйте самостоятельно поиграть с подобными комбинациями. Ключ и значение - это основная концепция, и простейший способ работать с ней - это команды get и set. Создайте других пользователей, попробуйте разные виды ключей и значений.

Запросы

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

У многих это может вызвать некоторое беспокойство. Мы живем в мире, где запросы к базам данных стали столь гибкие и мощные, что подход Redis кажется примитивным и неудобным. Не дайте ввести себя в заблуждение. Redis не является универсальным решением на все случаи жизни. Существуют проблемы, которые просто не решаются с помощью Redis (из-за ограничений в запросах). Также стоит принять к сведению, что в некоторых случаях, вы найдете другие способы смоделировать ваши данные.

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

Память и Персистентность

Мы упоминали ранее, что Redis является персистентным хранилищем в оперативной \linebreak памяти. По умолчанию, для поддержания персистентности, Redis сохраняет снимки базы данных на диск в зависимости от того, сколько ключей было изменено. Вы можете \linebreak настроить этот процесс таким образом, что если X - количество изменившихся ключей, то базу данных нужно сохранять каждые Y секунд. По умолчанию, Redis сохраняет базу с интервалами от 60 секунд, если 1000 или более ключей изменились, до 15 минут, если изменились хотя бы 9 ключей.

Кроме того, (или в дополнение к сохранению снимков базы на диске), Redis может быть запущен в режиме дозаписи (append mode). Каждый раз, когда ключ меняется, на диске дописывается запись в файле, открытом в режиме дозаписи (новые записи добавляются в конец файла). Иногда стоит принять риск потери данных последних 60 секунд в случае аппаратной или программной ошибки в обмен на производительность. В других случаях такой риск неприемлем. Redis дает вам выбор. В главе 5 мы рассмотрим третью \linebreak возможность - обеспечение персистентности за счет вспомогательного (slave) хранилища.

Что касается использования памяти, Redis хранит все данные в оперативной памяти. Явным следствием этого является цена использования Redis: оперативная память до сих пор является самой дорогой аппаратной частью серверов.

Я чувствую, что некоторые разработчики забывают о том, как мало места могут занимать данные. Полное собрание сочинений Уильяма Шекспира занимает примерно 5,5 МБ. Что касается масштабирования, другие решения, как правило, ограничены временем ввода/вывода или производительностью процессора. Какое из ограничений (память или ввод/вывод) вынудит вас масштабировать приложение на большем количестве серверов, зависит от типа обрабатываемых данных и от того, как вы их храните и запрашиваете. Пока вы не храните огромные медиа-файлы в Redis, использование оперативной памяти не должно быть проблемой. Для приложений, где это все же будет проблемой, вы, скорее всего, выберете дополнительную нагрузку на ввод/вывод, чем ограничения размера \linebreak памяти.

В Redis была реализована поддержка виртуальной памяти. Тем не менее, эта функция была признана неудачной (самими инженерами Redis) и ее использование не \linebreak рекомендуется.

К слову, 5,5 МБ сочинений Шекспира могут быть сжаты до примерно 2 МБ. Redis не использует автоматическое сжатие, но, поскольку он трактует данные, как набор байт, нет причин, по которым вы не могли бы обменять время обработки на дополнительную память путем сжатия/распаковки данных.

Собираем Все Вместе

Мы коснулись нескольких общих тем. Последнее, что я хотел бы сделать перед \linebreak погружением в Redis, это собрать несколько этих тем вместе. А именно, ограничения запросов, структуры данных и способ хранения данных Redis в оперативной памяти.

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

Насколько высока скорость? Это зависит от многих вещей: какие команды и типы данных вы используете и так далее. Но производительность Redis обычно измеряется в десятках тысяч или даже сотнях тысяч операций в секунду. Вы можете запустить redis-benchmark (расположен в той же директории, что и redis-server и redis-cli), чтобы проверить это.

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

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

В этой главе

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

Ключевые моменты этой главы:

  • Ключи - это строки, идентифицирующие фрагменты данных (значения)
  • Значения - это произвольные массивы байт, которым Redis не придает никакого смысла
  • Redis предоставляет пять специализированных структур данных (он реализован на их основе)
  • Все упомянутое вместе делает Redis быстрым и простым в использовании, но не подходящим для любого сценария использования
\clearpage
< Лекция 1 || Лекция 2 || Лекция 3 >
Александр Прокофьев
Александр Прокофьев

Что за бред? зачем его выложили если его нельзя закончить???

Тогда уберите бесплатность курса! Или надо жаловаться администрации сайта на вас?

Ups Shelest
Ups Shelest

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

Уровень курса - обзорная статья на хабре. Платить за такое - просто нельзя.

Так как же, все таки, завершить обучение в этом курсе?

Андрей Частухин
Андрей Частухин
Россия
Вера Борисова
Вера Борисова
Россия