Это может быть похоже на просьбу о луне на палке; но существует ли «Потокобезопасный LRU-кэш производственного качества C# с истекающим сроком действия? Или у кого-нибудь есть идеи передового опыта для достижения того же самого?»
public interface ICache
{
T GetOrAdd(string key, Func create, TimeSpan timeToLive) where T : class;
bool Remove(string key);
}
Мне нужен GetOrAdd, потому что я хочу, чтобы эти операции были «атомарными», т. е. чтобы избежать состояний гонки вокруг двух потоков, пытающихся запросить кеш. в то же время
Мне нужна функция Create, потому что создание этих объектов дорого (требуется сложный доступ к базе данных)
Мне нужен срок действия, так как срок действия этих объектов истекает через определенный период времени.
Лучшим решением от Microsoft кажется «System.Runtime.Caching.MemoryCache». , однако, похоже, здесь есть несколько предостережений:
Для соблюдения установленных ограничений памяти необходимо периодически опрашивать кэш. У меня не может быть никакой возможности нехватки памяти в моей системе. Я прочитал этот пост, который меня беспокоит: MemoryCache не подчиняется ограничениям памяти в конфигурации.
Похоже, что он имеет только «AddOrGetExisting» для поддержки моего интерфейса, который принимает созданный объект в качестве второго. параметр - если создание этого объекта требует больших затрат, не является ли его предварительное создание своего рода нарушением смысла кэша?
public sealed class Cache : ICache
{
private readonly MemoryCache _cache;
public Cache()
{
_cache = MemoryCache.Default;
}
public T GetOrAdd(string key, Func create, TimeSpan timeToLive) where T : class
{
// This call kinda defeats the point of the cache ?!?
var newValue = create();
return _cache.AddOrGetExisting(key, newValue, DateTimeOffset.UtcNow + timeToLive) as T;
}
public bool Remove(string key)
{
_cache.Remove(key);
return true;
}
}
Или, может быть, что-то получше в Lazy < T >, которое позволяет создавать результат только один раз, но выглядит как хак (есть ли последствия кеширования Func?) :
class Program
{
static void Main(string[] args)
{
Func creation = () =>
{
// Some expensive thing
return new Foo();
};
Cache cache = new Cache();
// Result 1 and 2 are correctly the same instance. Result 3 is correctly a new instance...
var result1 = cache.GetOrAdd("myKey", creation, TimeSpan.FromMinutes(30));
var result2 = cache.GetOrAdd("myKey", creation, TimeSpan.FromMinutes(30));
var result3 = cache.GetOrAdd("myKey3", creation, TimeSpan.FromMinutes(30));
return;
}
}
public sealed class Foo
{
private static int Counter = 0;
private int Index = 0;
public Foo()
{
Index = ++Counter;
}
}
public sealed class Cache
{
private readonly MemoryCache _cache;
public Cache()
{
_cache = MemoryCache.Default;
}
public T GetOrAdd(string key, Func create, TimeSpan timeToLive) where T : class
{
var newValue = new Lazy(create, LazyThreadSafetyMode.PublicationOnly);
var value = (Lazy)_cache.AddOrGetExisting(key, newValue, DateTimeOffset.UtcNow + timeToLive);
return (value ?? newValue).Value;
}
public bool Remove(string key)
{
_cache.Remove(key);
return true;
}
}
Другие мысли:
Я также нашел эту реализацию, но она не позволяет указать срок действия на основе времени: существует ли какая-либо реализация IDictionary с использованием LRU?
Может быть, существует реализация, использующая ReaderWriterLock?
Это может быть похоже на просьбу о луне на палке; но существует ли «Потокобезопасный LRU-кэш производственного качества C# с истекающим сроком действия? Или у кого-нибудь есть идеи передового опыта для достижения того же самого?»
(LRU — «наименее недавно используемый» — http://en.wikipedia.org/wiki/Cache_algorithms#LRU)
Чтобы уточнить: я хочу поддержать кэш памяти на сайте ASP.Net MVC со следующим интерфейсом:
[code]public interface ICache { T GetOrAdd(string key, Func create, TimeSpan timeToLive) where T : class; bool Remove(string key); } [/code]
[list] [*]Мне нужен GetOrAdd, потому что я хочу, чтобы эти операции были «атомарными», т. е. чтобы избежать состояний гонки вокруг двух потоков, пытающихся запросить кеш. в то же время [*]Мне нужна функция Create, потому что создание этих объектов дорого (требуется сложный доступ к базе данных) [*]Мне нужен срок действия, так как срок действия этих объектов истекает через определенный период времени. [/list]
Лучшим решением от Microsoft кажется «System.Runtime.Caching.MemoryCache». , однако, похоже, здесь есть несколько предостережений:
[list] [*]Для соблюдения установленных ограничений памяти необходимо периодически опрашивать кэш. У меня не может быть никакой возможности нехватки памяти в моей системе. Я прочитал этот пост, который меня беспокоит: MemoryCache не подчиняется ограничениям памяти в конфигурации. [*]Похоже, что он имеет только «AddOrGetExisting» для поддержки моего интерфейса, который принимает созданный объект в качестве второго. параметр - если создание этого объекта требует больших затрат, не является ли его предварительное создание своего рода нарушением смысла кэша? [/list]
public T GetOrAdd(string key, Func create, TimeSpan timeToLive) where T : class { // This call kinda defeats the point of the cache ?!? var newValue = create();
return _cache.AddOrGetExisting(key, newValue, DateTimeOffset.UtcNow + timeToLive) as T; }
Или, может быть, что-то получше в Lazy < T >, которое позволяет создавать результат только один раз, но выглядит как хак (есть ли последствия кеширования Func?) :
[code]class Program { static void Main(string[] args) { Func creation = () => { // Some expensive thing return new Foo(); };
Cache cache = new Cache(); // Result 1 and 2 are correctly the same instance. Result 3 is correctly a new instance... var result1 = cache.GetOrAdd("myKey", creation, TimeSpan.FromMinutes(30)); var result2 = cache.GetOrAdd("myKey", creation, TimeSpan.FromMinutes(30)); var result3 = cache.GetOrAdd("myKey3", creation, TimeSpan.FromMinutes(30));
return; } }
public sealed class Foo { private static int Counter = 0; private int Index = 0;
public Foo() { Index = ++Counter; } }
public sealed class Cache { private readonly MemoryCache _cache;
public Cache() { _cache = MemoryCache.Default; }
public T GetOrAdd(string key, Func create, TimeSpan timeToLive) where T : class { var newValue = new Lazy(create, LazyThreadSafetyMode.PublicationOnly); var value = (Lazy)_cache.AddOrGetExisting(key, newValue, DateTimeOffset.UtcNow + timeToLive); return (value ?? newValue).Value; }
[list] [*]Я также нашел эту реализацию, но она не позволяет указать срок действия на основе времени: существует ли какая-либо реализация IDictionary с использованием LRU? [*]Может быть, существует реализация, использующая ReaderWriterLock? [*]Какая-то оболочка вокруг ConcurrentDictionary? [/list]
где
id = trasactionID
type = тип транзакции (EARN = пользователь получает баллы из магазина, REDEEM = пользователь использует баллы)
expiredAt = балл срок действия (до истечения срока действия балла EARN...
Я хочу украсить функцию, как и с помощью functools.lru_cache с результатами, кэшированными на жестком диске вместо памяти.
(вычислительные изображения функции из имен файлов.)
Я хочу создать класс для возврата значения. Это значение будет кэшировано в объекте словаря на 2 минуты. В течение этих двух минут мне нужно вернуть кешированное значение, по истечении этих минут объект словарного кэша должен снова прочитать это...
Я использую эту библиотеку для сброса пароля пользователя. Это блок кода, который генерирует код:
async def create_code(db: AsyncSession, user):
secret_key = pyotp.random_base32()
Я успешно внедрил распределенный кэш с помощью SQL Server, настроив его следующим образом:
services.AddDistributedSqlServerCache(options =>
{
options.ConnectionString = Configuration.GetConnectionString( App );
options.SchemaName = dbo ;...