digital-garden/_inbox/Кэширование.md

74 lines
8.8 KiB
Markdown
Raw Normal View History

2024-06-13 21:01:37 +03:00
---
aliases:
tags:
- зрелость/🌱
date:
- - 2024-05-24
zero-link:
- "[[00 Архитектура ПО]]"
- "[[00 HighLoad]]"
parents:
linked:
---
Для каждого ресурса критичной для пользователя является такая характеристика, как время отклика сервера ([Latency](Latency.md)). Увеличение времени отклика сервера приводит к оттоку посетителей. Следовательно, необходимо минимизировать время отклика: для этого необходимо уменьшать время, требуемое на формирование ответа пользователю, при этом для формирования ответа пользователю необходимо получить данные из каких-то внешних ресурсов ([Бэкенд](Бэкенд.md)).
Ускорить сложные запросы может кэширование: мы помещаем результат вычислений в некоторое хранилище (например, [Memcached](Memcached.md) или [Redis](Redis.md)), которое обладает отличными характеристиками по времени доступа к информации. Теперь вместо обращений к медленным, сложным и тяжелым backendам нам достаточно выполнить запрос к быстрому кэшу.
2024-06-17 18:52:16 +03:00
![](Pasted%20image%2020240617184722.png)
2024-06-17 19:12:16 +03:00
Система должна уметь выдерживать нагрузку и без кэша. Задача кэша ускорить ответ, а не держать нагрузку.
2024-06-17 18:52:16 +03:00
Кэширование основывается на [принципе локальности](Принцип%20локальности.md).
2024-06-17 18:42:04 +03:00
==Системы используемые для кэширования обычно не являются надежными, так что не следует хранить только там какие-то важные данные.== Данные можно разделить на несколько категорий:
2024-06-13 21:01:37 +03:00
- «**Можно потерять**». К этой категории относятся кэши выборок из базы данных. Потеря таких ключей не так страшна, потому что мы можем легко восстановить их значения, обратившись заново к backendу. Однако частые потери кэшей приводят к излишним обращениям к БД.
- «**Не хотелось бы потерять**». Здесь можно упомянуть счетчики посетителей сайта, просмотров ресурсов и т.п. Хоть и восстановить эти значения иногда напрямую невозможно, но значения этих ключей имеют ограниченный по времени смысл: через несколько минут их значение уже неактуально, и будет рассчитано заново.
- «**Совсем не должны терять**». Кэш удобен для хранения сессий пользователей. Однако содержимое сессий не хотелось бы терять никогда иначе пользователей на сайте будет «разлогинивать». Как попытаться избежать? Можно кластеризовать систему кэширования, так вероятность потери снижается.
2024-06-17 19:52:16 +03:00
## Уровни кэширования
![](Pasted%20image%2020240617195054.png)
2024-06-17 19:42:16 +03:00
- [Кэширование в браузере](Кэширование%20в%20браузере.md)
2024-06-17 19:57:16 +03:00
- [Кэширование на стороне клиента Nginx](Кэширование%20на%20стороне%20клиента%20Nginx.md)
- [Кэширование на стороне Nginx](Кэширование%20на%20стороне%20Nginx.md)
- [Content Delivery Network](Content%20Delivery%20Network.md)
- [Кэширование на сервере](Кэширование%20на%20сервере.md)
2024-06-17 19:47:16 +03:00
Виды кэширования:
2024-06-17 19:52:16 +03:00
- Сквозное. Все запросы проходят через кэш. [Схема](Pasted%20image%2020240617194731.png).
- Кэширование на стороне сервиса. [Схема](Pasted%20image%2020240617194759.png).
- Опережающее. Кладем данные в кэш заранее. [Схема](Pasted%20image%2020240617194938.png).
2024-06-13 21:01:37 +03:00
## Ключ кэширования
Ключ кэширования должен обладать следующими свойствами:
- При изменении параметров выборки, которую мы кэшируем, ключ кэширования должен изменяться (чтобы с новыми параметрами мы не «попали» в старый кэш).
- По параметрам выборки ключ должен определяться однозначно, т.е. для одной и той же выборки ключ кэширования должен быть только один, иначе мы рискуем понизить эффективность процесса кэширования, создавая несколько кэшей для одной и той же выборки.
Можно использовать следующий вариант (пример для PHP): если существует некоторая точка в коде, через которую проходят все обращения к БД, а любое обращение полностью описывается (содержит все параметры запроса) в некоторой структуре `$options`, можно использовать следующий ключ:
```php
$key = md5(serialize($options))
```
Такой ключ удовлетворяет первому условию% при изменении `$options` будет обязательно изменен `$key`, но и второе условие будет соблюдаться, если мы будем все типы данных в $options использовать «канонически», т.е. не допускать строки `"1"` вместо числа `1`. Функция `md5` используется для «сжатия» данных.
## Инвалидация
Если мы закэшировали какие-то данные от backendа, например, выборку из БД, рано или поздно исходные данные изменяются, и кэш перестает быть валидным. Причем очень желательно, чтобы кэш сбрасывался сразу же за изменением.
Один из подходов это инвалидация по времени. Для кэшированных данных устанавливается TTL, и по прошествию времени кэш удаляется. Такое вариант подходит для редко изменяемых данных, устаревание которых не приводит к серьезным проблемам в бизнес-логике, например словари. При таком варианте важно подобрать оптимальное время жизни кэша, слишком маленькое время жизни будет давать плохую производительность, слишком большое ухудшит опыт пользователей.
2024-06-17 18:57:16 +03:00
Первый вариант не подходит. Некоторые чуствительные данные нужно инвалидировать их сразу при изменении. Тут может помочь тегирование ключей.
Инвалидация:
- По истечению срока жизни - TTL
- Принудительный вызов команды инвалидации
- Алгоритмы вытеснения
Алгоритмы вытеснения:
- Алгоритм Белади. Несуществующий идеальный алгоритм. Храним только нужную информацию, не нужную не храним.
- [Least Recently Used](Least%20Recently%20Used.md)
2024-06-17 19:07:16 +03:00
- [Most Recently Used](Most%20Recently%20Used.md)
2024-06-17 19:12:16 +03:00
- [Last Frequently Used](Last%20Frequently%20Used.md)
2024-06-17 20:22:59 +03:00
- [Adaptive Replacement Cache](Adaptive%20Replacement%20Cache.md)
## Cache miss