Мой взгляд на кэш в памяти

· 3 мин чтения

Я работал над некоторыми вещами, которые обрабатывали большой объем данных. Делая это, я понял, что большая часть этого никогда не меняется, или, по крайней мере, в течение определенного времени это не так.

Поэтому я подумал, что было бы полезно создать личный репозиторий кэша, конечно, это не ново, несколько недель назад я прочитал об этом в [посте] StackOverflow (https://nickcraver.com/blog/2019/08/06/stack-overflow-how-we-do-app-caching/#in-memory--redis-cache), написанном Ником Крейвером о том, как они управляют кешем приложений.

Кроме того, я всегда хотел разобраться с кешем, узнать, как он работает, его логику и как заставить его работать, так… почему бы и нет!

Поток

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

Изображение от Gyazo

Реализация

Прежде чем мы начнем

Я знаю, я знаю. Есть System.Runtime.Caching, который обрабатывает кеш памяти. Но я решил создать его сам. Если вы хотите использовать этот класс, проверьте здесь инструкции.

###Элемент кэша

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

[[[ТОК_6]]]

###Репозиторий кэша

Затем нам нужен класс, который обрабатывает объекты и где-то их сохраняет (как CacheItem). Мне нравится обрабатывать все данные/модели в классах, имеющих суфикс Repository, но это не обязательно, поэтому давайте создадим один для кэширования.

[[[ТОК_9]]]

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

Имейте в виду, что элемент Cache будет инициализирован после загрузки класса CacheRepository.

Единственный метод, доступный при вызове класса CacheRepository, — это GetOrSet(string key, Func<T> lookup, TimeSpan durationMinutes) для которого требуется три параметра:

  1. key: идентификатор объекта для сохранения.
  2. lookup: функция обратного вызова в случае, если срок действия кеша истек или он равен нулю.
  3. durationMinutes: продолжительность в минутах, которая будет добавлена ​​к текущему времени (в формате UTC).

Время кэширования

Теперь используйте наш репозиторий кэширования, чтобы получить откуда-нибудь данные.

Чтобы все это имело смысл, давайте создадим пример объекта с некоторыми свойствами, а затем репозиторий для извлечения и заполнения списка этого объекта.

public class User 
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public string Email { get; set; }
}
public class UserRepository 
{
    public List<User> Get()
    {
        // Code to get users
    }
}

Поскольку у нас есть метод заполнения списка User, давайте воспользуемся классом CacheRepository.

private UserRepository _userRepository = new UserRepository();
private List<User> _user;
public List<User> User
{
    get
    {
        _user = CacheRepository.GetOrSet($"users", usersRepo.Get, TimeSpan.FromMinutes(10));
        return _user;
    }
}

И точно так же, каждый раз, когда вы обращаетесь к переменной User, она запрашивает у CacheRepository значение объекта, имеющего ключ users.

Если этот ключ существует, он проверит дату истечения срока действия. Если какое-либо из этих условий ложно, он будет использовать обратный вызов для установки значения (с помощью usersRepo.Get) объекта, сохранения его в кэше с датой истечения срока действия, установленной в DateTime.UtcNow + TimeSpan.FromMinutes(10) и возврата его.