Struchkov Mark
bd6b7c1492
All checks were successful
continuous-integration/drone/push Build is passing
64 lines
6.3 KiB
Markdown
64 lines
6.3 KiB
Markdown
---
|
||
aliases:
|
||
tags:
|
||
- maturity/🌱
|
||
date: 2024-09-13
|
||
zero-link:
|
||
- "[[../../../meta/zero/00 HighLoad|00 HighLoad]]"
|
||
parents:
|
||
- "[[Кэширование]]"
|
||
linked:
|
||
---
|
||
Представим, что нам нужно кэшировать результат работы следующего метода:
|
||
|
||
```java
|
||
public List<User> getUsersByType(String userType, Set<Long> userIds)
|
||
```
|
||
|
||
Метод принимает 2 аргумента: строку и коллекцию. Ключ кэширования должен учитывать значения этих входящих аргументов и должен обладать следующими свойствами:
|
||
- При изменении параметров, ключ кэширования также должен изменяться. В данном случае, если изменятся значения аргументов `userType` и `userIds`, мы должны получить новое значение ключа.
|
||
- По параметрам ключ должен определяться однозначно, то есть для одних и тех же значений аргументов ключ кэширования должен принимать только одно значение. Иначе мы рискуем понизить эффективность процесса кэширования, создавая несколько кэшей для одной и той же выборки.
|
||
|
||
Сформируем ключ кэширования для нашего метода. В качестве хранилища будем использовать [[Redis]].
|
||
|
||
В начале ключа я обычно обязательно указываю какой-то уникальный префикс сервиса, чтобы не получить коллизию между разными сервисами. Пускай в данном случае префикс будет `USER_SERVICE`. Также добавляю уникальный префикс метода, в данном случае будет `USERS`.
|
||
|
||
В качестве разделителей рекомендую использовать `:`, в [[../../../../../_inbox/Redis|Redis]] это позволяет визуально сгруппировать ключи. Это позволяет визуально группировать ключи при использовании UI клиента. Таким образом начало нашего ключа выглядит следующим образом: `USER_SERVICE:USERS:`.
|
||
|
||
Значения аргументов метода также должны попасть в ключ. Возьмем наш первый аргумент `String userType`. Для аргумента также можно использовать префиксы, но это не обязательно. В данном случае пусть будет `USER_TYPE`. А вот для самого значения параметра есть несколько вариантов:
|
||
- Оставить строкой и просто выполнить конкатенацию.
|
||
- Использовать [[../../cryptography/Криптографическая хеш-функция|хеш-функцию]] с фиксированной длиной выхода, например [[../../cryptography/MD5|MD5]]. Фиксированная длина выхода нужна, чтобы иметь предсказуемую и ограниченную длину ключа.
|
||
|
||
Оставим просто строкой, так как тип пользователя вряд ли может быть длинным. В итоге пока наш ключ выглядит как-то так: `USER_SERVICE:USERS:USER_TYPE:VIP:`.
|
||
|
||
Переходим ко второму аргументу `Set<Long> userIds`. С коллекцией все будет сложнее. Мы точно должны использовать какую-нибудь [[../../cryptography/Криптографическая хеш-функция|хеш-функцию]], но как?
|
||
|
||
> [!WARNING] Disclamer
|
||
> Этот способ я придумал сам, возможно он не самый удачный, но он работает. Если вы придумаете лучше, напишите в комментариях ниже 👇
|
||
|
||
Во-первых, коллекцию необходимо предварительно отсортировать. Иначе на одинаковые параметры коллекций мы будем получать разные результаты [[../../cryptography/Криптографическая хеш-функция|хеш-функции]].
|
||
|
||
Во-вторых, нужно представить коллекцию как что-то понятное для [[../../cryptography/Криптографическая хеш-функция|хеш-функции]]. Для этого я преобразую коллекцию в JSON. JSON используется, потому что ваша коллекция может быть из сложных объектов.
|
||
|
||
Теперь используем [[../../cryptography/SHA-256|SHA-256]], чтобы из нашей строки получить какой-то хеш. И уже этот хеш мы добавляем к нашему ключу, получается примерно такое:
|
||
|
||
```
|
||
USER_SERVICE:USERS:USER_TYPE:VIP:USER_ID:315f5bdb76d078c43b8ac0064e4a0164612b1fce77c869345bfc94c75894edd3
|
||
```
|
||
|
||
> [!QUESTION] Почему SHA-256, а не MD5?
|
||
> [[../../cryptography/MD5|MD5]] подвержен коллизиям, [[../../cryptography/SHA-256|SHA-256]] считается более устойчивым к коллизиям.
|
||
|
||
|
||
***
|
||
## Мета информация
|
||
**Область**:: [[../../../meta/zero/00 HighLoad|00 HighLoad]]
|
||
**Родитель**:: [[../Кэширование|Кэширование]]
|
||
**Источник**::
|
||
**Создана**:: [[2024-09-13]]
|
||
**Автор**::
|
||
### Дополнительные материалы
|
||
- [[../../snippet/Реализация SHA-256 на Java|Реализация SHA-256 на Java]]
|
||
### Дочерние заметки
|
||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|