Запись содержимого MemoryCache в базу данных и условия гонкиC#

Место общения программистов C#
Ответить
Anonymous
 Запись содержимого MemoryCache в базу данных и условия гонки

Сообщение Anonymous »

Я реализую на C# .NET простой потребитель сообщений, который считывает из очереди кучу сообщений пары ключ, значение, и мне нужно поддерживать словарь ключей -> [значения, видимые до сих пор] (в приведенном ниже коде это MemoryCache _memoryCache). Потому что периодически мне хочется записать это в БД, добавляя значения к текущему значению, найденному в БД.
Как это сделать? Я поддерживаю ConcurrentDictionary ключей и каждые 30 минут перебираю ключи для добавления в БД, но боюсь условий гонки (приложение имеет несколько экземпляров, каждый из которых имеет несколько ядер). Вот примерный упрощенный код:

Код: Выделить всё

public class MyMessageConsumer : BaseMessageConsumer
{
private readonly MemoryCache _memoryCache; // key -> [values]
private ConcurrentDictionary _memoryCacheKeys;
private DateTime _lastUpdate;

// not expanding here on the constructors etc that set _lastUpdate etc.

internal async Task UpdateAsync(string cacheKey, string value)
{

await UpdateMemoryCache(cacheKey, keyword);

if (DateTime.Now > _lastUpdate.AddMinutes(30))
{
_lastUpdate = DateTime.Now;
foreach (var (cacheKey, _) in _memoryCacheKeys)
{
if (_memoryCache.TryGetValue(cacheKey, out HashSet values))
{
WriteToSomeDB()
_memoryCache.Remove(RemoveKey(cacheKey));
}

}
}
return MessageConsumeResult.Completed();
}

private async Task UpdateMemoryCache(string cacheKey, string value)
{
if (_memoryCache.TryGetValue(cacheKey, out HashSet previousValues))
{
if (!previousValues.Contains(value))
{
previousValues.Add(value);
_memoryCache.Set(AddKey(cacheKey), previousValues, TimeSpan.FromHours(48));
}
}
else
{
_memoryCache.Set(AddKey(cacheKey), new HashSet { value }, TimeSpan.FromHours(48));
}
}

private string AddKey(string key)
{
_memoryCacheKeys.TryAdd(key, true);
return key;
}

private string RemoveKey(string key)
{
_memoryCacheKeys.TryRemove(key, out _);
return key;
}
}
Я не слишком знаком с параллелизмом, но предполагаю, что мне следует ввести блокировку при обновлении MemoryCache (новое значение и удаление после вставки в БД). В идеале я хотел бы просто сбросить результат MemoryCache, когда срок его действия истечет! Но MemoryCache, похоже, не предоставляет такой функции. Поэтому я придумал обходной путь.
Большое спасибо за ваши идеи и хорошего дня!

Подробнее здесь: https://stackoverflow.com/questions/783 ... conditions
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»