Usando lo que juzgué que era el mejor de todos los mundos en el asombroso artículo Implementing the Singleton Pattern in C#, he estado usando con éxito la siguiente clase para persistir los datos definidos por el usuario en la memoria (para los muy raramente modificados datos):Patrón de Singleton en caché en memoria persistente
public class Params
{
static readonly Params Instance = new Params();
Params()
{
}
public static Params InMemory
{
get
{
return Instance;
}
}
private IEnumerable<Localization> _localizations;
public IEnumerable<Localization> Localizations
{
get
{
return _localizations ?? (_localizations = new Repository<Localization>().Get());
}
}
public int ChunkSize
{
get
{
// Loc uses the Localizations impl
LC.Loc("params.chunksize").To<int>();
}
}
public void RebuildLocalizations()
{
_localizations = null;
}
// other similar values coming from the DB and staying in-memory,
// and their refresh methods
}
mi uso sería algo como esto:
var allLocs = Params.InMemory.Localizations; //etc
Siempre que puedo actualizar la base de datos, los RefreshLocalizations es llamado por lo que sólo parte de mi tienda en memoria, se reconstruye. Tengo un entorno de producción único de aproximadamente 10 que parece que se comporta mal cuando se llama a RefreshLocalizations, no se actualiza en absoluto, pero esto también parece ser intermitente y muy extraño por completo.
Mi sospecha actual va hacia el singleton, que creo que hace bien el trabajo y todas las pruebas unitarias demuestran que el mecanismo de singleton, el mecanismo de actualización y el rendimiento de RAM funcionan todos como se esperaba.
Dicho esto, estoy abajo a estas posibilidades:
- Este cliente está mintiendo cuando dice que su entorno no está usando el equilibrio de carga, que es un entorno no estoy esperando la materia en memoria para trabajar correctamente (¿no?)
- Hay alguna configuración de grupo no estándar en su IIS contra la que estoy probando (¿quizás en una configuración Web Garden?)
- El singleton está fallando de alguna manera, pero no está seguro de cómo hacerlo.
¿Alguna sugerencia?
.NET 3.5 así no hay mucho jugo paralelo disponible, y no está listo para usar las extensiones reactivas por ahora
Edit1: de acuerdo con las sugerencias, lo haría el aspecto captador algo como:
public IEnumerable<Localization> Localizations
{
get
{
lock(_localizations) {
return _localizations ?? (_localizations = new Repository<Localization>().Get());
}
}
}
Es es posible que tenga algunos problemas de seguridad hilo aquí? Parece que le gustaría tener un candado para evitar que se creen varias instancias de su repositorio después de una actualización (comúnmente llamada "estampida de caché") –
Gracias por su comentario Eric, asumí la forma en que llamo al repositorio usando la instancia de InMemory evitaría que eso suceda, ¿tiene sentido? –
De tu pregunta, parece que el código para publicar sería el código que realiza la actualización. Lo que tienes arriba se ve bien para mí. El equilibrio de carga e IIS no deberían tener ningún efecto (pero de nuevo necesitaría ver el código de actualización de db), a menos que se refiera a múltiples servidores web, en cuyo caso deberá sincronizar la actualización entre ellos (en cuyo caso solo usará un caché externo). .... El caché de AppFabric sería adecuado) –