Рубрики
Без рубрики

Выбор кэша – возможности

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

Выбор кэша (Серия из 2 частей)

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

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

Зачем кэшировать?

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

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

  • Каталог
  • Тележка
  • Проверка
  • Ценообразование
  • Платеж

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

  1. Данные о ценах должны быть доступны : если служба ценообразования не работает, оформление заказа завершится неудачей, как и продажа.
  2. Данные о ценах должны быть доступны быстро : если услуга запущена, но пользователь ждет слишком долго, он может отказаться. Хотя термин “длительный” субъективен, задержка в 100 мс оказывает решающее влияние на продажи .

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

Следовательно, кэширование – это компромисс, при котором вы принимаете устаревшие данные, чтобы они были доступны/быстро.

Обязательные функции кэша

Вы, вероятно, знакомы с цитатой “Не создавайте свою собственную криптографическую библиотеку”. Это намекает на то, что разработка такой библиотеки может показаться простой на первый взгляд, но, скорее всего, вы совершите серьезную ошибку в области безопасности, если вы не являетесь экспертом по безопасности – и даже в этом случае. Вам также не следует создавать свой собственный кэш, но по несколько иным причинам.

Вы можете подумать, что кэш – это просто хранилище ключей и значений в памяти. Это то, что в точности представляет собой структура данных хэш-таблицы. В зависимости от языка структура имеет другое название: карта в Go, словари в Python, HashMap в Ява и Ржавчина , Хэш в Ruby и т.д. Каким бы ни был стек, мы можем смоделировать кэш с такими структурами.

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

Ограничение по размеру

Давайте начнем с простой функции.

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

Стратегия (стратегии) выселения

Когда размер кэша достигает предельного размера, какую запись мы удаляем при поступлении новой записи? Выбор записи для удаления известен как стратегия выселения . Пара таких стратегий довольно широко распространена:

Случайный … наугад
ФИФО Сохраняйте записи хэш-таблицы в связанном списке для поддержки обхода порядка вставки … который был впервые добавлен в кэш
ЛИФО Храните записи хэш-таблицы в структуре стека для поддержки обхода в обратном порядке вставки … это было _last_ добавлено в кэш
ЛРУ Храните дополнительное поле метки времени с каждой записью и обновляйте его каждый раз, когда к нему обращаются, и используйте алгоритм выборки, чтобы найти приблизительно самую низкую метку времени, или используйте упорядоченную структуру данных вместо хэш-таблицы, чтобы найти точно самую низкую метку времени …это был наименее недавно доступный
ЛФУ Храните дополнительное поле счетчика с каждой записью и увеличивайте его каждый раз, когда к нему обращаются, и используйте алгоритм выборки, чтобы найти приблизительно наименьшее количество или используйте упорядоченную структуру данных вместо хэш-таблицы, чтобы найти точно наименьшее количество … это наименее часто посещаемый

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

Время-Жить

Возможно, вы знаете об этой цитате:

В информатике есть две трудные вещи:

  1. Аннулирование кэша
  2. Называние вещей
  3. И отдельные ошибки

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

Возможной реализацией является добавление поля к каждой записи: отметка времени, когда запись истечет (текущее время + TTL ). Поток может время от времени посещать записи и нетерпеливо удалять просроченные. В качестве альтернативы, кэш может лениво удалять записи с истекшим сроком действия, когда ему требуется больше места.

Другие критерии

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

Конфигурация

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

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

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

Интеграция с абстракциями кэша

Экосистема JVM имеет официальный API кэша, известный как Cache или JSR 107. Это спецификация с API, которая описывает четыре аннотации, т. Е. , @cacheresult , @CachePut , @cacheremove , и @cacheremoveall . Поставщики должны реализовать спецификацию.

Фреймворк Spring довольно широко распространен в экосистеме JVM. Он также предоставляет API кэширования. Исторически сложилось так, что он предшествовал JCache. Несмотря на то, что API отличается, он очень похож на кэши. Spring предлагает готовый код интеграции для нескольких кэшей, в то время как несколько других обеспечивают интеграцию Spring.

Улавливание закономерностей

Я описал несколько шаблонов кэширования в следующем выступлении.

Поскольку это довольно долго, вот краткое изложение:

  • Кэш-В сторону
  • Сквозной кэш
  • Считывание
  • Обновление – Впереди
  • Кэш-Опережающий

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

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

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

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

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

Кроме того, при достаточно большой емкости хранилища можно использовать кэш в качестве базы данных в памяти. Кэш – это хранилище значений ключа: обычно используется для извлечения записи по ее ключу. Исторически базы данных имели гораздо больший объем и предоставляли возможности для запросов, т. Е. , ВЫБЕРИТЕ *ИЗ Foo . Следовательно, распределенный кэш также может предоставлять такие возможности с помощью выделенного API или синтаксиса, подобного SQL.

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

С распределенным кэшем архитектура является клиент-серверной: приложение является клиентом; кэш является сервером. Чтобы максимизировать свои инвестиции, вы, вероятно, захотите поделиться своими данными с несколькими клиентами. Клиенты могут принадлежать к разным языкам, языкам Java и JVM, но также и другим: C#, C, C++, Ruby, Python, Go, Rust, Erlang и т.д. Стоит проверить, какие привязки предлагает кэш в отношении языков, которые вы используете.

Конечно, ни одна из этих функций не является “бесплатной”. Распределенный кэш – это распределенная система, и в ней есть все их подводные камни . Одним из важных критериев для изучения является то, как узлы образуют кластер по сети. Например:

  • Существует ли механизм автоматического обнаружения?
  • Если да, то можно ли его отключить?
  • Можно ли настроить несколько кластеров в одной сети?
  • Работает ли это на Kubernetes?
  • и т.д.

Неблокирующий API

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

Вам необходимо учитывать несколько аспектов; наиболее важным из них является API, используемый кэшем. Например, для CompletableFuture требуется Java 8. В зависимости от используемого стека вы можете выбрать кэш, который интегрируется с RxJava, Project Reactor, сопрограммами Kotlin или любой их комбинацией.

Стандартные показатели здоровья проекта

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

  • Лицензия : в основном с открытым исходным кодом по сравнению с коммерческим, но в зависимости от вашего использования не каждая лицензия с открытым исходным кодом совместима
  • Ценообразование , если коммерческое
  • Срок реализации проекта : проверьте дату начала проекта. Причина в том, что вы, вероятно, можете больше полагаться на “старый” проект, чем на созданный вчера.
  • Деятельность :

    • Количество основных коммиттеров – коэффициент шины
    • Количество непрофильных коммиттеров
    • История фиксаций коммиттеров
    • Количество открытых вопросов
    • Среднее время для их исправления
    • Если основной комитет прекратил работу над проектом
    • и т.д.
  • Документация : хотя этот термин является очень общим, хорошая документация составлена из справочных материалов , учебных пособий , практические руководства и объяснения . Если вы никогда раньше не сталкивались с этими условиями, прочитайте эту страницу или посмотрите это видео . Я начал получать документацию только после просмотра выступления.

  • Сообщество : насколько оно велико? Насколько активен? Насколько это полезно?

  • Поддержка : каковы каналы поддержки? Стековый поток? Группы Google? Слабину? Как часто вопросы получают ответ?

  • и т.д.

Вывод

В этом посте я описал несколько критериев, на которых следует основывать свой выбор поставщика кэша. Я попытаюсь перечислить и сравнить наиболее распространенных поставщиков кэша с открытым исходным кодом в экосистеме JVM в следующем посте.

Большое спасибо моему коллеге Марко Топольнику за его отзыв.

Чтобы идти дальше:

Первоначально опубликовано на Помешанный на Java 24 октября th , 2021

Выбор кэша (Серия из 2 частей)

Оригинал: “https://dev.to/nfrankel/choosing-a-cache-capabilities-4773”