Кластер Redis На Базе Python. Часть 1: Распределенные Системы, Теоремы Cap И Pacelc И Зачем Нужен Redis

Рано или поздно сервисы растут, и вместе с высоким числом запросов в секунду появляется Highload. Что делать, когда ресурсов для вертикального масштабирования Redis больше нет, а данных не меньше? Как решить эту проблему без простоев и стоит ли решать ее с помощью redis-cluster? В мастерской Кластер на базе Redis Python Савва Демиденко и Илья Сильченков рассмотрели теорию алгоритмов консенсуса и попытались в реальном времени показать, как можно решить проблему с данными с помощью шардинга, который уже включен в redis-cluster. Семинар длился два часа.

Внутри этого поста — сокращенная расшифровка самых важных мыслей.



Введение

Немного о тех, кто проводил мастер-класс и почему вообще решили его провести.



Кластер Redis на базе Python. Часть 1: распределенные системы, теоремы CAP и PACELC и зачем нужен Redis

Савва Демиденко Я занимаюсь разработкой на Авито, делаю программу для курса «Разработчик Middle Python» от Яндекс.

Практикум.

Окончил Бауманку и Технопарк.

Я разрабатываю на Python и Golang. Мне нравится решать архитектурные задачи в веб-программировании.



Кластер Redis на базе Python. Часть 1: распределенные системы, теоремы CAP и PACELC и зачем нужен Redis

Илья Сильченков Руководитель команды в Сбермаркете и ментор курса Middle Python Developer. Я успел поработать фронтенд-разработчиком и дата-инженером, но остановился на бэкенде.

Сейчас я пишу на Python и Go. В пределах наш курс В Яндекс.

Практикуме уже полгода мы создаем онлайн-кинотеатр из множества микросервисов.

Сначала пишем небольшой ETL от Elasticsearch и Flask, затем админку и асинхронный API, систему авторизации/аутентификации и уведомлений.

Есть еще небольшая продуктовая задача — пиар в социальных сетях.

Как вы знаете, в Твиттере смехотворное ограничение на количество символов.

Пользователи часто сокращают ссылки.

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

Чтобы решить эту проблему, мы взяли простой стек с учетом разработки на Python: FastAPI, pydantic-фреймворк асинхронной проверки, и Redis в качестве хранилища данных.

Redis очень простой, однопоточный и доставляет данные за постоянное время.

Кажется, чтобы сохранить ссылку и получить ее, большего и не нужно.

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

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

Переезд на другое хранилище – дорогостоящая операция.

Прочтите статьи Как Uber перешел с MySQL на PostgreSQL - там все ужасно.

Речь идет о событиях 2013 года: из-за отрицательных результатов через три года был осуществлен обратный переход в инфраструктуре Uber. Сменить хранилище на нашем сервисе – это последнее, что вы можете сделать.

Перед этим важно понять, как мы тратим ресурсы, и попытаться оптимизировать хранение данных — переместить часть данных в холодное хранилище или удалить их.

Возможно, мы забыли очистить память, и она засорилась.

После всех оптимизаций нужно двигаться в сторону масштабирования.



Кластер Redis на базе Python. Часть 1: распределенные системы, теоремы CAP и PACELC и зачем нужен Redis

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



Теория



Распределенные системы

Давайте посмотрим, что такое распределенные системы с точки зрения информатики.

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

Для этого нужно не наступать на чужие грабли, а теория как раз позволяет их обойти.



Кластер Redis на базе Python. Часть 1: распределенные системы, теоремы CAP и PACELC и зачем нужен Redis

Простейшее определение распределенной системы предложено Лесли Лэмпортом, создателем алгоритма Paxos. Распределенная система — система, в которой машинный сбой, о котором вы даже не подозревали, мог превратить ваш компьютер в тыкву.

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

Из этого определения следует, что любой сайт — это распределенная система.

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

Если хост выйдет из строя, сайт не будет работать.

Распределена ли какая-либо система, в которой задействовано более двух аппаратных средств? Почти.

Давайте посмотрим на пример Redis Cluster. Он вводит подтипы распределенных систем, для классификации которых требуется теорема CAP. Оно описывает главное свойство распределенных систем — согласованность.

Википедия разбивает согласованность на три отдельные концепции: «…согласованность данных друг с другом, целостность данных и внутренняя согласованность».

Рассмотрим пример с обычной реляционной базой данных социальной сети.

В нем есть таблица с пользователями и отдельная таблица с друзьями (парами ID).

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

А если пользователь уйдет, то пары с ним либо будут удалены, либо не будут учитываться.

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

Пары облигаций согласуются друг с другом.

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



Кластер Redis на базе Python. Часть 1: распределенные системы, теоремы CAP и PACELC и зачем нужен Redis

В действительности консистенция варьируется.

То, что это большое дерево из Jepsen.io подсвечено зеленым, — это какая-то нормальная последовательность, а все под ним — технические детали, которые его приближают.

Теорема CAP

В Теорема CAP используется линеаризуемая консистенция.

Приведем пример, когда это свойство отсутствует.

Кластер Redis на базе Python. Часть 1: распределенные системы, теоремы CAP и PACELC и зачем нужен Redis

Предположим, что в распределенной системе есть три узла: лидер и два последователя.

Судья сказал, что Германия выиграла футбольный матч.

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

Алиса зашла и увидела победу Германии, а Боб увидел, что матч все еще продолжается — изменение дошло не до всех последователей.

Если бы последовательность в этой системе была линеаризуемой, то оба участника прочитали бы о победе Германии.

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

Второе свойство — это толерантность к разделению, или устойчивость к разделению сети или нестабильности сети.

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

Если его разрезать, произойдет такое же деление сети.

Будет два контура со множеством серверов в каждом.

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

Последнее свойство — доступность.

Система ответит быстро, но без гарантии, что это будет быстро и со свежими данными.

Линейной последовательности не ожидается.



Кластер Redis на базе Python. Часть 1: распределенные системы, теоремы CAP и PACELC и зачем нужен Redis

Теорема CAP утверждает принцип тройного ограничения: можно получить только два свойства из трех.

Системы делятся на CP, CA и AP. Все системы стараются охватить сразу два объекта недвижимости, а не один.

Давайте рассмотрим самые простые примеры.

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

Если кабель между ними оборвется, оба перестанут работать.

В теореме CAP этот образец работы соответствует согласованности и доступности (CA).

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

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

Однако данные будут не самыми последними.

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

Оказывается, каждый раз, когда вы решаете задачу, вам нужно смотреть на теорему CAP, чтобы выбрать необходимые свойства.



Теорема PACELC

ПАСЕЛК заменил теорему CAP и расширил ее.

Выпускает четыре типа систем.



Кластер Redis на базе Python. Часть 1: распределенные системы, теоремы CAP и PACELC и зачем нужен Redis

В правом верхнем углу находятся системы PC/EC, которые всегда выбирают согласованность.

Это банки, самолеты и другие надежные системы.

Кому это не нужно, идут в левый нижний угол - к системам PA/EL. При нарушении сетевого подключения (раздела) обеспечивается доступность, в противном случае обеспечивается скорость ответа (задержка).

Примером такой системы является Amazon в Черную пятницу.

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

Не важно, все ли будет в наличии, важно, чтобы вы могли сделать заказ.

В левом верхнем углу расположены системы PA/EC. В случае разделения сети необходима доступность; в другом случае необходима последовательность.

MongoDB работает по этому принципу, хотя иногда он ближе к системе PC/EC. Если происходит расщепление, могут возникнуть проблемы с согласованностью.

Единственная известная система, работающая через ПК/EL, — это поисковая система Yahoo. При разбиении узлов он выбирает согласованность, поскольку ему важно сохранять данные и реагировать единообразно.

Если проблем нет, он выбирает задержку для быстрого предоставления ответа.

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

При чем здесь Redis?

Redis не может рассматриваться в теореме CAP. Всё-таки это одноузловая штука, а по теореме CAP — распределённая система хранения данных.

Вы можете думать об этом как о распределенной системе с веб-сайтом сверху: множество узлов и кода переходят в один Redis. И вы получаете систему CA: если между сайтом и Redis нет сети, все будет проваливаться, но каждый узел все равно будет доступен.

Многие люди используют Redis в качестве уровня кэширования.

Memcached играет эту роль реже.

Но он живет только в памяти, а сообщество Redis неплохо развивается.

В курсе Middle Python Developer мы используем Redis Cluster в асинхронном API. Мы уже рассматриваем механизмы работы с узлами и способы их правильного масштабирования.

Тема сложная, но несколько отчетов от Amazon объясняют, как все должно быть сделано — вы найдете их в конце поста.

Мы далеко не первопроходцы — отдел исследований и разработок Amazon сделал это уже в 2007 году.

Итак, в теореме CAP Redis Cluster — это P. Почему просто P, без еще одной буквы?

Кластер Redis на базе Python. Часть 1: распределенные системы, теоремы CAP и PACELC и зачем нужен Redis

Обычно это происходит, когда кто-то не до конца разбирается в теме и решает разработать собственное решение.

Ребята из Jepsen.io провели анализ и сказали, что система устойчива к расщеплению.

В то же время он пытается вести себя как кластер.

А если половина узлов недоступна, он уже не сможет работать.

Это говорит о том, что Redis Cluster не является системой AP. Остался только один П.

Если мы используем WAIT, который мы добавили позже, когда закончили читать теорию, Redis Cluster станет CP.

Острова и мосты

Проектирование распределенных систем и проверка согласованности — хорошая инженерная задача.

Во время анализа человеческому разуму необходима какая-то аналогия.

Проблема обедающих философов является хорошим примером этого.

Будет аналогия в виде островов и мостов между ними.

Острова живут как одно государство с общим сводом законов.

И каждый остров хочет влиять на эти законы.

Но не съездом в том же замке с распространением коронавируса, а отправкой посыльных как курьеров с едой.

И они будут перемещаться между островами по мостам.

На каждом острове мы сохраним свой собственный свод законов, но изменения будут заблокированы для всех.

Важно понимать, что здесь необходим консенсус чтения и консенсус записи.

Мы обязательно уточним, со скольких островов вам нужно получить информацию, чтобы заявить, что закон работает на 100%.

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

Чтение – это сбор логов изменений законов к себе.

Запись - этот журнал изменений законов мы куда-то берем.

Это именно то, что представляют собой два консенсуса: чтение и письмо.

Если сменить острова на сервера, ничего не потеряется: как рассудили, так и останется.

Острова и мосты уже стали традицией.

Создатель этого алгоритма Лесли Лампорт использует аналогию из Алгоритм Паксоса .

Его конкретные реализации — ZAB (Apache ZooKeeper) и Raft. Если мы возьмем алгоритм, соответствующий Paxos, то на выходе будет CP. В спецификациях говорится, что Raft прост, но на самом деле его нелегко понять.

На сайте raft.github.io содержит классную настраиваемую анимацию браузера, с которой мы рекомендуем поиграть.



Упражняться

Теперь представим, что мы стажер, который впервые пришел на работу и впервые видит этот код. Напомним, модуль взят из курса «Разработчик Middle Python»: на входе он получает ссылку, на выходе выдает новый хеш, а при нажатии на хеш разворачивает его и дает редирект. Кажется, все просто – поехали! Перейти к прочтению.

Здесь написано, что это код вебинара, и описано, как запустить Docker Compose, что упрощает взаимодействие сервисов друг с другом.



Кластер Redis на базе Python. Часть 1: распределенные системы, теоремы CAP и PACELC и зачем нужен Redis

Автор сервиса оставил нам документацию - большое спасибо.

В этом заслуга FastAPI: документация генерируется автоматически.

У нас есть сервис и конфигурационные файлы.

Давайте разберём их.



Кластер Redis на базе Python. Часть 1: распределенные системы, теоремы CAP и PACELC и зачем нужен Redis

В Dockerfile все классически: Python через pip и Pipenv, последний уже все остальное устанавливает, API запускается на порту 8080.

Кластер Redis на базе Python. Часть 1: распределенные системы, теоремы CAP и PACELC и зачем нужен Redis

В файле docker-compose всё просто: Redis и наше Python-приложение.

Идите реализовывать это.



Кластер Redis на базе Python. Часть 1: распределенные системы, теоремы CAP и PACELC и зачем нужен Redis

Мы находимся в начале приложения.

Есть несколько хуков для начала и конца, запуска и завершения работы.

И вот самое интересное: в этом фрезере присутствуют основные ручки.

Чуть не пропустил FastAPI. Кстати, что такое FastAPI? FastAPI — это крутой современный асинхронный фреймворк на Python. Внутри пидантик, генерация спецификаций OpenAPI (даже третьей версии, а не Swagger!).

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

И в то же время он асинхронен, что позволяет дешево работать по сети.

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

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

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

Мы также коснемся сопрограмм, которые соединяются с Golang и каналами.



Кластер Redis на базе Python. Часть 1: распределенные системы, теоремы CAP и PACELC и зачем нужен Redis

Вернемся к коду.

Нам нужны функции «создать», «проверить» и «перенаправить».

Это три функции.



Кластер Redis на базе Python. Часть 1: распределенные системы, теоремы CAP и PACELC и зачем нужен Redis

Давайте посмотрим на то, что я считаю самым простым — создание URL-адреса.

Давайте поговорим о логике:

  • запрос поступает и проверяется по URL-адресу;
  • если данные подходят — то есть, например, не пусты — сжимаем URL в хэш и записываем его в Redis;
  • затем мы указываем полный путь, хеш и URL-адрес, по которому вы можете перейти и получить перенаправление.

Давайте посмотрим, как это реализовано.

Внутри метода url_repository.create_url нет ничего умного.



Кластер Redis на базе Python. Часть 1: распределенные системы, теоремы CAP и PACELC и зачем нужен Redis

Есть околослужебная информация, которую мы инициализировали.

Мы также отслеживаем столкновения.

Решаем проблему коллизий добавлением букв.

Мы не городим список и не хешируем ключ, а просто меняем ключ.




Во второй части поста мы расскажем, зачем нужно Dynamo и что делать, когда Redis несколько.

Теги: #python #программирование #redis #Высокая производительность #highload #cap #Яндекс.

мастерская #pacelc

Вместе с данным постом часто просматривают: