TG Telegram Group & Channel
C# 1001 notes | United States America (US)
Create: Update:

📌 Задача: "Высоконагружённый кэш с автоматической очисткой и конкурентным доступом"

❗️Условие:

Реализуйте класс SmartCache<TKey, TValue> в .NET, который должен:

- Позволять безопасно добавлять и получать элементы из кэша в многопоточной среде (`Get`, `Set`).
- Автоматически удалять элементы через N секунд после их добавления (TTL).
- Поддерживать высокую производительность при массовом доступе (тысячи операций в секунду).
- Минимизировать блокировки (`lock`) или использовать неблокирующие структуры.
- Корректно работать с истекшими элементами:
- Не возвращать их через Get.
- Не копить мусор в памяти.

---

▪️ Ограничения:

- Можно использовать стандартные коллекции .NET (`ConcurrentDictionary`, Timer, Task, CancellationToken и т.д.).
- Нельзя использовать внешние библиотеки типа MemoryCache, Redis, LazyCache и др.
- Нужно поддерживать работу под большой нагрузкой (много ключей и операций параллельно).

---

▪️ Подсказки:

- Для конкурентного доступа подойдёт ConcurrentDictionary<TKey, ValueWithExpiry>.
- Для очистки устаревших данных:
- Можно использовать фоновую задачу (`Task`) с таймером, которая периодически чистит старые записи.
- Обратите внимание на гонки состояний: между проверкой срока жизни элемента и его удалением.

---

▪️ Что оценивается:

- Умение проектировать потокобезопасные структуры данных.
- Продуманность балансировки между скоростью операций и частотой очистки.
- Правильная работа со временем жизни (`TTL`).
- Чистота и лаконичность кода.

---

▪️ Разбор возможного решения:

▪️ Основная идея:

- В кэше храним не просто значение, а пару (значение + время истечения).
- При Get(key):
- Проверяем, истёк ли элемент.
- Если истёк — удаляем его и возвращаем null или default.
- При Set(key, value):
- Сохраняем значение с текущим временем + TTL.
- Отдельная фоновая задача (`Task`) регулярно сканирует кэш и удаляет устаревшие элементы.

▪️ Мини-пример структуры:


using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;

public class SmartCache<TKey, TValue>
{
private readonly ConcurrentDictionary<TKey, (TValue Value, DateTime Expiry)> _cache = new();
private readonly TimeSpan _ttl;
private readonly CancellationTokenSource _cts = new();

public SmartCache(TimeSpan ttl)
{
_ttl = ttl;
StartCleanupTask();
}

public void Set(TKey key, TValue value)
{
_cache[key] = (value, DateTime.UtcNow.Add(_ttl));
}

public TValue Get(TKey key)
{
if (_cache.TryGetValue(key, out var entry))
{
if (entry.Expiry > DateTime.UtcNow)
{
return entry.Value;
}
else
{
_cache.TryRemove(key, out _);
}
}
return default;
}

private void StartCleanupTask()
{
Task.Run(async () =>
{
while (!_cts.Token.IsCancellationRequested)
{
foreach (var key in _cache.Keys)
{
if (_cache.TryGetValue(key, out var entry) && entry.Expiry <= DateTime.UtcNow)
{
_cache.TryRemove(key, out _);
}
}
await Task.Delay(TimeSpan.FromSeconds(30), _cts.Token); // периодическая очистка
}
});
}

public void Dispose()
{
_cts.Cancel();
}
}

📌 Важные моменты:

- Кэш конкурентный (`ConcurrentDictionary`) — доступ без явных блокировок.
- Периодическая чистка не мешает основным операциям.
- Удаление истёкших элементов происходит "мягко" (через проверку срока жизни).
- Фоновая задача корректно завершается через CancellationToken.

📌 Задача: "Высоконагружённый кэш с автоматической очисткой и конкурентным доступом"

❗️Условие:

Реализуйте класс SmartCache<TKey, TValue> в .NET, который должен:

- Позволять безопасно добавлять и получать элементы из кэша в многопоточной среде (`Get`, `Set`).
- Автоматически удалять элементы через N секунд после их добавления (TTL).
- Поддерживать высокую производительность при массовом доступе (тысячи операций в секунду).
- Минимизировать блокировки (`lock`) или использовать неблокирующие структуры.
- Корректно работать с истекшими элементами:
- Не возвращать их через Get.
- Не копить мусор в памяти.

---

▪️ Ограничения:

- Можно использовать стандартные коллекции .NET (`ConcurrentDictionary`, Timer, Task, CancellationToken и т.д.).
- Нельзя использовать внешние библиотеки типа MemoryCache, Redis, LazyCache и др.
- Нужно поддерживать работу под большой нагрузкой (много ключей и операций параллельно).

---

▪️ Подсказки:

- Для конкурентного доступа подойдёт ConcurrentDictionary<TKey, ValueWithExpiry>.
- Для очистки устаревших данных:
- Можно использовать фоновую задачу (`Task`) с таймером, которая периодически чистит старые записи.
- Обратите внимание на гонки состояний: между проверкой срока жизни элемента и его удалением.

---

▪️ Что оценивается:

- Умение проектировать потокобезопасные структуры данных.
- Продуманность балансировки между скоростью операций и частотой очистки.
- Правильная работа со временем жизни (`TTL`).
- Чистота и лаконичность кода.

---

▪️ Разбор возможного решения:

▪️ Основная идея:

- В кэше храним не просто значение, а пару (значение + время истечения).
- При Get(key):
- Проверяем, истёк ли элемент.
- Если истёк — удаляем его и возвращаем null или default.
- При Set(key, value):
- Сохраняем значение с текущим временем + TTL.
- Отдельная фоновая задача (`Task`) регулярно сканирует кэш и удаляет устаревшие элементы.

▪️ Мини-пример структуры:


using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;

public class SmartCache<TKey, TValue>
{
private readonly ConcurrentDictionary<TKey, (TValue Value, DateTime Expiry)> _cache = new();
private readonly TimeSpan _ttl;
private readonly CancellationTokenSource _cts = new();

public SmartCache(TimeSpan ttl)
{
_ttl = ttl;
StartCleanupTask();
}

public void Set(TKey key, TValue value)
{
_cache[key] = (value, DateTime.UtcNow.Add(_ttl));
}

public TValue Get(TKey key)
{
if (_cache.TryGetValue(key, out var entry))
{
if (entry.Expiry > DateTime.UtcNow)
{
return entry.Value;
}
else
{
_cache.TryRemove(key, out _);
}
}
return default;
}

private void StartCleanupTask()
{
Task.Run(async () =>
{
while (!_cts.Token.IsCancellationRequested)
{
foreach (var key in _cache.Keys)
{
if (_cache.TryGetValue(key, out var entry) && entry.Expiry <= DateTime.UtcNow)
{
_cache.TryRemove(key, out _);
}
}
await Task.Delay(TimeSpan.FromSeconds(30), _cts.Token); // периодическая очистка
}
});
}

public void Dispose()
{
_cts.Cancel();
}
}

📌 Важные моменты:

- Кэш конкурентный (`ConcurrentDictionary`) — доступ без явных блокировок.
- Периодическая чистка не мешает основным операциям.
- Удаление истёкших элементов происходит "мягко" (через проверку срока жизни).
- Фоновая задача корректно завершается через CancellationToken.


>>Click here to continue<<

C# 1001 notes




Share with your best friend
VIEW MORE

United States America Popular Telegram Group (US)