Las empresas de hoy están desarrollando aplicaciones web ASP.NET de alto tráfico que sirven a decenas de miles de usuarios simultáneos. Varios clientes tienen acceso a los datos de caché en un entorno agrupado donde los servidores de aplicaciones se implementan en un entorno de carga equilibrada. En tales condiciones paralelas, varios usuarios a menudo intentan acceder y modificar los mismos datos y activar una condición de carrera.
Una condición de carrera es cuando dos o más usuarios intentan acceder y cambiar los mismos datos compartidos simultáneamente pero terminan haciéndolo en el orden incorrecto. Esta situación conduce a un alto riesgo de pérdida de integridad y consistencia de los datos. Con la llegada de las soluciones de almacenamiento en memoria caché escalables como NCache Al proporcionar mecanismos de bloqueo distribuido, las empresas pueden lograr una consistencia de datos significativamente mejorada.
NCache Detalles Documentos de bloqueo y control NCache Docs
Bloqueo distribuido para la consistencia de datos
NCache proporciona un mecanismo de distribución cierre en .NET que le permite bloquear elementos de caché específicos durante las actualizaciones simultáneas. Para mantener la consistencia de los datos en tales casos, NCache actúa como un administrador de bloqueo distribuido y le proporciona dos tipos de bloqueo:
Los discutiremos en detalle más adelante en el blog. Por ahora, considere el siguiente escenario para comprender cómo, sin un servicio de bloqueo distribuido, existe una violación de la integridad de los datos.
Dos usuarios acceden a la misma Cuenta Bancaria simultáneamente con un saldo de 30,000. Un usuario retira 15,000, mientras que el otro usuario deposita 5,000. Si se hace correctamente, el saldo final debe ser de 20,000. Por el contrario, si surge una condición de carrera que no se atiende, el saldo bancario sería de 15,000 35,000 o XNUMX XNUMX, como puede ver arriba.
Así es como ocurre esta condición de carrera:
- Tiempo t1: El usuario 1 obtiene una cuenta bancaria con saldo = 30,000
- Tiempo t2: El usuario 2 obtiene una cuenta bancaria con saldo = 30,000
- Tiempo t3: El usuario 1 retira 15,000 15,000 y actualiza el saldo de la cuenta bancaria = XNUMX XNUMX
- Tiempo t4: El usuario 2 deposita 5,000 y actualiza el saldo de la cuenta bancaria = 35,000 XNUMX
En ambos casos, un bloque de código que no atienda a la gestión de subprocesos podría ser desastroso para el banco. Entonces, en las secciones subsiguientes, veamos cómo NCache proporciona mecanismos de bloqueo para garantizar que la lógica de su aplicación sea segura para subprocesos.
NCache Detalles Bloqueo pesimista Bloqueo optimista
Bloqueo optimista (versiones de artículos)
In bloqueo optimista, NCache usos control de versiones de elementos de caché. En el lado del servidor, cada objeto almacenado en caché tiene un número de versión asociado que se incrementa en cada actualización de elementos de caché. NCache luego verifica si está trabajando en la última versión. Si no, rechaza la actualización de su caché. De esta manera, solo un usuario puede actualizar y las actualizaciones de otros usuarios fallan.
Puede agregar un elemento en el caché usando ambos Añada or recuadro métodos.
- El método Agregar agrega un nuevo elemento en el caché y guarda la versión del elemento por primera vez.
- El método de inserción sobrescribe el valor de un elemento existente y actualiza su versión del elemento.
Eche un vistazo al siguiente ejemplo de código.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
// Pre-condition: Cache is already connected // An item is added in the cache with itemVersion // Specify the key of the cacheItem string key = "Product:1001"; // Initialize the cacheItemVersion CacheItemVersion version = null; // Get the cacheItem previously added in the cache with the version CacheItem cacheItem = cache.GetCacheItem(key, ref version); // If result is not null if (cacheitem != null) { // CacheItem is retrieved successfully with the version // If result is Product type var prod = new Product(); prod = cacheItem.GetValue(); prod.UnitsInStock++; // Create a new cacheItem with updated value var updateItem = new CacheItem(prod); CacheItemVersion version = cache.Insert(key, updateItem); // If it matches, the insert will be successful, otherwise it will fail } else { // Item could not be retrieved due to outdated CacheItemVersion } |
En el ejemplo anterior, dos aplicaciones diferentes usan un solo caché que contiene los datos de los productos. CacheItem se agrega al caché. Ambas aplicaciones obtienen el elemento con la versión actual, digamos versión. Application1 modifica el nombre del producto y luego vuelve a insertar el elemento en el caché que actualiza su versión del elemento a nueva versión. Application2 todavía tiene el elemento con versión. Si application2 actualiza las unidades del artículo en stock y vuelve a insertar el artículo en el caché, la inserción del artículo fallará. Por lo tanto, la aplicación 2 tendrá que obtener la versión actualizada para operar en ese elemento de caché.
NCache Detalles Bloqueo optimista Control de versiones de elementos de caché
Sin embargo, si desea obtener un elemento existente que puede tener una versión más nueva disponible en el caché, NCache proporciona una Obtener si es más nuevo método. Si especifica la versión actual como argumento de la llamada al método, la memoria caché devuelve un resultado adecuado. Si la versión específica es menor que la que está en el caché, el método devuelve un nuevo elemento; de lo contrario, devolverá un valor nulo.
Echemos un vistazo al código de abajo.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
// Get object from cache var result = cache.GetIfNewer(key, ref version); // Check if updated item is available if (result != null) { // An item with newer version is available if (result is Product) { // Perform operations according to business logic } } else { // No new itemVersion is available } |
El ejemplo anterior agrega un elemento en el caché con la clave Producto: 1001 y la versión del elemento. Si hay alguna versión más reciente del artículo disponible, Obtener si es más nuevo El método recupera el elemento utilizando la versión del elemento de caché.
Con bloqueo optimista, NCache asegura que cada escritura en el caché distribuido sea consistente con la versión que contiene cada aplicación. Consulte nuestro oficial NCache Documentación para un extenso ejemplo de código.
NCache Detalles Obtener si es más nuevo Versionado de elemento de caché
Bloqueo pesimista (bloqueo exclusivo)
La otra forma de garantizar la coherencia de los datos es adquirir un bloqueo exclusivo en los datos almacenados en caché. Este mecanismo se llama Bloqueo pesimista . Bloquea el elemento usando el identificador de bloqueo, impidiendo que todos los demás usuarios realicen cualquier operación de escritura en ese elemento de caché. A Manija de bloqueo es un identificador asociado con cada elemento bloqueado en el caché devuelto por la API de bloqueo.
El siguiente ejemplo crea un LockHandle y luego bloquea un elemento con la clave Product:1001 durante un período de 10 segundos para que el elemento se desbloquee automáticamente después de 10 segundos.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
// Pre-Requisite: Cache is already connected // Item is already added in the cache // Specify the key of the item string key = $"Product:1001"; //Create a new LockHandle LockHandle lockHandle = null; // Specify time span of 10 seconds for which the item remains locked TimeSpan lockSpan = TimeSpan.FromSeconds(10); // Lock the item for a time span of 10 seconds bool lockAcquired = cache.Lock(key, lockSpan, out lockHandle); // Verify if the item is locked successfully if (lockAcquired == true) { // Item has been successfully locked } else { // Key does not exist // Item is already locked with a different LockHandle } |
Al adquirir con éxito el bloqueo mientras busca el elemento, la aplicación ahora puede realizar operaciones de manera segura, sabiendo que ninguna otra aplicación puede obtener o actualizar este elemento mientras tenga este bloqueo. Llamaremos a Insertar API con el mismo identificador de bloqueo para actualizar los datos y liberar el bloqueo. Al hacerlo, se insertarán los datos en el caché y se liberará el bloqueo, todo en una sola llamada, lo que permitirá que los datos almacenados en caché estén disponibles para todas las demás aplicaciones.
Solo recuerde que debe adquirir todos los bloqueos con un tiempo de espera. De forma predeterminada, si no se especifica el tiempo de espera, NCache bloqueará el artículo por un tiempo indefinido, timepan.zero. Puede haber un caso en el que el elemento permanezca bloqueado para siempre si la aplicación falla sin liberar el bloqueo. Para una solución alternativa, podría liberar con fuerza pero esta práctica es desaconsejable. Por lo tanto, bloquee un elemento durante el TimeSpan mínimo para evitar interbloqueos o inanición de subprocesos.
NCache Detalles Bloqueo pesimista Uso del bloqueo con el blog de datos almacenados en caché
Soporte de conmutación por error en bloqueo distribuido
Como NCache es un recuerdo, caché distribuida, también proporciona soporte completo de conmutación por error para que no haya pérdida de datos y esté altamente disponible. En caso de falla del servidor, sus aplicaciones cliente seguirán funcionando sin problemas. De manera similar, sus bloqueos en el sistema distribuido también son replicados y mantenidos por los nodos de replicación. Si algún nodo falla mientras una de sus aplicaciones adquiere un bloqueo, se propagará automáticamente a un nuevo nodo con sus propiedades especificadas, por ejemplo, Caducidad de bloqueo.
Conclusión
Entonces, ¿qué mecanismo de bloqueo es mejor para usted, optimista o pesimista? Bueno, depende de su caso de uso y de lo que quiera lograr. El bloqueo optimista proporciona un beneficio de rendimiento mejorado en comparación con el bloqueo pesimista, especialmente cuando sus aplicaciones son de lectura intensiva. Mientras que Pessimistic Locking es más seguro desde una perspectiva de consistencia de datos. Por lo tanto, elija su mecanismo de bloqueo con cuidado. Para más detalles, dirígete a la página web. En caso de cualquier pregunta, contáctenos ¡y deja que nuestros expertos te ayuden!