Найти в Дзене

Лекция 2 Кеширование, API и Observability

Основные термины Какие данные кэшировать? Кэширование ошибок Кэшируем ошибки и тогда последующие запросы не будут обращаться к источнику информации, а также не будет cache miss attack !!! По-хорошему, нужно уметь держать нагрузку без кэша задача кэша - ускорить ответ, а не держать нагрузку проблема старта с непрогретым кэшем Всегда ли кэшированеи полезно? оценка эффективности кэширования AverageTime = DBAccessTime * CacheMissRate + CacheAccessTime Пусть: Тогда при CacheMissRate > 0.8 - кэш вреден! внутреннее кэширование кэш хранится внутри сервиса, (например ввиде хэщ-таблиц) или рядом на диске Плюсы: Минусы: внешнее кэширование кэш храниться в какой-то другой in-memory базе данных, севрис обраащеться к ней и воспринимате как кэш Плюсы: Минусы: Cache Aside(кэширование на стороне) В этой стратегии, приложение координирует запросы в кэш и БД и само решает, куда и в какой момент обращаться пайплайн чтения: Пайплайн записи: Cache through(Сквозное кэширование) В рамках этой стратегии все
Оглавление

Кеширование

Какие проблемы позволяет решать:

  1. Сокращение response-time сервисов,
  2. Снижение лишней нагрузки на сторонние сервисы,
  3. Переиспользование ранее полученных или вычисленных данных,
  4. Стабилизация работы при кратковременных отказах систем.

Основные термины

  • Cache miss --- промах кэша, запрошенный ключ не был найден в кэше
  • Cache hit --- попадание в кэш, запрошенный ключ найден в кэше
  • Hit ratio --- процент попаданий запросов в кэш, характеризизует эффективность кэширования
  • Горячий ключ --- ключ, на который приходиться большая часть запросов
  • Прогрев кэша --- процесс наполнения кэша данными
  • Инвалидация --- удаление кэшированных данных

Какие данные кэшировать?

  • меняются редко(дни, недели, месяцы) --- в данном случае можно спокойно кешировать эти данные
  • меняются нечасто(минуты, часы) --- чаще всего здесь задаемся вопросом - "стоит ли мне кэшировать"
  • меняются часто(секунды) --- кэшировтаь чаще всего бессмысленно, но иногда может пригодиться

Кэширование ошибок

Кэшируем ошибки и тогда последующие запросы не будут обращаться к источнику информации, а также не будет cache miss attack

!!! По-хорошему, нужно уметь держать нагрузку без кэша

задача кэша - ускорить ответ, а не держать нагрузку

проблема старта с непрогретым кэшем

  • предварительно загружаем данные в кэш часто используемых запросов

Всегда ли кэшированеи полезно?

оценка эффективности кэширования

AverageTime = DBAccessTime * CacheMissRate + CacheAccessTime

Пусть:

  • DBAccessTime = 100ms
  • CacheAccessTime = 20ms

Тогда при CacheMissRate > 0.8 - кэш вреден!

Виды кэширования

внутреннее кэширование

кэш хранится внутри сервиса, (например ввиде хэщ-таблиц) или рядом на диске

Плюсы:

  • Высокая скорость
  • Отсутствие сетевых запросов
  • Нет расходов на Marshaling / Unmarshaling данных

Минусы:

  • Горизонтальное мастшабирование
  • Прогрев кэша после падения сервиса

внешнее кэширование

-2

кэш храниться в какой-то другой in-memory базе данных, севрис обраащеться к ней и воспринимате как кэш

Плюсы:

  • Хранение большого объёма данных
  • Простое горизонтальное масштабирование
  • После падение сервиса данные кэша не теряются
  • Простой прогрев кэша и простая логика инвалидации

Минусы:

  • Скорость работы

Способы взаимодействия с кэшем

Cache Aside(кэширование на стороне)

В этой стратегии, приложение координирует запросы в кэш и БД и само решает, куда и в какой момент обращаться

пайплайн чтения:

-3

Пайплайн записи:

-4

Cache through(Сквозное кэширование)

В рамках этой стратегии все запросы от приложения проходят через кэш

пайплайн чтения:

-5

пайплайн записи:

-6

Cache Ahead(Опережающее кэширование)

Запросы на чтение всегда идут только в кэш, никогда не попадая в БД напрямую

-7

Резюме

  • Важно учитывать актуализацию данных
  • Стоит балансировать между характером нагрузки (какая нагрузка преобладает – чтение или запись)
  • Также не забыть про отказоустойчивость

Алгоритмы вытеснения данных

допустим наш кэш способен вмещать только 4 пользователей

-8

рассмотрим разные алгоритмы

Random

можно ли вытеснять рандомно?

можно, но вопрос в эффективности

FIFO

-9

первым зашел первым вышел

LIFO

-10

последним зашел первым вышел

LRU

-11

вытесняеться элемент к которому дольше всего не было обращений

MRU

-12

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

LFU

-13

ведется счетчик обращений к элементам, вытеснятеся тот к кому было меньше всего обращений

Second Chance

-14

При обращении выставляем бит присутствия, а при вытеснении удаляем из начала очереди, если бит = 0

Если бит = 1, то меняем бит на ноль, затем переносим элемент в конец очереди и идем к следующему

Clock

-15

Тот же Second Chance, только не нужно двигать элемент из начала в конец очереди, если бит равен единице

Используется циклическая очередь

2Q

-16

Элементы, запрошенные из 1FIFO, никуда не двигаются. Вытесненные из 1FIFO перемещаются в 2FIFO

Элементы, запрошенные из 2FIFO, уходят в LRU. Вытесненные из 2FIFO удаляются

SLRU

-17
  • Сперва кладем в первую коробочку.
  • При повторном запросе 
 перекладываем во вторую
  • При еще одном повторном 
 – из второй в третью

TLRU (Time aware LRU)

Абсолютно такой же алгоритм, только к данным добавляется их время жизни в кэше (TTL), 
 по которому они автоматически удаляются из кэша

LRU-k

Удаляет страницу, К-й последний доступ к которой находится дальше всего в прошлом. 

 Например, LRU-1 — это просто LRU, тогда как LRU-2 удаляет страницы в соответствии со временем их предпоследнего доступа

Инвалидация данных в кэше

Инвалидация по TTL 
 (Time To Live)

При сохранении данных в кэш для них устанавливается время жизни (TTL) и данные будут автоматически удалены через это время (основная проблема заключается в поборе TTL)

Jitter

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

Thundering herd problem

Резкий рост нагрузки на источник данных, который возникает, когда множество процессов/потоков одновременно запрашивают один ключ кэша, получают cache miss, а затем каждый из них выполняет 
 один и тот же запрос

Инвалидация по событию

-18

не устанавливаем время жизни данных, а удаляемых их по событию. Допустим у нас есть какой-то notifier (оповещатель). За ним есть брокер, который пойдет и поудаляет кэши по событию.

Версионирование кэша

К ключу кэширования добавляется версия: поэтому инвалидации всех ключей кэширования с префиксом достаточно инкрементировать версию ключа.

Тегирование кэша

-19

Многомерный кэш

Кэши могут складываться в цепочку или в дерево

когда, например, происходит обращение к какому-нибудь сервису:

  1. Кэш браузера
  2. Кэш прокси сервера
  3. Внутренний кэш приложения
  4. Внешний кэш приложения
  5. Кэш движка базы данных

API

CRUD

Акроним, обозначающий четыре базовые функции, используемые при работе с данными: создание (C), чтение (R), модификация (U), удаление (D)

REST

  • Глагол – метод запроса (GET, POST, DELETE, PUT)
  • Существительное – URI запроса
  • Дополнительная информация – хедеры запроса
  • Содержимое – тело запроса и ответа в Json
  • Результат – код ответа
-20

SOAP

старый, мало где используется

тоже что что и rest только всё храниться внутри xml.

-21

RPC

Класс технологий, позволяющих программам вызывать функции или процедуры в другом 
 адресном пространстве

gRPC

-22

описывается определенный формат ввиде protobuf, затем используется кодогенерация, в данном случае для языка программирвоания go

GraphQL

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

-23

Резюме

  1. SOAP уже умер
  2. REST для клиентского взаимодействия
  3. gRPC для внутреннего взаимодействия
  4. GraphQL для кастомизации запросов

Получение событий от сервера

Как переодически получать обновления от сервера?

-24
-25

Webhook

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

-26

Streaming

-27

SSE (Server Side Events)

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

WebSocket

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

Резюме

  • Polling --- используется, когда клиенту необходимо регулярно обновлять информацию
  • Streaming --- используется, когда клиенту необходимо получать непрерывный или хаотичный поток данных
  • Webhooks --- используются, когда серверу необходимо уведомить клиента о каком-то событии

Подходы проектирования API

Как отдавать большое количество сущностей через API?

Ответ: Пагинация

Большое количество сущностей отправляется клиенту по частям (чанками — chunks)

-28

Как улучшить производительность API?

Вариант №1

Запросы и ответы можно сжимать

Чем меньше размер данных, тем быстрее они передаются по сети

Сжатие ускоряет загрузку и скачивание данных

Вариант №2

Можно сохранять запрашиваемые данные в кэше у клиента

И возвращать их клиентам без повторного обращения к сервису

Как предотвратить повторное выполнение операции?

-29

ключ идемпотентности

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

-30

Как вносить изменения в API?

Версионирование API

Так как API со временем развивается, важно иметь стратегию управления версиями для управления будущими изменениями

Этот этап включает в себя реализацию механизмов управления версиями, включая номер версии

-31

Observability

Мониторинг

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

Методологии мониторинга:

LTES (Google SRE)

  • Latency – время на обработку одного запроса
  • Traffic – количество запросов
  • Errors – количество ошибок
  • Saturation – насколько компонент использует свои ресурсы

RED

  • Rate – количество запросов
  • Errors – количество ошибок
  • Duration – время обработки одного запроса

USE

  • Utilization – время или процент использования ресурса
  • Saturation – количество отложенной работы
  • Errors – количество ошибок

Нельзя сказать, что какая-то из этих методологий «правильная»

Каждый отдельный компонент системы нужно мониторить, основываясь на здравом смысле

Алертинг

Алертинг отслеживает изменения определенных метрик с помощью алертов и отправляет уведомления через подходящий для вас канал уведомлений 
 (основывается на концепциях SLI, SLA и SLO)

алерт должен срабатывать, когда возникла ошибка, но еще можно что-то исправить

а не когда «всё уже очень плохо» и не от каждой «помехи»

-32

Логирование

Логированием называют запись логов - оно позволяет ответить на вопросы, что происходило, когда и при каких обстоятельствах

Без логов сложно понять, из-за чего появляется ошибка, если она возникает периодически и только при определенных условиях

Логируем:

  1. ошибки и исключения
  2. события и действия пользователей
  3. запросы к серверу и сторонним ресурсам
  4. информацию о состоянии приложения

!!!Используем 
 уровни логирования

Персональные данные 
 не логируем

-33

Трейсинг

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

-34

строиться граф распределенных запросов который проще анализировать

сервисы отправляют спаны с единым индетификатором запроса

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

-35
-36
-37

Непрерывное профилирование

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

Допустим есть определенный сервис, который приходит к нашему приложению, и с помощью профилировщика снимает метрики памяти и cpu, допустим раз в 5 минут, тогда будет понятно, что так сильно измотало память или cpu перед неисправностью

-38
-39

Как надежно поставлять данные телеметрии?

-40
-41

есть подход связанный с агентами доставки данных телеметрии

агент - это sidecar, sidecar это такой патернн когда у вас например живете в k8s, и у вас рамках пода запущено несколько контейнеров, а вы можете в этот под подселить ещё контейнер который будет отвечать за какую-то инфраструктуру, в нашем случае за сбор телеметрии, ваше приложение будет просто писать в локалхост в какой-то порт и ничего не знать о надежности и всём таком. А ваш агент этот порт будет слушать, и сначала напишет в диск эти данные и потом из диска будет отправлять.