70 lines
6.4 KiB
Plaintext
70 lines
6.4 KiB
Plaintext
### Дизайн кэша для клиента kakoisegodnyaprazdnik.ru.
|
|
|
|
Мы исходим из следующих предпосылок:
|
|
1. Необходимо делать минимальное количество запросов, чтобы нас не забанили.
|
|
2. На каждый запрос мы меняем строку user-agent. Делаем выборку из списка в зависимости от номера дня в месяце.
|
|
3. Кэш актуален до ~ 0:01 следующего дня
|
|
|
|
В идеале в сутки делается всего один запрос в ихнее "api" (там на самом деле парсинг странцы, что какбэ не айс, но
|
|
ничего не поделать - api как таковое у них отсутствует).
|
|
|
|
### Техническая часть
|
|
Вроде как [pebble db](github.com/cockroachdb/pebble) показала себя как впорлне рабочее решение для хранения данных типа
|
|
key-value. Так что задействуем её.
|
|
|
|
Из минусов этого решения - в этой базе экспайринг ключей не предусмотрен в принципе. То есть именно сам экспайринг надо
|
|
проводить самостоятельно.
|
|
|
|
Технически это делать несложно. Берём базу cache и в неё складываем 2 k-v записи: prazdnikisegodhyaru_timestamp->date
|
|
и prazdnikisegodhyaru_value->value.
|
|
|
|
Далее, при любом обращении к клиенту, мы извлекаем prazdnikisegodhyaru_timestamp->date и сравниваем с датой
|
|
предполагаемого экспайра кэша, если извлечённая дата больше предполагаемая, достаём данные из кэша, если извлечённая
|
|
дата меньше или равна извлечённой, то делаем запрос в "api", складываем api в prazdnikisegodhyaru_value->value,
|
|
обновляем timestamp в prazdnikisegodhyaru_timestamp->date, а данные возвращаем в качестве ответа наверх, по цепочке.
|
|
|
|
## Дизайн кэша для клиента openweathermap
|
|
|
|
Здесь предпосылки другие:
|
|
|
|
1. Согласно показаниям openweathermap данные для "погоды в текущий момент времени" обновляются раз в три часа.
|
|
2. Делать много запросов и их api тоже нежелательно - они в ведут учёт запросов и там есть верхнее ограничение, которое
|
|
сбрасывается раз в месяц.
|
|
3. Точных моментов времени, когда происходит обновление данных они не приводят.
|
|
|
|
### Техническая часть
|
|
|
|
Таже самая pebbledb, заводить новую смысла особого нету. Название базы тоже cache.
|
|
|
|
Кэшировать имеет смысл не более, чем на 3 часа. Слишком большой ttl кэша приведёт к "неправдаподобности", особенно в
|
|
ситуациях, когда мы запросили данные в когда они "скоро протухнут" на источнике. Слишком малое значение ttl снижает
|
|
эффективность кэша. В перловой реализации мы брали 3 часа, выглядит, как отличной вариант для начала.
|
|
|
|
Далее, реализация. Важным моментом является ключ. Ключ должен содержать в себе данные, уникальные для типа запроса.
|
|
То есть, собственно имя города. В нашем случае имя города, после "нормализации". Собственно, ключ будет содержать имя
|
|
города + тип значения, от кторого взята sha256, например, sha256(London+timestamp) или sha256(Tokyo+value) (sha256 на
|
|
себя берёт враппер бд - функции GetValue и saveKeyWithValue).
|
|
|
|
(В идеале, было бы неплохо составить табличку с названиями городов на разных языках, которые мапятся либо в одно
|
|
название, либо в geo координаты, тогда эффективность кэша будем максимальной, но для этого нужна либо периодическая
|
|
джоба, которая обновляет соответсвующий кэш, либо обновлять его on-request, по мере протухания).
|
|
|
|
N.B. вероятность коллизий sha256 сравнительно минимальна, но она есть, поэтому timestamp необходимо проверять на
|
|
валидность формата. Тоже касается и прогнозов погоды. Проверки по длине вполне хватает.
|
|
|
|
### Механика взаимодействия с кэшом
|
|
|
|
На поступивший запрос мы
|
|
|
|
1. извлекаем из базы timestamp
|
|
1. если timestamp валиден
|
|
1. если он не просрочен, извлекаем из базы значение, если
|
|
1. оно валидно, отправляем его в качестве ответа
|
|
2. если оно не валидно, делаем запрос в api, обновляем кэш
|
|
2. если timestamp просрочен делаем запрос в api, обновляем кэш
|
|
2. если timestamp не валиден, делаем запрос в api, обновляем кэш
|
|
2. если извлеклась пустая строка, делаем запрос в api, обновляем кэш
|
|
|
|
Обновление кэша подразумевает вычисление timestamp, когда он должен просрочиться (текущее время + ttl), обновление
|
|
2-х ключей в кэше: city+timestamp и city+value.
|