2010-04-14 8 views
13

estoy usando Cache en un método de servicio Web como esto:'HttpContext.Current.Cache' con seguridad

var pblDataList = (List<blabla>)HttpContext.Current.Cache.Get("pblDataList"); 

if (pblDataList == null) 
{ 
    var PBLData = dc.ExecuteQuery<blabla>(@"SELECT blabla"); 

    pblDataList = PBLData.ToList(); 

    HttpContext.Current.Cache.Add("pblDataList", pblDataList, null, 
     DateTime.Now.Add(new TimeSpan(0, 0, 15)), 
     Cache.NoSlidingExpiration, CacheItemPriority.Normal, null); 
} 

Pero me pregunto, es el código flujos seguros? El método de servicio web es llamado por múltiples solicitantes. Y más de un solicitante puede intentar recuperar datos y agregarlos al Cache al mismo tiempo mientras el caché está vacío.

La consulta tarda de 5 a 8 segundos. ¿La introducción de una declaración de bloqueo alrededor de este código evitaría posibles conflictos? (Sé que varias consultas se pueden ejecutar simultáneamente, pero quiero estar seguro de que solo se está ejecutando una consulta a la vez).

Respuesta

22

El objeto de caché es seguro para hilos pero HttpContext.Current no estará disponible desde los hilos de fondo. Esto puede aplicarse o no a usted aquí, no es obvio por su fragmento de código si realmente está usando hilos de fondo, pero en caso de que esté o decida hacerlo en algún momento en el futuro, debe tener esto en cuenta .

Si hay alguna posibilidad de que necesite acceder al caché desde un hilo de fondo, entonces use HttpRuntime.Cache.

Además, aunque las operaciones individuales en la memoria caché son seguras para hilos, las operaciones secuenciales de búsqueda/almacenamiento obviamente no son atómicas. Si usted necesita o no que sean atómicos depende de su aplicación particular. Si puede ser un problema grave para la misma consulta ejecutar varias veces, es decir, si produciría más carga de la que su base de datos puede manejar, o si sería un problema para una solicitud devolver datos que se sobrescriben inmediatamente en el caché, entonces es probable que desee colocar un bloqueo alrededor de todo el bloque de código.

Sin embargo, en la mayoría de los casos, realmente querrás hacer un perfil primero y ver si esto es realmente un problema. La mayoría de las aplicaciones/servicios web no se preocupan por este aspecto del almacenamiento en caché porque son apátridas y no importa si se sobrescribe el caché.

+0

No utilizo hilos de fondo, solo son llamadas al servicio web. De paso, gracias. –

2

Tiene razón. Las operaciones de recuperación y adición no se están tratando como una transacción atómica. Si necesita evitar que la consulta se ejecute varias veces, deberá usar un bloqueo.

(Normalmente esto no sería un gran problema, pero en el caso de una consulta de larga ejecución que puede ser útil para aliviar la tensión en la base de datos.)

+2

Esto realmente depende. En un entorno de alto rendimiento, la carga adicional en la base de datos puede no ser tan importante como la solicitud de aceleración que resulta de este tipo de bloqueo.En la mayoría de los casos, diría que tienes razón, pero cada caso debe evaluarse individualmente. – Aaronaught

+0

Buen punto. Reformé ligeramente mi respuesta debido a esto. – Greg

1

creo que el Add debe ser seguro para subprocesos - es decir, no se producirá un error si se llama a Add dos veces con la misma clave, pero obviamente la consulta podría ejecutar dos veces.

Otra pregunta, sin embargo, es es la seguridad de los hilos de datos. No hay garantía de que cada List<blabla> esté aislado; depende del proveedor de caché. El proveedor de memoria caché en memoria almacena los objetos directamente, por lo que existe el riesgo de colisiones si alguno de los hilos edita los datos (agrega/elimina/intercambia elementos en la lista, o cambia las propiedades de uno de los elementos). Sin embargo, con un proveedor de serialización , debería estar bien. Por supuesto, esto exige que blabla sea serializable ...

+0

¿Podría compartir un enlace para serializar su objeto para caché? Estaba tratando de almacenar en caché una tabla de datos en el trabajo para una pantalla web que filtra algunos datos. Me dijeron que la carga del servidor sería demasiado. ¿Conoce algún artículo sobre el almacenamiento en caché y la serialización, así como sobre la carga del servidor? No pude encontrar nada específico mientras busco en Google. –

+0

@kcbeard primero, una vez en caché: ** no mutes ** una 'DataTable'. Ahora que está fuera del camino: ¿qué tan grande es la información? ¿Qué volumen de filas? –

+0

Desde cientos de filas hasta 5k máx. Una docena de columnas con tipos de datos date-time, int y var-char. El sentido común me dijo que no use view state y SO me respaldó. Estaba bajo la suposición de que solo unos pocos usuarios por instancia de aplicación estarían accediendo a él, así que al principio usé Current.Session, luego se mencionó que la carga del servidor era demasiado, así que pensé en Current.Cache (aplicación de ancho). Quiero decir que tal vez un procedimiento almacenado lo suficientemente flexible como para manejar todo el filtrado sería la mejor ruta. Pero en cualquier caso, quiero saber más sobre la seguridad del almacenamiento en caché, las mejores prácticas, las trampas, etc. –

Cuestiones relacionadas