Рано или поздно сервисы растут, и вместе с высоким числом запросов в секунду появляется Highload. Что делать, когда ресурсов для вертикального масштабирования Redis больше нет, а данных не меньше? Как решить эту проблему без простоев и стоит ли решать ее с помощью redis-cluster? В мастерской Кластер на базе Redis Python Савва Демиденко и Илья Сильченков рассмотрели теорию алгоритмов консенсуса и попытались в реальном времени показать, как можно решить проблему с данными с помощью шардинга, который уже включен в redis-cluster. Семинар длился два часа.
Внутри этого поста — сокращенная расшифровка самых важных мыслей.
Введение
Немного о тех, кто проводил мастер-класс и почему вообще решили его провести.
Савва Демиденко Я занимаюсь разработкой на Авито, делаю программу для курса «Разработчик Middle Python» от Яндекс.
Практикум.
Окончил Бауманку и Технопарк.
Я разрабатываю на Python и Golang. Мне нравится решать архитектурные задачи в веб-программировании.
Илья Сильченков Руководитель команды в Сбермаркете и ментор курса Middle Python Developer. Я успел поработать фронтенд-разработчиком и дата-инженером, но остановился на бэкенде.
Сейчас я пишу на Python и Go. В пределах наш курс В Яндекс.
Практикуме уже полгода мы создаем онлайн-кинотеатр из множества микросервисов.
Сначала пишем небольшой ETL от Elasticsearch и Flask, затем админку и асинхронный API, систему авторизации/аутентификации и уведомлений.
Есть еще небольшая продуктовая задача — пиар в социальных сетях.
Как вы знаете, в Твиттере смехотворное ограничение на количество символов.
Пользователи часто сокращают ссылки.
Один из сервисов нашего курса вставляет ссылку в простой API, который сокращает ее и отправляет обратно.
Чтобы решить эту проблему, мы взяли простой стек с учетом разработки на Python: FastAPI, pydantic-фреймворк асинхронной проверки, и Redis в качестве хранилища данных.
Redis очень простой, однопоточный и доставляет данные за постоянное время.
Кажется, чтобы сохранить ссылку и получить ее, большего и не нужно.
К сожалению, с высоким числом запросов в секунду связана и высокая нагрузка — то состояние инфраструктуры, которое требует ее оптимизации и масштабирования.
Сегодня мы решим проблему, когда наше хранилище, а именно Redis, уже не помещается на одном серверном оборудовании, поэтому нам нужно придумать, как его раздвинуть.
Переезд на другое хранилище – дорогостоящая операция.
Прочтите статьи Как Uber перешел с MySQL на PostgreSQL - там все ужасно.
Речь идет о событиях 2013 года: из-за отрицательных результатов через три года был осуществлен обратный переход в инфраструктуре Uber. Сменить хранилище на нашем сервисе – это последнее, что вы можете сделать.
Перед этим важно понять, как мы тратим ресурсы, и попытаться оптимизировать хранение данных — переместить часть данных в холодное хранилище или удалить их.
Возможно, мы забыли очистить память, и она засорилась.
После всех оптимизаций нужно двигаться в сторону масштабирования.
В результате хранилище превращается в несколько машин Redis. Прежде чем приступить к работе с практической задачей, необходимо понять академическую сторону вопроса.
Теория
Распределенные системы
Давайте посмотрим, что такое распределенные системы с точки зрения информатики.Это важно понимать, поскольку ожидается, что у вас будет готовое решение, которое будет работать «из коробки».
Для этого нужно не наступать на чужие грабли, а теория как раз позволяет их обойти.
Простейшее определение распределенной системы предложено Лесли Лэмпортом, создателем алгоритма Paxos. Распределенная система — система, в которой машинный сбой, о котором вы даже не подозревали, мог превратить ваш компьютер в тыкву.
Неважно, какая проблема с системой виновата: сеть, электричество или ретроградный Меркурий.
Из этого определения следует, что любой сайт — это распределенная система.
Схема его работы включает в себя клиентское устройство и хост-машину, к которой оно подключается.
Если хост выйдет из строя, сайт не будет работать.
Распределена ли какая-либо система, в которой задействовано более двух аппаратных средств? Почти.
Давайте посмотрим на пример Redis Cluster. Он вводит подтипы распределенных систем, для классификации которых требуется теорема CAP. Оно описывает главное свойство распределенных систем — согласованность.
Википедия разбивает согласованность на три отдельные концепции: «…согласованность данных друг с другом, целостность данных и внутренняя согласованность».
Рассмотрим пример с обычной реляционной базой данных социальной сети.
В нем есть таблица с пользователями и отдельная таблица с друзьями (парами ID).
В этом случае честность означает, что таблица с парами подключений не будет содержать идентификаторы, которых нет в таблице с пользователями.
А если пользователь уйдет, то пары с ним либо будут удалены, либо не будут учитываться.
Возможности подключения означает, что если первый пользователь является другом второго, то второй также является другом первого.
Пары облигаций согласуются друг с другом.
Правило последовательность требует, чтобы если один пользователь удалит другого, вся связь также будет удалена.
В действительности консистенция варьируется.
То, что это большое дерево из Jepsen.io подсвечено зеленым, — это какая-то нормальная последовательность, а все под ним — технические детали, которые его приближают.
Теорема CAP
В Теорема CAP используется линеаризуемая консистенция.
Приведем пример, когда это свойство отсутствует.
Предположим, что в распределенной системе есть три узла: лидер и два последователя.
Судья сказал, что Германия выиграла футбольный матч.
Вставка произошла на лидере, на что он ответил успехом входа, но не стал выкатывать изменения на всех последователей сразу.
Алиса зашла и увидела победу Германии, а Боб увидел, что матч все еще продолжается — изменение дошло не до всех последователей.
Если бы последовательность в этой системе была линеаризуемой, то оба участника прочитали бы о победе Германии.
Для обеспечения линейноразлагаемой согласованности важно, чтобы лидер узла успешно реагировал после развертывания на все узлы.
Второе свойство — это толерантность к разделению, или устойчивость к разделению сети или нестабильности сети.
Например, есть два узла, соединенных кабелем.
Если его разрезать, произойдет такое же деление сети.
Будет два контура со множеством серверов в каждом.
Каждый узел должен будет решить для себя, как обеспечить соблюдение двух других свойств теоремы CAP. Устойчивость означает, что система знает, как действовать в такой ситуации.
Последнее свойство — доступность.
Система ответит быстро, но без гарантии, что это будет быстро и со свежими данными.
Линейной последовательности не ожидается.
Теорема CAP утверждает принцип тройного ограничения: можно получить только два свойства из трех.
Системы делятся на CP, CA и AP. Все системы стараются охватить сразу два объекта недвижимости, а не один.
Давайте рассмотрим самые простые примеры.
В PostgreSQL при синхронной репликации лидер и ведомый тесно связаны, то есть лидер закроет транзакцию только после получения ответа от ведомого.
Если кабель между ними оборвется, оба перестанут работать.
В теореме CAP этот образец работы соответствует согласованности и доступности (CA).
В случае асинхронной репликации изначально предусмотрен разрыв, и может случиться тот же инцидент с футбольным матчем.
Если возникнут проблемы с сетью, реплики продолжат отвечать в предоставленном окне.
Однако данные будут не самыми последними.
Такая система называется AP: она устойчива к разделению сети и обеспечивает доступность, но не согласованность.
Оказывается, каждый раз, когда вы решаете задачу, вам нужно смотреть на теорему CAP, чтобы выбрать необходимые свойства.
Теорема PACELC
ПАСЕЛК заменил теорему CAP и расширил ее.Выпускает четыре типа систем.
В правом верхнем углу находятся системы 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, без еще одной буквы?
Обычно это происходит, когда кто-то не до конца разбирается в теме и решает разработать собственное решение.
Ребята из Jepsen.io провели анализ и сказали, что система устойчива к расщеплению.
В то же время он пытается вести себя как кластер.
А если половина узлов недоступна, он уже не сможет работать.
Это говорит о том, что Redis Cluster не является системой AP. Остался только один П.
Если мы используем WAIT, который мы добавили позже, когда закончили читать теорию, Redis Cluster станет CP.
Острова и мосты
Проектирование распределенных систем и проверка согласованности — хорошая инженерная задача.Во время анализа человеческому разуму необходима какая-то аналогия.
Проблема обедающих философов является хорошим примером этого.
Будет аналогия в виде островов и мостов между ними.
Острова живут как одно государство с общим сводом законов.
И каждый остров хочет влиять на эти законы.
Но не съездом в том же замке с распространением коронавируса, а отправкой посыльных как курьеров с едой.
И они будут перемещаться между островами по мостам.
На каждом острове мы сохраним свой собственный свод законов, но изменения будут заблокированы для всех.
Важно понимать, что здесь необходим консенсус чтения и консенсус записи.
Мы обязательно уточним, со скольких островов вам нужно получить информацию, чтобы заявить, что закон работает на 100%.
Нам нужно знать, сколько гонцов нужно отправить на другие острова, чтобы убедиться, что закон записан и теперь мы будем ему следовать.
Чтение – это сбор логов изменений законов к себе.
Запись - этот журнал изменений законов мы куда-то берем.
Это именно то, что представляют собой два консенсуса: чтение и письмо.
Если сменить острова на сервера, ничего не потеряется: как рассудили, так и останется.
Острова и мосты уже стали традицией.
Создатель этого алгоритма Лесли Лампорт использует аналогию из Алгоритм Паксоса .
Его конкретные реализации — ZAB (Apache ZooKeeper) и Raft. Если мы возьмем алгоритм, соответствующий Paxos, то на выходе будет CP. В спецификациях говорится, что Raft прост, но на самом деле его нелегко понять.
На сайте raft.github.io содержит классную настраиваемую анимацию браузера, с которой мы рекомендуем поиграть.
Упражняться
Теперь представим, что мы стажер, который впервые пришел на работу и впервые видит этот код. Напомним, модуль взят из курса «Разработчик Middle Python»: на входе он получает ссылку, на выходе выдает новый хеш, а при нажатии на хеш разворачивает его и дает редирект. Кажется, все просто – поехали! Перейти к прочтению.Здесь написано, что это код вебинара, и описано, как запустить Docker Compose, что упрощает взаимодействие сервисов друг с другом.
Автор сервиса оставил нам документацию - большое спасибо.
В этом заслуга FastAPI: документация генерируется автоматически.
У нас есть сервис и конфигурационные файлы.
Давайте разберём их.
В Dockerfile все классически: Python через pip и Pipenv, последний уже все остальное устанавливает, API запускается на порту 8080.
В файле docker-compose всё просто: Redis и наше Python-приложение.
Идите реализовывать это.
Мы находимся в начале приложения.
Есть несколько хуков для начала и конца, запуска и завершения работы.
И вот самое интересное: в этом фрезере присутствуют основные ручки.
Чуть не пропустил FastAPI. Кстати, что такое FastAPI? FastAPI — это крутой современный асинхронный фреймворк на Python. Внутри пидантик, генерация спецификаций OpenAPI (даже третьей версии, а не Swagger!).
Вы просто берете и используете: описываете пидантические входные и выходные данные для валидации и предоставляете готовую документацию для других модулей.
И в то же время он асинхронен, что позволяет дешево работать по сети.
Сейчас мы говорим о коде, который ожидает других операций: доступа к большому файлу на диске или сетевому ресурсу.
Итак, если у нас не монолитная структура, а микросервисная, то с точки зрения процессоров и серверов гораздо дешевле будет взять асинхронный фреймворк, потому что у него внутри есть цикл событий, что сэкономит время.
Мы не будем слишком углубляться в цикл событий, потому что мы подробно рассмотрим его в курсе — там есть основы.
Мы также коснемся сопрограмм, которые соединяются с Golang и каналами.
Вернемся к коду.
Нам нужны функции «создать», «проверить» и «перенаправить».
Это три функции.
Давайте посмотрим на то, что я считаю самым простым — создание URL-адреса.
Давайте поговорим о логике:
- запрос поступает и проверяется по URL-адресу;
- если данные подходят — то есть, например, не пусты — сжимаем URL в хэш и записываем его в Redis;
- затем мы указываем полный путь, хеш и URL-адрес, по которому вы можете перейти и получить перенаправление.
Внутри метода url_repository.create_url нет ничего умного.
Есть околослужебная информация, которую мы инициализировали.
Мы также отслеживаем столкновения.
Решаем проблему коллизий добавлением букв.
Мы не городим список и не хешируем ключ, а просто меняем ключ.
Во второй части поста мы расскажем, зачем нужно Dynamo и что делать, когда Redis несколько.
Теги: #python #программирование #redis #Высокая производительность #highload #cap #Яндекс.
мастерская #pacelc
-
Просто Обожаю Идею Партнерского Маркетинга!
19 Oct, 24 -
Ос Микротик Роутер. «Честный» Обмен Каналами
19 Oct, 24 -
Дайджест Laravel (19–25 Октября 2020 Г.)
19 Oct, 24 -
Метрики Рекомендательной Системы Imhonet.ru
19 Oct, 24 -
Рекомендации Любых Продуктов
19 Oct, 24 -
Семь Правил Предпринимателя От Стива Джобса
19 Oct, 24 -
Youtube Хочет Оставаться Независимым
19 Oct, 24 -
Дружественный Ии И Захват Вселенной
19 Oct, 24