Almacenamiento en memoria cachéCaching

El almacenamiento en caché es una técnica que tiene como objetivo mejorar el rendimiento y la escalabilidad de un sistema.Caching is a common technique that aims to improve the performance and scalability of a system. Para ello, se copian temporalmente los datos a los que se accede con mayor frecuencia en almacenamiento rápido ubicado cerca de la aplicación.It does this by temporarily copying frequently accessed data to fast storage that's located close to the application. Si este almacenamiento de datos rápido se encuentra más cerca de la aplicación que el primer origen, el almacenamiento en caché puede mejorar considerablemente los tiempos de respuesta de las aplicaciones cliente dado que los datos se sirven con mayor rapidez.If this fast data storage is located closer to the application than the original source, then caching can significantly improve response times for client applications by serving data more quickly.

El almacenamiento en caché es más eficaz cuando una instancia de cliente lee de forma repetida los mismos datos, en especial si todas las condiciones siguientes se aplican al almacén de datos original:Caching is most effective when a client instance repeatedly reads the same data, especially if all the following conditions apply to the original data store:

  • Permanece relativamente estático.It remains relatively static.
  • Es lento en comparación con la velocidad de la caché.It's slow compared to the speed of the cache.
  • Está sujeto a un alto nivel de contención.It's subject to a high level of contention.
  • Está lejos cuando la latencia de red puede provocar que el acceso sea lento.It's far away when network latency can cause access to be slow.

Almacenamiento en caché en aplicaciones distribuidasCaching in distributed applications

Las aplicaciones distribuidas normalmente implementan ambas de las siguientes estrategias, o una de ellas, al almacenar datos en caché:Distributed applications typically implement either or both of the following strategies when caching data:

  • Mediante una caché privada, donde los datos se guardan localmente en el equipo que ejecuta una instancia de una aplicación o un servicio.Using a private cache, where data is held locally on the computer that's running an instance of an application or service.
  • Mediante una memoria caché compartida, que actúa como un origen común al que se puede acceder desde varios procesos y máquinas.Using a shared cache, serving as a common source that can be accessed by multiple processes and machines.

En ambos casos, el almacenamiento en caché se puede realizar en el lado cliente y servidor.In both cases, caching can be performed client-side and server-side. El almacenamiento en caché en el lado cliente se realiza mediante el proceso que proporciona la interfaz de usuario de un sistema, como un explorador web o una aplicación de escritorio.Client-side caching is done by the process that provides the user interface for a system, such as a web browser or desktop application. El almacenamiento en caché en el lado servidor se realiza mediante el proceso que proporciona los servicios de negocios que se ejecutan de forma remota.Server-side caching is done by the process that provides the business services that are running remotely.

Almacenamiento en caché privadoPrivate caching

El tipo más básico de caché es un almacén en memoria.The most basic type of cache is an in-memory store. Está contenido en el espacio de direcciones de un solo proceso y se accede directamente a él mediante el código que se ejecuta en ese proceso.It's held in the address space of a single process and accessed directly by the code that runs in that process. Este tipo de memoria caché es de acceso rápido.This type of cache is quick to access. También puede proporcionar un medio efectivo de almacenar cantidades modestas de datos estáticos, dado que el tamaño de una memoria caché suele estar restringido por la cantidad de memoria disponible en la máquina que hospeda el proceso.It can also provide an effective means for storing modest amounts of static data, since the size of a cache is typically constrained by the amount of memory available on the machine hosting the process.

Si necesita almacenar en caché más información de lo que es posible físicamente en la memoria, puede escribir datos en caché en el sistema de archivos local.If you need to cache more information than is physically possible in memory, you can write cached data to the local file system. El acceso será más lento que cuando los datos están contenidos en memoria, pero aún así debería ser más rápido y confiable que recuperar los datos desde una red.This will be slower to access than data held in memory, but should still be faster and more reliable than retrieving data across a network.

Si tiene varias instancias de una aplicación que usa este modelo de ejecución simultánea, cada instancia de la aplicación tendrá su propia caché independiente con su propia copia de los datos.If you have multiple instances of an application that uses this model running concurrently, each application instance has its own independent cache holding its own copy of the data.

Una caché se puede considerar como una instantánea de los datos originales en algún momento del pasado.Think of a cache as a snapshot of the original data at some point in the past. Si estos datos no son estáticos, es probable que las diferentes instancias de aplicación contengan versiones diferentes de los datos en sus cachés.If this data is not static, it is likely that different application instances hold different versions of the data in their caches. Por lo tanto, la misma consulta realizada por estas instancias podría devolver resultados diferentes, como se muestra en la Figura 1.Therefore, the same query performed by these instances can return different results, as shown in Figure 1.

Uso de una caché en memoria en instancias diferentes de una aplicación

Figura 1: Uso de una caché en memoria en instancias diferentes de una aplicación.Figure 1: Using an in-memory cache in different instances of an application.

Almacenamiento en caché compartidoShared caching

El uso de una caché compartida puede ayudar a aliviar la preocupación de que los datos puedan ser diferentes en cada caché, como podría ocurrir con el almacenamiento en caché en memoria.Using a shared cache can help alleviate concerns that data might differ in each cache, which can occur with in-memory caching. El almacenamiento en caché compartido garantiza que diferentes instancias de una aplicación ven la misma vista de datos en caché.Shared caching ensures that different application instances see the same view of cached data. Para ello, se ubica la caché en una ubicación aparte, normalmente hospedada como parte de un servicio independiente, como se muestra en la Figura 2.It does this by locating the cache in a separate location, typically hosted as part of a separate service, as shown in Figure 2.

Uso de una caché compartida

Figura 2: Uso de una caché compartida.Figure 2: Using a shared cache.

Una ventaja importante del enfoque de almacenamiento en caché compartido es la escalabilidad que proporciona.An important benefit of the shared caching approach is the scalability it provides. Muchos servicios de memoria caché compartida se implementan mediante un clúster de servidores y utilizan software para distribuir los datos en el clúster de forma transparente.Many shared cache services are implemented by using a cluster of servers and use software to distribute the data across the cluster transparently. Una instancia de aplicación simplemente envía una solicitud al servicio de caché.An application instance simply sends a request to the cache service. La infraestructura subyacente es determina la ubicación de los datos almacenados en caché en el clúster.The underlying infrastructure determines the location of the cached data in the cluster. Puede escalar fácilmente la memoria caché al agregar más servidores.You can easily scale the cache by adding more servers.

Dos son las desventajas principales del enfoque de almacenamiento en caché compartido:There are two main disadvantages of the shared caching approach:

  • La caché es de acceso más lento porque ya no está contenida localmente en cada instancia de aplicación.The cache is slower to access because it is no longer held locally to each application instance.
  • La necesidad de implementar un servicio de caché independiente puede agregar complejidad a la solución.The requirement to implement a separate cache service might add complexity to the solution.

Consideraciones para usar el almacenamiento en cachéConsiderations for using caching

En las secciones siguientes se describe con más detalle las consideraciones para diseñar y usar una memoria caché.The following sections describe in more detail the considerations for designing and using a cache.

Decidir cuándo almacenar en caché los datosDecide when to cache data

El almacenamiento en caché puede mejorar considerablemente el rendimiento, la escalabilidad y la disponibilidad.Caching can dramatically improve performance, scalability, and availability. Cuantos más datos tenga y mayor sea el número de usuarios que necesitan tener acceso a ellos, mayores son cada vez las ventajas del almacenamiento en caché.The more data that you have and the larger the number of users that need to access this data, the greater the benefits of caching become. El motivo es que el almacenamiento en caché reduce la latencia y la contención asociadas con el tratamiento de grandes volúmenes de solicitudes simultáneas en el almacén de datos original.That's because caching reduces the latency and contention that's associated with handling large volumes of concurrent requests in the original data store.

Por ejemplo, una base de datos puede admitir un número limitado de conexiones simultáneas.For example, a database might support a limited number of concurrent connections. La recuperación de datos de una caché compartida, sin embargo, en lugar de la base de datos subyacente, permite que una aplicación cliente acceda a estos datos incluso si el número de conexiones disponibles está actualmente agotado.Retrieving data from a shared cache, however, rather than the underlying database, makes it possible for a client application to access this data even if the number of available connections is currently exhausted. Además, si la base de datos deja de estar disponible, es posible que las aplicaciones cliente continúen usando los datos contenidos en la caché.Additionally, if the database becomes unavailable, client applications might be able to continue by using the data that's held in the cache.

Considere la posibilidad de almacenar en caché los datos que se leen con frecuencia, pero que se modifican con poca frecuencia (por ejemplo, los datos que tienen una proporción de operaciones de lectura más alta que de escritura).Consider caching data that is read frequently but modified infrequently (for example, data that has a higher proportion of read operations than write operations). Sin embargo, no se recomienda usar la caché como almacén autoritativo de la información crítica.However, we don't recommend that you use the cache as the authoritative store of critical information. En su lugar, asegúrese de que todos los cambios que la aplicación no puede permitirse perder siempre se guarden en un almacén de datos persistente.Instead, ensure that all changes that your application cannot afford to lose are always saved to a persistent data store. De esta manera, si la caché no está disponible, su aplicación podrá continuar funcionando usando el almacén de datos y no perderá información importante.This means that if the cache is unavailable, your application can still continue to operate by using the data store, and you won't lose important information.

Determinar cómo almacenar en caché los datos de forma efectivaDetermine how to cache data effectively

La clave para usar de forma eficaz una memoria caché reside en la determinación de los datos más adecuados para la caché y de su almacenamiento en caché en el momento adecuado.The key to using a cache effectively lies in determining the most appropriate data to cache, and caching it at the appropriate time. Los datos pueden agregarse a la caché a petición la primera vez que los recupera una aplicación.The data can be added to the cache on demand the first time it is retrieved by an application. Esto significa que la aplicación debe capturar los datos una sola vez del almacén de datos y que el posterior acceso se puede satisfacer mediante la caché.This means that the application needs to fetch the data only once from the data store, and that subsequent access can be satisfied by using the cache.

O bien, una caché se puede rellenar total o parcialmente con datos de antemano, normalmente cuando se inicia la aplicación (un método conocido como inicialización).Alternatively, a cache can be partially or fully populated with data in advance, typically when the application starts (an approach known as seeding). Sin embargo, es posible que no sea aconsejable implementar la inicialización para una caché de gran tamaño ya que este enfoque puede imponer una carga alta y repentina en el almacén de datos original cuando la aplicación comienza a ejecutarse.However, it might not be advisable to implement seeding for a large cache because this approach can impose a sudden, high load on the original data store when the application starts running.

A menudo, un análisis de los patrones de uso puede ayudarle a decidir si desea rellenar previamente total o parcialmente una caché, así como a elegir los datos que se almacenarán en caché.Often an analysis of usage patterns can help you decide whether to fully or partially prepopulate a cache, and to choose the data to cache. Por ejemplo, puede ser útil propagar la caché con los datos de perfil de usuario estáticos para los clientes que usan la aplicación con regularidad (quizá todos los días), pero no para los clientes que usan la aplicación solo una vez a la semana.For example, it can be useful to seed the cache with the static user profile data for customers who use the application regularly (perhaps every day), but not for customers who use the application only once a week.

El almacenamiento en caché funciona normalmente bien con datos inmutables o que cambian con poca frecuencia.Caching typically works well with data that is immutable or that changes infrequently. Entre los ejemplos se incluye información de referencia, como la información de precios y productos en una aplicación de comercio electrónico, o recursos estáticos compartidos que son costosos de construir.Examples include reference information such as product and pricing information in an e-commerce application, or shared static resources that are costly to construct. Algunos de estos datos, o todos ellos, pueden cargarse en la memoria caché al iniciarse la aplicación para minimizar la demanda de recursos y mejorar el rendimiento.Some or all of this data can be loaded into the cache at application startup to minimize demand on resources and to improve performance. Puede que también sea adecuado contar con un proceso en segundo plano que actualice periódicamente los datos de referencia en la memoria caché para asegurarse de que está actualizada o que actualice la memoria caché cuando cambien los datos de referencia.It might also be appropriate to have a background process that periodically updates reference data in the cache to ensure it is up-to-date, or that refreshes the cache when reference data changes.

El almacenamiento es ser menos útil para los datos dinámicos, aunque hay algunas excepciones a esta consideración (para más información, consulte la sección Almacenar en caché los datos altamente dinámicos más adelante en este artículo).Caching is less useful for dynamic data, although there are some exceptions to this consideration (see the section Cache highly dynamic data later in this article for more information). Cuando los datos originales cambian con frecuencia, la información almacenada en caché se vuelve obsoleta muy rápidamente o la sobrecarga de sincronización de la caché con el almacén de datos original reduce la efectividad del almacenamiento en caché.When the original data changes regularly, either the cached information becomes stale very quickly or the overhead of synchronizing the cache with the original data store reduces the effectiveness of caching.

Tenga en cuenta que una memoria caché no tiene que incluir los datos completos para una entidad.Note that a cache does not have to include the complete data for an entity. Por ejemplo, si un elemento de datos representa un objeto con múltiples valores como un cliente de banco con un nombre, una dirección y un saldo de cuenta, algunos de estos elementos pueden permanecer estáticos (el nombre y la dirección), mientras que otros (como el saldo de la cuenta) pueden ser más dinámicos.For example, if a data item represents a multivalued object such as a bank customer with a name, address, and account balance, some of these elements might remain static (such as the name and address), while others (such as the account balance) might be more dynamic. En estas situaciones, puede ser útil almacenar en caché las partes estáticas de los datos y recuperar solo (o calcular) la información restante cuando sea necesario.In these situations, it can be useful to cache the static portions of the data and retrieve (or calculate) only the remaining information when it is required.

Se recomienda llevar a cabo pruebas de rendimiento y análisis de uso para determinar si es adecuado el rellenado previo, la carga a petición de la memoria caché o una combinación de ambos.We recommend that you carry out performance testing and usage analysis to determine whether prepopulating or on-demand loading of the cache, or a combination of both, is appropriate. La decisión debe basarse en la volatilidad y el patrón de uso de los datos.The decision should be based on the volatility and usage pattern of the data. El análisis de rendimiento y el uso de la memoria caché es especialmente importante en las aplicaciones que tienen cargas pesadas y deben ser altamente escalables.Cache utilization and performance analysis are particularly important in applications that encounter heavy loads and must be highly scalable. Por ejemplo, en escenarios muy escalables, puede tener sentido inicializar la caché para reducir la carga en el almacén de datos en las horas punta.For example, in highly scalable scenarios it might make sense to seed the cache to reduce the load on the data store at peak times.

El almacenamiento en caché también se puede usar para evitar repetir cálculos mientras se ejecuta la aplicación.Caching can also be used to avoid repeating computations while the application is running. Si una operación transforma datos o realiza un cálculo complicado, puede guardar los resultados de la operación en la memoria caché.If an operation transforms data or performs a complicated calculation, it can save the results of the operation in the cache. Si se requiere el mismo cálculo posteriormente, la aplicación puede recuperar simplemente los resultados de la caché.If the same calculation is required afterward, the application can simply retrieve the results from the cache.

Una aplicación puede modificar los datos contenidos en una caché.An application can modify data that's held in a cache. Sin embargo, se recomienda considerar la caché como un almacén de datos transitorios que podrían desaparecer en cualquier momento.However, we recommend thinking of the cache as a transient data store that could disappear at any time. No almacene datos valiosos solo en la caché; asegúrese de mantener también la información en el almacén de datos original.Do not store valuable data in the cache only; make sure that you maintain the information in the original data store as well. Así si la caché deja de estar disponible, se reduce la posibilidad de pérdida de datos.This means that if the cache becomes unavailable, you minimize the chance of losing data.

Almacenar en caché los datos altamente dinámicosCache highly dynamic data

Al almacenar la información que cambia rápidamente en un almacén de datos persistente, se puede crear una sobrecarga en el sistema.When you store rapidly changing information in a persistent data store, it can impose an overhead on the system. Por ejemplo, un dispositivo que informa continuamente del estado o de alguna otra medida.For example, consider a device that continually reports status or some other measurement. Si una aplicación decide no almacenar en caché estos datos según la base de que la información almacenada en caché casi siempre quedará obsoleta, la misma consideración podría ser verdadera al almacenar y recuperar esta información desde el almacén de datos.If an application chooses not to cache this data on the basis that the cached information will nearly always be outdated, then the same consideration could be true when storing and retrieving this information from the data store. En el tiempo en que se tarda en guardar y capturar estos datos, podrían haber cambiado.In the time it takes to save and fetch this data, it might have changed.

En una situación como ésta, considere las ventajas de almacenar la información dinámica directamente en la caché en lugar de en el almacén de datos persistente.In a situation such as this, consider the benefits of storing the dynamic information directly in the cache instead of in the persistent data store. Si los datos no son críticos y no es necesario auditarlos, no importa si se pierde un cambio ocasional.If the data is noncritical and does not require auditing, then it doesn't matter if the occasional change is lost.

Administrar la expiración de los datos en una cachéManage data expiration in a cache

En la mayoría de los casos, los datos contenidos en una caché son una copia de los datos que se encuentran en el almacén de datos original.In most cases, data that's held in a cache is a copy of data that's held in the original data store. Los datos del almacén de datos original pueden cambiar después de haberse almacenado en caché, lo que hace que los datos almacenados en memoria caché se vuelvan obsoletos.The data in the original data store might change after it was cached, causing the cached data to become stale. Muchos sistemas de almacenamiento en caché le habilitan para configurar la memoria caché para expirar datos y reducir el período para el que los datos pueden estar desfasados.Many caching systems enable you to configure the cache to expire data and reduce the period for which data may be out of date.

Cuando los datos almacenados en caché expiran, se eliminan de la memoria caché y la aplicación debe recuperar los datos del almacén de datos original (se puede volver a colocar la información recién capturada en la memoria caché).When cached data expires, it's removed from the cache, and the application must retrieve the data from the original data store (it can put the newly fetched information back into cache). Puede establecer una directiva de expiración predeterminada al configurar la memoria caché.You can set a default expiration policy when you configure the cache. En muchos de los servicios de caché, también puede estipular el período de expiración de objetos individuales cuando los almacena mediante programación en la caché.In many cache services, you can also stipulate the expiration period for individual objects when you store them programmatically in the cache. Algunas cachés permiten especificar el período de expiración como un valor absoluto o como un valor variable que hace que el elemento se elimine de la caché si no se accede a él dentro del tiempo especificado.Some caches enable you to specify the expiration period as an absolute value, or as a sliding value that causes the item to be removed from the cache if it is not accessed within the specified time. Esta configuración invalida cualquier directiva de expiración de toda la memoria caché, pero solo para los objetos especificados.This setting overrides any cache-wide expiration policy, but only for the specified objects.

Nota

Considere detenidamente el período de expiración de la memoria caché y los objetos que contiene.Consider the expiration period for the cache and the objects that it contains carefully. Si hace que sea demasiado breve, los objetos expirarán con demasiada rapidez y reducirá las ventajas del uso de la memoria caché.If you make it too short, objects will expire too quickly and you will reduce the benefits of using the cache. Si hace que el periodo sea demasiado largo, se arriesgan a que los datos se vuelvan obsoletos.If you make the period too long, you risk the data becoming stale.

También es posible que la caché se rellene si se permite que los datos permanezcan residentes durante mucho tiempo.It's also possible that the cache might fill up if data is allowed to remain resident for a long time. En este caso, las solicitudes para agregar nuevos elementos a la caché podrían provocar que se forzara la eliminación de algunos elementos en un proceso conocido como expulsión.In this case, any requests to add new items to the cache might cause some items to be forcibly removed in a process known as eviction. Los servicios de caché normalmente expulsan los datos menos usados recientemente (LRU), pero normalmente puede invalidar esta directiva y evitar que se expulsen los elementos.Cache services typically evict data on a least-recently-used (LRU) basis, but you can usually override this policy and prevent items from being evicted. Sin embargo, si adopta este enfoque, se arriesga a que se supere la memoria que está disponible en la caché.However, if you adopt this approach, you risk exceeding the memory that's available in the cache. Una aplicación que intente agregar un elemento a la caché producirá una excepción.An application that attempts to add an item to the cache will fail with an exception.

Algunas implementaciones de almacenamiento en caché podrían proporcionar directivas de expulsión adicionales.Some caching implementations might provide additional eviction policies. Hay varios tipos de directivas de expulsión.There are several types of eviction policies. Entre ellas se incluyen las siguientes:These include:

  • Una directiva de usados más recientemente (en la expectativa de que los datos no volverán a ser necesarios).A most-recently-used policy (in the expectation that the data will not be required again).
  • Una directiva de primero en entrar primero en salir (los datos más antiguos se expulsan primero).A first-in-first-out policy (oldest data is evicted first).
  • Una directiva de eliminación explícita basada en un evento desencadenado (como los datos que se va a modificar).An explicit removal policy based on a triggered event (such as the data being modified).

Invalidar los datos en una caché del lado clienteInvalidate data in a client-side cache

Por lo general, se considera que los datos que se almacenan en una caché del lado cliente quedan fuera de la protección del servicio que proporciona los datos al cliente.Data that's held in a client-side cache is generally considered to be outside the auspices of the service that provides the data to the client. Un servicio no puede forzar directamente a un cliente a agregar o quitar información de una caché del lado cliente.A service cannot directly force a client to add or remove information from a client-side cache.

Esto significa que es posible que un cliente que utiliza una caché mal configurada pueda seguir usando información obsoleta.This means that it's possible for a client that uses a poorly configured cache to continue using outdated information. Por ejemplo, si las directivas de expiración de la caché no están correctamente implementadas, un cliente podría usar información obsoleta almacenada en caché localmente cuando la información del origen de datos original haya cambiado.For example, if the expiration policies of the cache aren't properly implemented, a client might use outdated information that's cached locally when the information in the original data source has changed.

Si va a crear una aplicación web que sirve datos mediante una conexión HTTP, puede forzar implícitamente a un cliente web (por ejemplo, un explorador o un proxy web) a capturar la información más reciente.If you are building a web application that serves data over an HTTP connection, you can implicitly force a web client (such as a browser or web proxy) to fetch the most recent information. Puede hacer esto si un recurso se actualiza debido a un cambio en el URI de ese recurso.You can do this if a resource is updated by a change in the URI of that resource. Los clientes web usan normalmente el URI de un recurso como clave de la caché del lado cliente, por lo que si el URI cambia, el cliente web ignora las versiones de un recurso almacenadas en caché anteriormente y captura la nueva versión en su lugar.Web clients typically use the URI of a resource as the key in the client-side cache, so if the URI changes, the web client ignores any previously cached versions of a resource and fetches the new version instead.

Administración de la simultaneidad en una memoria cachéManaging concurrency in a cache

Las memorias caché a menudo están diseñadas para ser compartidas por varias instancias de una aplicación.Caches are often designed to be shared by multiple instances of an application. Cada instancia de aplicación puede leer y modificar los datos de la memoria caché.Each application instance can read and modify data in the cache. Por consiguiente, los mismos problemas de simultaneidad que surgen con cualquier almacén de datos compartidos también son aplicables a una caché.Consequently, the same concurrency issues that arise with any shared data store also apply to a cache. En una situación donde una aplicación necesite modificar los datos contenidos en la caché, puede que deba asegurarse de que las actualizaciones realizadas por una instancia de la aplicación no sobrescriben los cambios realizados por otra instancia.In a situation where an application needs to modify data that's held in the cache, you might need to ensure that updates made by one instance of the application do not overwrite the changes made by another instance.

En función de la naturaleza de los datos y de la probabilidad de las colisiones, puede adoptar uno de dos enfoques para simultaneidad:Depending on the nature of the data and the likelihood of collisions, you can adopt one of two approaches to concurrency:

  • Optimista.Optimistic. Inmediatamente antes de actualizarlos, la aplicación comprueba si han cambiado los datos de la caché desde que se recuperaron.Immediately prior to updating the data, the application checks to see whether the data in the cache has changed since it was retrieved. Si los datos siguen siendo los mismos, se pueden realizar el cambio.If the data is still the same, the change can be made. De lo contrario, la aplicación tiene que decidir si los va a actualizar.Otherwise, the application has to decide whether to update it. (La lógica de negocios que impulsa esta decisión será específica de la aplicación). Este enfoque es adecuado para situaciones en las que las actualizaciones no son frecuentes o donde es improbable que se produzcan colisiones.(The business logic that drives this decision will be application-specific.) This approach is suitable for situations where updates are infrequent, or where collisions are unlikely to occur.
  • Pesimista.Pessimistic. Cuando la aplicación recupera los datos, los bloquea en la caché para impedir que otra instancia los cambie.When it retrieves the data, the application locks it in the cache to prevent another instance from changing it. Este proceso garantiza que no se produzcan colisiones, pero puede bloquear otras instancias que deben procesar los mismos datos.This process ensures that collisions cannot occur, but they can also block other instances that need to process the same data. La simultaneidad pesimista puede afectar a la escalabilidad de la solución y debe usarse únicamente en operaciones de corta duración.Pessimistic concurrency can affect the scalability of a solution and is recommended only for short-lived operations. Este enfoque puede ser adecuado en situaciones donde existe una mayor probabilidad de colisiones, especialmente si una aplicación actualiza varios elementos de la caché y debe asegurarse de que estos cambios se apliquen de forma coherente.This approach might be appropriate for situations where collisions are more likely, especially if an application updates multiple items in the cache and must ensure that these changes are applied consistently.

Implementar alta disponibilidad y escalabilidad y mejorar el rendimientoImplement high availability and scalability, and improve performance

Evite usar una caché como repositorio principal de los datos; esta es la función del almacén de datos original desde el que se rellena la caché.Avoid using a cache as the primary repository of data; this is the role of the original data store from which the cache is populated. El almacén de datos original es responsable de garantizar la persistencia de los datos.The original data store is responsible for ensuring the persistence of the data.

Tenga cuidado de no introducir dependencias críticas en la disponibilidad de un servicio de caché compartida en sus soluciones.Be careful not to introduce critical dependencies on the availability of a shared cache service into your solutions. Una aplicación debe poder seguir funcionando si el servicio que proporciona la caché compartida no está disponible.An application should be able to continue functioning if the service that provides the shared cache is unavailable. La aplicación no debería dejar de responder ni producir errores mientras espera a que el servicio de almacenamiento en caché se reanude.The application should not become unresponsive or fail while waiting for the cache service to resume.

Por tanto, la aplicación debe estar preparada para detectar la disponibilidad del servicio de caché y revertir al almacén de datos original si la memoria caché no está accesible.Therefore, the application must be prepared to detect the availability of the cache service and fall back to the original data store if the cache is inaccessible. El patrón de interruptor es útil para controlar este escenario.The Circuit-Breaker pattern is useful for handling this scenario. El servicio que proporciona la caché se puede recuperar y, una vez que está disponible, la caché se puede volver a llenar a medida que se leen datos del almacén de datos original mediante una estrategia como la del patrón cache-aside.The service that provides the cache can be recovered, and once it becomes available, the cache can be repopulated as data is read from the original data store, following a strategy such as the Cache-aside pattern.

Sin embargo, la escalabilidad del sistema puede verse afectada si la aplicación retrocede al almacén de datos original cuando la memoria caché deja de estar temporalmente disponible.However, system scalability may be affected if the application falls back to the original data store when the cache is temporarily unavailable. Mientras el almacén de datos de se recupera, el almacén de datos original podría inundarse de solicitudes de datos, dando lugar a tiempos de espera y conexiones con error.While the data store is being recovered, the original data store could be swamped with requests for data, resulting in timeouts and failed connections.

Considere la posibilidad de implementar una caché privada local en cada instancia de una aplicación junto con la caché compartida a la que tienen acceso todas las instancias de la aplicación.Consider implementing a local, private cache in each instance of an application, together with the shared cache that all application instances access. Cuando la aplicación recupera un elemento, puede comprobar primero en su caché local, luego en la caché compartida y finalmente en el almacén de datos original.When the application retrieves an item, it can check first in its local cache, then in the shared cache, and finally in the original data store. La caché local se pueden rellenar con los datos de la caché compartida, o de la base de datos en caso de que la caché compartida no esté disponible.The local cache can be populated using the data in either the shared cache, or in the database if the shared cache is unavailable.

Este enfoque requiere tener mucho cuidado con la configuración para evitar que la caché local se vuelva demasiado obsoleta con respecto a la caché compartida.This approach requires careful configuration to prevent the local cache from becoming too stale with respect to the shared cache. Sin embargo, la caché local actúa como búfer si la caché compartida es inaccesible.However, the local cache acts as a buffer if the shared cache is unreachable. En la Figura 3 se muestra esta estructura.Figure 3 shows this structure.

Uso de una caché privada local con memoria caché compartida

Figura 3: Uso de una caché privada local con memoria caché compartida.Figure 3: Using a local private cache with a shared cache.

Para admitir cachés de gran tamaño con datos de duración relativamente larga, algunos servicios de caché ofrecen una opción de alta disponibilidad que implementa la conmutación automática por error si la memoria caché dejar de estar disponible.To support large caches that hold relatively long-lived data, some cache services provide a high-availability option that implements automatic failover if the cache becomes unavailable. Este enfoque implica normalmente la réplica de los datos en caché que se almacenan en un servidor de caché principal en un servidor de caché secundario y el cambio al servidor secundario si el servicio principal genera error o se pierde la conectividad.This approach typically involves replicating the cached data that's stored on a primary cache server to a secondary cache server, and switching to the secondary server if the primary server fails or connectivity is lost.

Para reducir la latencia asociada a la escritura en varios destinos, cuando se escriben datos en la caché del servidor principal, la replicación en el servidor secundario puede producirse de forma asincrónica.To reduce the latency that's associated with writing to multiple destinations, the replication to the secondary server might occur asynchronously when data is written to the cache on the primary server. Este enfoque lleva a la posibilidad de que se pueda perder parte de la información almacenada en caché en el caso de un error, pero la proporción de estos datos debe ser pequeña en comparación con el tamaño total de la caché.This approach leads to the possibility that some cached information might be lost in the event of a failure, but the proportion of this data should be small compared to the overall size of the cache.

Si una caché compartida es grande, puede resultar ventajoso crear particiones de los datos en caché en los nodos para reducir las posibilidades de contención y mejorar la escalabilidad.If a shared cache is large, it might be beneficial to partition the cached data across nodes to reduce the chances of contention and improve scalability. Muchas cachés compartidas admiten la capacidad de agregar (y de quitar) nodos dinámicamente y de reequilibrar los datos entre las particiones.Many shared caches support the ability to dynamically add (and remove) nodes and rebalance the data across partitions. Este enfoque puede implicar la agrupación en clústeres, en el que la colección de nodos se presenta a las aplicaciones cliente como una caché única y eficiente.This approach might involve clustering, in which the collection of nodes is presented to client applications as a seamless, single cache. Internamente, sin embargo, los datos se dispersan entre los nodos siguiendo una estrategia de distribución predefinida que equilibra la carga uniformemente.Internally, however, the data is dispersed between nodes following a predefined distribution strategy that balances the load evenly. Para más información acerca de posibles estrategias de particiones, consulte Guía de creación de particiones de datos.For more information about possible partitioning strategies, see Data partitioning guidance.

La agrupación en clústeres también puede aumentar la disponibilidad de la caché.Clustering can also increase the availability of the cache. Si se produce un error en un nodo, el resto de la caché sigue siendo accesible.If a node fails, the remainder of the cache is still accessible. La agrupación en clústeres se utiliza con frecuencia junto con la replicación y la conmutación por error.Clustering is frequently used in conjunction with replication and failover. Cada nodo se puede replicar y la réplica se puede poner en línea rápidamente si se produce un error en el nodo.Each node can be replicated, and the replica can be quickly brought online if the node fails.

En muchas operaciones de lectura y escritura intervendrán probablemente objetos o valores de datos únicos.Many read and write operations are likely to involve single data values or objects. Sin embargo, en ocasiones puede ser necesario almacenar o recuperar rápidamente grandes volúmenes de datos.However, at times it might be necessary to store or retrieve large volumes of data quickly. Por ejemplo, la inicialización de una caché podría suponer la escritura de cientos o miles de elementos en la caché.For example, seeding a cache could involve writing hundreds or thousands of items to the cache. Una aplicación también podría necesitar recuperar de la caché un gran número de elementos relacionados como parte de la misma solicitud.An application might also need to retrieve a large number of related items from the cache as part of the same request.

Para estos fines, muchas cachés a gran escala ofrecen operaciones por lotes.Many large-scale caches provide batch operations for these purposes. De esta forma una aplicación cliente puede empaquetar un gran volumen de elementos en una única solicitud y reduce la sobrecarga asociada con la realización de un gran número de solicitudes pequeñas.This enables a client application to package up a large volume of items into a single request and reduces the overhead that's associated with performing a large number of small requests.

Almacenamiento en caché y coherencia eventualCaching and eventual consistency

Para que el patrón cache-aside funcione, la instancia de la aplicación que rellena la caché debe tener acceso a la versión más reciente y coherente de los datos.For the cache-aside pattern to work, the instance of the application that populates the cache must have access to the most recent and consistent version of the data. En un sistema que implementa coherencia eventual (como un almacén de datos replicados), este podría no ser el caso.In a system that implements eventual consistency (such as a replicated data store) this might not be the case.

Una instancia de una aplicación podría modificar un elemento de datos e invalidar la versión almacenada en caché de ese elemento.One instance of an application could modify a data item and invalidate the cached version of that item. Otra instancia de la aplicación podría intentar leer este elemento de una caché, lo que produce un error de caché, así que lee los datos del almacén de datos y los agrega a la caché.Another instance of the application might attempt to read this item from a cache, which causes a cache-miss, so it reads the data from the data store and adds it to the cache. Sin embargo, si el almacén de datos no se ha sincronizado por completo con las demás réplicas, la instancia de la aplicación podría leer la caché y rellenarla con el valor antiguo.However, if the data store has not been fully synchronized with the other replicas, the application instance could read and populate the cache with the old value.

Para más información sobre cómo administrar la coherencia de los datos, consulte la página Data consistency primer (Aspectos básicos de la coherencia de los datos).For more information about handling data consistency, see the Data consistency primer.

Proteger los datos almacenados en cachéProtect cached data

Sea cual sea el servicio de caché que utilice, debe pensar en cómo proteger los datos contenidos en la caché frente al acceso no autorizado.Irrespective of the cache service you use, consider how to protect the data that's held in the cache from unauthorized access. Hay dos cuestiones principales:There are two main concerns:

  • La privacidad de los datos en la caché.The privacy of the data in the cache.
  • La privacidad de los datos a medida que fluyen entre la caché y la aplicación que la utiliza.The privacy of data as it flows between the cache and the application that's using the cache.

Para proteger los datos de la caché, el servicio de caché podría implementar un mecanismo de autenticación que requiere que las aplicaciones especifiquen lo siguiente:To protect data in the cache, the cache service might implement an authentication mechanism that requires that applications specify the following:

  • Qué identidades pueden tener acceso a datos de la caché.Which identities can access data in the cache.
  • Qué operaciones (lectura y escritura) se permite que realicen estas identidades.Which operations (read and write) that these identities are allowed to perform.

Para reducir la sobrecarga asociada a la lectura y la escritura de datos, una vez que se ha concedido acceso de lectura/o escritura a una entidad, dicha identidad puede usar cualquier dato de la caché.To reduce overhead that's associated with reading and writing data, after an identity has been granted write and/or read access to the cache, that identity can use any data in the cache.

Si necesita restringir el acceso a los subconjuntos de los datos en caché, puede hacer lo siguiente:If you need to restrict access to subsets of the cached data, you can do one of the following:

  • Dividir la caché en particiones (mediante el uso de distintos servidores de caché) y conceder a las identidades acceso únicamente a las particiones para las que deben tener permiso de uso.Split the cache into partitions (by using different cache servers) and only grant access to identities for the partitions that they should be allowed to use.
  • Cifrar los datos de cada subconjunto con claves diferentes y proporcionar únicamente las claves de cifrado a las identidades que deben tener acceso a cada subconjunto.Encrypt the data in each subset by using different keys, and provide the encryption keys only to identities that should have access to each subset. Aún así, una aplicación cliente podría ser capaz de recuperar todos los datos de la caché, pero solo podrá descifrar los datos para los que tiene las claves.A client application might still be able to retrieve all of the data in the cache, but it will only be able to decrypt the data for which it has the keys.

También debe proteger los datos que fluyen dentro y fuera de la caché.You must also protect the data as it flows in and out of the cache. Para ello, depende de las características de seguridad proporcionadas por la infraestructura de red que usan las aplicaciones cliente para conectarse a la caché.To do this, you depend on the security features provided by the network infrastructure that client applications use to connect to the cache. Si la caché se implementa mediante un servidor local en la misma organización que hospeda las aplicaciones cliente, el aislamiento de la propia red podría no requerir que lleve a cabo pasos adicionales.If the cache is implemented using an on-site server within the same organization that hosts the client applications, then the isolation of the network itself might not require you to take additional steps. Si la caché se encuentra ubicada de manera remota y requiere una conexión TCP o HTTP mediante una red pública (como Internet), considere la posibilidad de implementar SSL.If the cache is located remotely and requires a TCP or HTTP connection over a public network (such as the Internet), consider implementing SSL.

Consideraciones para implementar el almacenamiento en caché en AzureConsiderations for implementing caching in Azure

Azure Cache for Redis es una implementación del almacenamiento en caché de Redis de código abierto que se ejecuta como un servicio en un centro de datos de Azure.Azure Cache for Redis is an implementation of the open source Redis cache that runs as a service in an Azure datacenter. Ofrece un servicio de almacenamiento en caché al que se puede acceder desde cualquier aplicación de Azure, ya se implementa la aplicación como servicio en la nube, un sitio web o dentro de una máquina virtual de Azure.It provides a caching service that can be accessed from any Azure application, whether the application is implemented as a cloud service, a website, or inside an Azure virtual machine. Las memorias caché pueden compartirse entre aplicaciones cliente que dispongan de la clave de acceso adecuado.Caches can be shared by client applications that have the appropriate access key.

Azure Cache for Redis es una solución de almacenamiento en caché de alto rendimiento que ofrece disponibilidad, escalabilidad y seguridad.Azure Cache for Redis is a high-performance caching solution that provides availability, scalability and security. Normalmente se ejecuta como un servicio distribuido entre una o varias máquinas dedicadas.It typically runs as a service spread across one or more dedicated machines. Su función es intentar almacenar tanta información como sea posible en la memoria para garantizar un acceso rápido.It attempts to store as much information as it can in memory to ensure fast access. Esta arquitectura está pensada para ofrecer baja latencia y alto rendimiento al reducir la necesidad de realizar operaciones lentas de E/S.This architecture is intended to provide low latency and high throughput by reducing the need to perform slow I/O operations.

Azure Cache for Redis es compatible con muchas de las distintas API que usan las aplicaciones cliente.Azure Cache for Redis is compatible with many of the various APIs that are used by client applications. Si tiene aplicaciones existentes que ya usan Azure Cache for Redis localmente, Azure Cache for Redis ofrece una ruta de migración rápida para el almacenamiento en caché en la nube.If you have existing applications that already use Azure Cache for Redis running on-premises, the Azure Cache for Redis provides a quick migration path to caching in the cloud.

Características de RedisFeatures of Redis

Redis es más que un simple servidor de caché.Redis is more than a simple cache server. Proporciona una base de datos en memoria distribuida con un conjunto extenso de comandos que admite muchos escenarios comunes.It provides a distributed in-memory database with an extensive command set that supports many common scenarios. Estos métodos se describen más adelante en este documento, en la sección Uso del almacenamiento en caché de Redis.These are described later in this document, in the section Using Redis caching. En esta sección se resumen algunas de las características clave que ofrece Redis.This section summarizes some of the key features that Redis provides.

Redis como base de datos en memoriaRedis as an in-memory database

Redis admite operaciones tanto de lectura como de escritura.Redis supports both read and write operations. En Redis, las escrituras se pueden proteger de los errores del sistema almacenándolas periódicamente en un archivo de instantánea local o en un archivo de registro de solo anexo.In Redis, writes can be protected from system failure either by being stored periodically in a local snapshot file or in an append-only log file. No es el caso de muchas caché (lo que se debe tener en cuenta en los almacenes de datos transitorios).This is not the case in many caches (which should be considered transitory data stores).

Todas las escrituras son asincrónicas y no impiden que los clientes lean y escriban datos.All writes are asynchronous and do not block clients from reading and writing data. Cuando Redis empieza a ejecutarse, lee los datos del archivo de registro o de instantánea y lo usa para construir la caché en memoria.When Redis starts running, it reads the data from the snapshot or log file and uses it to construct the in-memory cache. Para más información, consulte Redis persistence (Persistencia de Redis) en el sitio web de Redis.For more information, see Redis persistence on the Redis website.

Nota

Redis no garantiza que todas las escrituras se guarden en caso de un error grave, pero en el peor de los casos solo perdería unos segundos de datos.Redis does not guarantee that all writes will be saved in the event of a catastrophic failure, but at worst you might lose only a few seconds worth of data. Recuerde que una memoria caché no está diseñada para actuar como un origen de datos autoritativo y que es responsabilidad de las aplicaciones que usan la memoria caché asegurarse de que los datos críticos se guardan correctamente en un almacén de datos adecuado.Remember that a cache is not intended to act as an authoritative data source, and it is the responsibility of the applications using the cache to ensure that critical data is saved successfully to an appropriate data store. Para más información, consulte el patrón reservado en caché.For more information, see the Cache-aside pattern.

Tipos de datos de RedisRedis data types

Redis es un almacén de valor-clave, donde los valores pueden contener estructuras de datos complejos o tipos simples, como valores hash, listas y conjuntos.Redis is a key-value store, where values can contain simple types or complex data structures such as hashes, lists, and sets. Admite un conjunto de operaciones atómicas en estos tipos de datos.It supports a set of atomic operations on these data types. Las claves pueden ser permanentes o estar etiquetadas con un tiempo limitado de vida, momento en el cual se quitan automáticamente de la caché la clave y su valor correspondiente.Keys can be permanent or tagged with a limited time-to-live, at which point the key and its corresponding value are automatically removed from the cache. Para más información sobre los valores y las claves de Redis, visite la página An introduction to Redis data types and abstractions (Introducción a los tipos de datos y abstracciones de Redis) en el sitio web de Redis.For more information about Redis keys and values, visit the page An introduction to Redis data types and abstractions on the Redis website.

Agrupación en clústeres y replicación de RedisRedis replication and clustering

Redis admite la replicación principal/subordinado para ayudar a garantizar la disponibilidad y mantener el rendimiento.Redis supports primary/subordinate replication to help ensure availability and maintain throughput. Las operaciones de escritura en un nodo principal de Redis se replican a uno o varios nodos subordinados.Write operations to a Redis primary node are replicated to one or more subordinate nodes. Las operaciones de lectura pueden ser atendidas por el principal o cualquiera de los subordinados.Read operations can be served by the primary or any of the subordinates.

En el caso de una partición de red, los subordinados pueden continuar sirviendo datos y luego volver a sincronizar de manera transparente con el principal cuando se restablece la conexión.In the event of a network partition, subordinates can continue to serve data and then transparently resynchronize with the primary when the connection is reestablished. Para obtener más información, visite la página Replicación en el sitio web de Redis.For further details, visit the Replication page on the Redis website.

Redis también ofrece agrupación en clústeres, lo que le permite particionar los datos de manera transparente en particiones entre servidores y distribuir la carga.Redis also provides clustering, which enables you to transparently partition data into shards across servers and spread the load. Esta característica mejora la escalabilidad, puesto que se pueden agregar nuevos servidores de Redis y se pueden volver a particionar los datos conforme aumenta el tamaño de la caché.This feature improves scalability, because new Redis servers can be added and the data repartitioned as the size of the cache increases.

Además, cada servidor del clúster se puede replicar mediante la replicación principal/subordinado.Furthermore, each server in the cluster can be replicated by using primary/subordinate replication. Esto garantiza la disponibilidad en cada nodo del clúster.This ensures availability across each node in the cluster. Para más información sobre la agrupación en clústeres y el particionamiento, visite la página del tutorial del clúster de Redis en el sitio web de Redis.For more information about clustering and sharding, visit the Redis cluster tutorial page on the Redis website.

Uso de la memoria RedisRedis memory use

Una caché de Redis tiene un tamaño limitado que depende de los recursos disponibles en el equipo host.A Redis cache has a finite size that depends on the resources available on the host computer. Al configurar un servidor de Redis, puede especificar la cantidad máxima de memoria que puede usar.When you configure a Redis server, you can specify the maximum amount of memory it can use. También puede configurar una clave en una caché de Redis para que tenga un tiempo de expiración, tras lo cual se quita automáticamente de la caché.You can also configure a key in a Redis cache to have an expiration time, after which it is automatically removed from the cache. Esta característica puede ayudar a impedir que la caché en memoria se rellene con datos obsoletos o antiguos.This feature can help prevent the in-memory cache from filling with old or stale data.

Conforme se rellena la memoria, Redis puede expulsar automáticamente las claves y sus valores siguiendo varias directivas.As memory fills up, Redis can automatically evict keys and their values by following a number of policies. El valor predeterminado es LRU (menos usados recientemente), pero también puede seleccionar otras directivas como expulsar las claves de manera aleatoria o desactivar completamente la expulsión (en cuyo caso, los intentos de agregar elementos a la caché generarán error si se llena).The default is LRU (least recently used), but you can also select other policies such as evicting keys at random or turning off eviction altogether (in which, case attempts to add items to the cache fail if it is full). En la página Using Redis as an LRU cache (Uso de Redis como caché de LRU) se ofrece más información.The page Using Redis as an LRU cache provides more information.

Lotes y transacciones de RedisRedis transactions and batches

Redis habilita una aplicación cliente para que envíe una serie de operaciones que leer y escriben datos en la memoria caché como una transacción atómica.Redis enables a client application to submit a series of operations that read and write data in the cache as an atomic transaction. Se tiene la garantía de que todos los comandos de la transacción se ejecutan secuencialmente y de que ninguno de los comandos emitidos por otros clientes simultáneos se entrelazará entre ellos.All the commands in the transaction are guaranteed to run sequentially, and no commands issued by other concurrent clients will be interwoven between them.

Sin embargo, estas no son verdaderas transacciones como las realizaría una base de datos relacional.However, these are not true transactions as a relational database would perform them. El procesamiento de transacciones consta de dos fases: la primera es cuando los comandos se ponen en cola y la segunda es cuando los comandos se ejecutan.Transaction processing consists of two stages--the first is when the commands are queued, and the second is when the commands are run. Durante la fase de puesta en cola de comandos, el cliente envía los comandos que componen la transacción.During the command queuing stage, the commands that comprise the transaction are submitted by the client. Si se produce algún tipo de error en este momento (por ejemplo, un error de sintaxis o un número incorrecto de parámetros), Redis rechaza el procesamiento de toda la transacción y la descarta.If some sort of error occurs at this point (such as a syntax error, or the wrong number of parameters) then Redis refuses to process the entire transaction and discards it.

Durante la fase de ejecución, Redis ejecuta cada comando en cola en secuencia.During the run phase, Redis performs each queued command in sequence. Si se produce un error de un comando durante esta fase, Redis continuará con el siguiente comando en cola y no revertirá los efectos de los comandos que ya se hayan ejecutado.If a command fails during this phase, Redis continues with the next queued command and does not roll back the effects of any commands that have already been run. Esta forma simplificada de transacción ayuda a mantener el rendimiento y a evitar los problemas de rendimiento provocados por la contención.This simplified form of transaction helps to maintain performance and avoid performance problems that are caused by contention.

Redis no implementa una forma de bloqueo optimista para ayudar a mantener la coherencia.Redis does implement a form of optimistic locking to assist in maintaining consistency. Para obtener información detallada sobre las transacciones y el bloqueo con Redis, visite la página Transacciones del sitio web de Redis.For detailed information about transactions and locking with Redis, visit the Transactions page on the Redis website.

Redis también admite el procesamiento por lotes no transaccional de solicitudes.Redis also supports nontransactional batching of requests. El protocolo Redis que usan los clientes para enviar comandos a un servidor de Redis permite a un cliente enviar una serie de operaciones como parte de la misma solicitud.The Redis protocol that clients use to send commands to a Redis server enables a client to send a series of operations as part of the same request. Esto puede ayudar a reducir la fragmentación de paquetes en la red.This can help to reduce packet fragmentation on the network. Cuando se procesa el lote, se lleva a cabo cada comando.When the batch is processed, each command is performed. Si alguno de estos comandos tienen un formato incorrecto, se rechazará (lo que no sucede con una transacción), pero los comandos restantes se ejecutarán.If any of these commands are malformed, they will be rejected (which doesn't happen with a transaction), but the remaining commands will be performed. Tampoco hay ninguna garantía sobre el orden en el que se procesarán los comandos del lote.There is also no guarantee about the order in which the commands in the batch will be processed.

Seguridad de RedisRedis security

Redis se centra exclusivamente en ofrecer un acceso rápido a los datos y está diseñado para ejecutarse dentro de un entorno de confianza al que solo puedan acceder los clientes de confianza.Redis is focused purely on providing fast access to data, and is designed to run inside a trusted environment that can be accessed only by trusted clients. Redis admite un modelo de seguridad limitada basado en la autenticación mediante contraseña.Redis supports a limited security model based on password authentication. (Aunque es posible quitar la autenticación completamente, no se recomienda).(It is possible to remove authentication completely, although we don't recommend this.)

Todos los clientes autenticados comparten la misma contraseña global y tienen acceso a los mismo recursos.All authenticated clients share the same global password and have access to the same resources. Si necesita una seguridad de inicio de sesión más completa, debe implementar su propia capa de seguridad delante del servidor de Redis y todas las solicitudes de cliente deben pasar por esta capa adicional.If you need more comprehensive sign-in security, you must implement your own security layer in front of the Redis server, and all client requests should pass through this additional layer. Redis no debe exponerse directamente a clientes que no sean de confianza o sin autenticar.Redis should not be directly exposed to untrusted or unauthenticated clients.

Puede restringir el acceso a los comandos deshabilitándolos o cambiándolos de nombre (y ofreciendo solo a los clientes con privilegios los nuevos nombres).You can restrict access to commands by disabling them or renaming them (and by providing only privileged clients with the new names).

Redis no admite directamente ninguna forma de cifrado de datos, por lo que toda la codificación debe realizarse por las aplicaciones cliente.Redis does not directly support any form of data encryption, so all encoding must be performed by client applications. Además, Redis no proporciona ninguna forma de seguridad de transporte.Additionally, Redis does not provide any form of transport security. Si necesita proteger los datos que fluyen a través de la red, se recomienda implementar un proxy SSL.If you need to protect data as it flows across the network, we recommend implementing an SSL proxy.

Para más información, visite la página Redis Security (Seguridad de Redis) en el sitio web de Redis.For more information, visit the Redis security page on the Redis website.

Nota

Azure Cache for Redis proporciona su propia capa de seguridad mediante la cual se conectan los clientes.Azure Cache for Redis provides its own security layer through which clients connect. Los servidores de Redis subyacentes no se exponen a la red pública.The underlying Redis servers are not exposed to the public network.

Caché en Redis de AzureAzure Redis cache

Azure Cache for Redis proporciona acceso a servidores de Redis que se hospedan en un centro de datos de Azure.Azure Cache for Redis provides access to Redis servers that are hosted at an Azure datacenter. Actúa como una fachada que ofrece control de acceso y seguridad.It acts as a façade that provides access control and security. Puede aprovisionar una caché mediante el Portal de Azure.You can provision a cache by using the Azure portal.

En él se proporcionan varias configuraciones predefinidas.The portal provides a number of predefined configurations. Estas van desde una caché de 53 GB que se ejecuta como un servicio dedicado que admite comunicaciones SSL (para la privacidad) y la replicación maestro/subordinado con un SLA del 99,9 % de disponibilidad, hasta una caché de 250 MB sin replicación (sin garantía de disponibilidad) que se ejecuta en hardware compartido.These range from a 53 GB cache running as a dedicated service that supports SSL communications (for privacy) and master/subordinate replication with an SLA of 99.9% availability, down to a 250 MB cache without replication (no availability guarantees) running on shared hardware.

Mediante el Portal de Azure, también puede configurar la directiva de expulsión de la caché y agregar usuarios a los roles proporcionados con el fin de controlar el acceso.Using the Azure portal, you can also configure the eviction policy of the cache, and control access to the cache by adding users to the roles provided. Estos roles, que definen las operaciones que pueden realizar los miembros, incluyen Propietario, Colaborador y Lector.These roles, which define the operations that members can perform, include Owner, Contributor, and Reader. Por ejemplo, los miembros del rol Propietario tienen control completo sobre la caché (incluida la seguridad) y su contenido, los miembros del rol Colaborador pueden leer y escribir información en la caché y los miembros del rol Lector solo pueden recuperar datos de la caché.For example, members of the Owner role have complete control over the cache (including security) and its contents, members of the Contributor role can read and write information in the cache, and members of the Reader role can only retrieve data from the cache.

La mayoría de las tareas administrativas se realizan mediante el Portal de Azure.Most administrative tasks are performed through the Azure portal. Por este motivo, muchos de los comandos administrativos disponibles en la versión estándar de Redis no están disponibles, como la posibilidad de modificar la configuración mediante programación, apagar el servidor de Redis, configurar subordinados adicionales o forzar el proceso de guardado de los datos en el disco.For this reason, many of the administrative commands that are available in the standard version of Redis are not available, including the ability to modify the configuration programmatically, shut down the Redis server, configure additional subordinates, or forcibly save data to disk.

El Portal de Azure incluye una práctica visualización gráfica que le permite supervisar el rendimiento de la caché.The Azure portal includes a convenient graphical display that enables you to monitor the performance of the cache. Por ejemplo, puede ver el número de conexiones que se realizan, el número de solicitudes llevadas a cabo, el volumen de lecturas y escrituras y el número de aciertos frente a errores de caché.For example, you can view the number of connections being made, the number of requests being performed, the volume of reads and writes, and the number of cache hits versus cache misses. Con esta información puede determinar la eficacia de la caché y, en caso necesario, cambiar a una configuración diferente o cambiar la directiva de expulsión.Using this information, you can determine the effectiveness of the cache and if necessary, switch to a different configuration or change the eviction policy.

Además, puede crear alertas que envíen mensajes de correo electrónico a un administrador si una o más métricas críticas quedan fuera de un intervalo esperado.Additionally, you can create alerts that send email messages to an administrator if one or more critical metrics fall outside of an expected range. Por ejemplo, puede que quiera alertar a un administrador si el número de errores de caché supera un valor especificado en la última hora, ya que significa que la caché podría ser demasiado pequeña o los datos se podrían estar expulsando demasiado rápido.For example, you might want to alert an administrator if the number of cache misses exceeds a specified value in the last hour, because it means the cache might be too small or data might be being evicted too quickly.

También puede supervisar la CPU, la memoria y el uso de la red de la caché.You can also monitor the CPU, memory, and network usage for the cache.

Para más información y ejemplos en los que se muestra cómo crear y configurar una instancia de Azure Cache for Redis, visite la página En torno a Azure Cache for Redis en el blog de Azure.For further information and examples showing how to create and configure an Azure Cache for Redis, visit the page Lap around Azure Cache for Redis on the Azure blog.

Estado de la sesión del almacenamiento en caché y salida HTMLCaching session state and HTML output

Si va a crear aplicaciones web de ASP.NET que se ejecutan mediante roles web de Azure, puede guardar información del estado de la sesión y la salida HTML en una instancia de Azure Cache for Redis.If you're building ASP.NET web applications that run by using Azure web roles, you can save session state information and HTML output in an Azure Cache for Redis. El proveedor de estados de sesión para Azure Cache for Redis le permite compartir información de sesión entre diferentes instancias de una aplicación web de ASP.NET y es muy útil en situaciones de granja de servidores web donde no está disponible la afinidad cliente-servidor y los datos de sesión de almacenamiento en caché en memoria no serían adecuados.The session state provider for Azure Cache for Redis enables you to share session information between different instances of an ASP.NET web application, and is very useful in web farm situations where client-server affinity is not available and caching session data in-memory would not be appropriate.

El uso del proveedor de estados de sesión con Azure Cache for Redis ofrece varias ventajas, entre las que se incluyen:Using the session state provider with Azure Cache for Redis delivers several benefits, including:

  • Uso compartido del estado de sesión con un gran número de instancias de aplicaciones web ASP.NET.Sharing session state with a large number of instances of ASP.NET web applications.
  • Escalabilidad mejorada.Providing improved scalability.
  • Compatibilidad con acceso simultáneo y controlado a los mismos datos de estado de sesión para múltiples lectores y un escritor único.Supporting controlled, concurrent access to the same session state data for multiple readers and a single writer.
  • Posibilidad de usar compresión para ahorrar memoria y mejorar el rendimiento de la red.Using compression to save memory and improve network performance.

Para más información, consulte Proveedor de estado de sesión de ASP.NET para Azure Cache for Redis.For more information, see ASP.NET session state provider for Azure Cache for Redis.

Nota

No use el proveedor de estado de sesión de Azure Cache for Redis con aplicaciones de ASP.NET que se ejecutan fuera del entorno de Azure.Do not use the session state provider for Azure Cache for Redis with ASP.NET applications that run outside of the Azure environment. La latencia del acceso a la memoria caché desde fuera de Azure puede eliminar las ventajas del rendimiento del almacenamiento en caché de los datos.The latency of accessing the cache from outside of Azure can eliminate the performance benefits of caching data.

De forma similar, el proveedor de memoria caché de salida para Azure Cache for Redis permite guardar las respuestas HTTP generadas por una aplicación web de ASP.NET.Similarly, the output cache provider for Azure Cache for Redis enables you to save the HTTP responses generated by an ASP.NET web application. El uso del proveedor de memoria caché de salida con Azure Cache for Redis puede mejorar los tiempos de respuesta de las aplicaciones que representan una salida HTML compleja.Using the output cache provider with Azure Cache for Redis can improve the response times of applications that render complex HTML output. Las instancias de aplicación que generan respuestas similares pueden hacer uso de los fragmentos de salida compartidos en la memoria caché en lugar de generar esta salida HTML de nuevo.Application instances that generate similar responses can use the shared output fragments in the cache rather than generating this HTML output afresh. Para más información, consulte Proveedor de memoria caché de salida de ASP.NET para Azure Cache for Redis.For more information, see ASP.NET output cache provider for Azure Cache for Redis.

Creación de una caché en Redis personalizadaBuilding a custom Redis cache

Azure Cache for Redis actúa como una fachada para los servidores de Redis subyacentes.Azure Cache for Redis acts as a façade to the underlying Redis servers. Si necesita una configuración avanzada que escapa del ámbito de Caché en Redis de Azure (por ejemplo, una caché mayor de 53 GB) puede crear y hospedar sus propios servidores Redis con máquinas virtuales de Azure.If you require an advanced configuration that is not covered by the Azure Redis cache (such as a cache bigger than 53 GB) you can build and host your own Redis servers by using Azure virtual machines.

Este es un proceso potencialmente complejo, ya que podría tener que crear varias máquinas virtuales para que actúen como nodos principal y subordinados si desea implementar la replicación.This is a potentially complex process because you might need to create several VMs to act as primary and subordinate nodes if you want to implement replication. Además, si desea crear un clúster, necesita varios servidores principales y subordinados.Furthermore, if you wish to create a cluster, then you need multiple primaries and subordinate servers. Una topología mínima de replicación en clúster que proporciona un alto grado de disponibilidad y escalabilidad consta de seis máquinas virtuales como mínimo organizadas en tres pares de servidores principal/subordinado (un clúster debe contener al menos tres nodos principales).A minimal clustered replication topology that provides a high degree of availability and scalability comprises at least six VMs organized as three pairs of primary/subordinate servers (a cluster must contain at least three primary nodes).

Cada par principal/subordinado debe estar cerca uno del otro para reducir la latencia.Each primary/subordinate pair should be located close together to minimize latency. Sin embargo, si desea colocar los datos almacenados en caché cerca de las aplicaciones que es más probable que se utilicen, cada conjunto de pares se puede estar ejecutando en distintos centros de datos Azure ubicados en diferentes regiones.However, each set of pairs can be running in different Azure datacenters located in different regions, if you wish to locate cached data close to the applications that are most likely to use it. Para obtener un ejemplo de creación y configuración de un nodo de Redis que se ejecuta como una máquina virtual de Azure, consulte Running Redis on a CentOS Linux VM in Azure (Ejecución de Redis en una máquina virtual Linux CentOS en Azure).For an example of building and configuring a Redis node running as an Azure VM, see Running Redis on a CentOS Linux VM in Azure.

Nota

Si implementa su propio almacenamiento en memoria caché de Redis de esta manera, usted es responsable de supervisar, administrar y proteger el servicio.If you implement your own Redis cache in this way, you are responsible for monitoring, managing, and securing the service.

Creación de particiones de una caché en RedisPartitioning a Redis cache

La creación de particiones de la memoria caché implica la división de la memoria caché en varios equipos.Partitioning the cache involves splitting the cache across multiple computers. Esta estructura le ofrece varias ventajas sobre el uso de un único servidor de caché, incluidos:This structure gives you several advantages over using a single cache server, including:

  • La creación de una caché que es mucho mayor de lo que se puede almacenar en un servidor único.Creating a cache that is much bigger than can be stored on a single server.
  • La distribución de datos entre servidores, mejorando la disponibilidad.Distributing data across servers, improving availability. Si se produce un error en un servidor o deja de estar accesible, los datos que contiene dejan de estar disponibles, pero los datos de los demás servidores siguen estando accesibles.If one server fails or becomes inaccessible, the data that it holds is unavailable, but the data on the remaining servers can still be accessed. En el caso de una caché, esto no es importante porque los datos en caché son solo una copia temporal de los datos contenidos en una base de datos.For a cache, this is not crucial because the cached data is only a transient copy of the data that's held in a database. Los datos en caché en un servidor que deja de estar accesible se pueden almacenar en caché en un servidor diferente.Cached data on a server that becomes inaccessible can be cached on a different server instead.
  • El reparto de la carga entre servidores, lo que mejora el rendimiento y la escalabilidad.Spreading the load across servers, thereby improving performance and scalability.
  • La colocación geográfica de los datos cerca de los usuarios que acceden a ellos, lo que reduce la latencia.Geolocating data close to the users that access it, thus reducing latency.

Para una memoria caché, la forma más común de crear particiones es mediante el particionamiento.For a cache, the most common form of partitioning is sharding. En esta estrategia, cada partición es una caché de Redis por derecho propio.In this strategy, each partition (or shard) is a Redis cache in its own right. Los datos se dirigen a una partición específica mediante el uso de lógica de particionamiento, que puede usar una variedad de enfoques para distribuir los datos.Data is directed to a specific partition by using sharding logic, which can use a variety of approaches to distribute the data. En Sharding Pattern (Patrón de particionamiento) se ofrece más información sobre la implementación del particionamiento.The Sharding pattern provides more information about implementing sharding.

Para implementar la creación de particiones en una caché de Redis, puede adoptar uno de los enfoques siguientes:To implement partitioning in a Redis cache, you can take one of the following approaches:

  • Enrutamiento de consultas del lado servidor.Server-side query routing. En esta técnica, una aplicación cliente envía una solicitud a cualquiera de los servidores de Redis que componen la memoria caché (probablemente, el servidor más cercano).In this technique, a client application sends a request to any of the Redis servers that comprise the cache (probably the closest server). Cada servidor Redis almacena metadatos que describen la partición que contiene y también incluye información acerca de qué claves particiones se encuentran en otros servidores.Each Redis server stores metadata that describes the partition that it holds, and also contains information about which partitions are located on other servers. El servidor Redis examina la solicitud del cliente.The Redis server examines the client request. Si se puede resolver localmente, realiza la operación solicitada.If it can be resolved locally, it will perform the requested operation. De lo contrario, reenvía la solicitud al servidor apropiado.Otherwise it will forward the request on to the appropriate server. Este modelo se implementa mediante la agrupación en clústeres de Redis y se describe con más detalle en la página Tutorial de clúster Redis en el sitio web de Redis.This model is implemented by Redis clustering, and is described in more detail on the Redis cluster tutorial page on the Redis website. La agrupación en clústeres de Redis es transparente para las aplicaciones de cliente y se pueden agregar servidores Redis al clúster (y los datos se pueden volver a dividir en particiones) sin necesidad de volver a configurar los clientes.Redis clustering is transparent to client applications, and additional Redis servers can be added to the cluster (and the data re-partitioned) without requiring that you reconfigure the clients.
  • Creación de particiones del lado cliente.Client-side partitioning. En este modelo, la aplicación cliente contiene lógica (posiblemente en forma de una biblioteca) que enruta solicitudes al servidor de Redis adecuado.In this model, the client application contains logic (possibly in the form of a library) that routes requests to the appropriate Redis server. Este enfoque se puede utilizar con Azure Cache for Redis.This approach can be used with Azure Cache for Redis. Cree varias instancias de Azure Cache for Redis (una para cada partición de datos) e implemente la lógica del lado cliente que enruta las solicitudes a la memoria caché correcta.Create multiple Azure Cache for Redis (one for each data partition) and implement the client-side logic that routes the requests to the correct cache. Si cambia el esquema de creación de particiones (si se crean instancias de Azure Cache for Redis adicionales, por ejemplo), es posible que se deban volver a configurar las aplicaciones cliente.If the partitioning scheme changes (if additional Azure Cache for Redis are created, for example), client applications might need to be reconfigured.
  • Creación de particiones asistida por proxy.Proxy-assisted partitioning. En este esquema, las aplicaciones cliente envían solicitudes a un servicio proxy intermediario que comprende cómo se particionan los datos y luego enruta la solicitud al servidor de Redis adecuado.In this scheme, client applications send requests to an intermediary proxy service which understands how the data is partitioned and then routes the request to the appropriate Redis server. Este enfoque también se puede usar con Azure Cache for Redis; el servicio proxy se podría implementar como un servicio en la nube de Azure.This approach can also be used with Azure Cache for Redis; the proxy service can be implemented as an Azure cloud service. Este enfoque requiere un nivel adicional de complejidad para implementar el servicio y las solicitudes pueden tardar más tiempo en ejecutarse que con el uso de la creación de particiones del lado cliente.This approach requires an additional level of complexity to implement the service, and requests might take longer to perform than using client-side partitioning.

La página Creación de particiones: cómo dividir los datos entre varias instancias de Redis del sitio web de Redis ofrece más información acerca de cómo implementar la creación de particiones con Redis.The page Partitioning: how to split data among multiple Redis instances on the Redis website provides further information about implementing partitioning with Redis.

Implementar las aplicaciones cliente de caché de RedisImplement Redis cache client applications

Redis admite las aplicaciones de cliente escritas en numeroso lenguajes de programación.Redis supports client applications written in numerous programming languages. Si va a crear nuevas aplicaciones con .NET Framework, el enfoque recomendado es usar la biblioteca de cliente de StackExchange.Redis.If you are building new applications by using the .NET Framework, the recommended approach is to use the StackExchange.Redis client library. Esta biblioteca ofrece un modelo de objeto de .NET Framework que abstrae los detalles para conectarse a un servidor de Redis, enviar comandos y recibir respuestas.This library provides a .NET Framework object model that abstracts the details for connecting to a Redis server, sending commands, and receiving responses. Está disponible en Visual Studio como paquete NuGet.It is available in Visual Studio as a NuGet package. Puede usar esta misma biblioteca para conectarse a una instancia de Azure Cache for Redis o a una memoria caché de Redis personalizada hospedada en una máquina virtual.You can use this same library to connect to an Azure Cache for Redis, or a custom Redis cache hosted on a VM.

Para conectarse a un servidor de Redis, use el método estático Connect de la clase ConnectionMultiplexer.To connect to a Redis server you use the static Connect method of the ConnectionMultiplexer class. La conexión que este método crea está diseñada para usarse en todo el período de duración de la aplicación cliente y la misma conexión pueden usarla varios subprocesos simultáneos.The connection that this method creates is designed to be used throughout the lifetime of the client application, and the same connection can be used by multiple concurrent threads. No se vuelva a conectar y desconectar cada vez que realice una operación de Redis porque el rendimiento puede degradarse.Do not reconnect and disconnect each time you perform a Redis operation because this can degrade performance.

Puede especificar los parámetros de conexión, como la dirección del host de Redis y la contraseña.You can specify the connection parameters, such as the address of the Redis host and the password. Si usa Azure Cache for Redis, la contraseña es la clave principal o secundaria generada para Azure Cache for Redis mediante Azure Portal.If you are using Azure Cache for Redis, the password is either the primary or secondary key that is generated for Azure Cache for Redis by using the Azure portal.

Cuando se haya conectado al servidor de Redis, puede obtener un identificador de la base de datos de Redis que actúa como la caché.After you have connected to the Redis server, you can obtain a handle on the Redis database that acts as the cache. La conexión de Redis ofrece el método GetDatabase para lograrlo.The Redis connection provides the GetDatabase method to do this. A continuación, puede recuperar los elementos de la caché y almacenar datos en la memoria caché mediante los métodos StringGet y StringSet.You can then retrieve items from the cache and store data in the cache by using the StringGet and StringSet methods. Estos métodos esperan una clave como parámetro y devuelven el elemento de la caché que tiene un valor coincidente (StringGet) o agregan el elemento a la caché con esta clave (StringSet).These methods expect a key as a parameter, and return the item either in the cache that has a matching value (StringGet) or add the item to the cache with this key (StringSet).

En función de la ubicación del servidor Redis, muchas operaciones pueden sufrir latencia mientras se transmite una solicitud al servidor y se devuelve una respuesta al cliente.Depending on the location of the Redis server, many operations might incur some latency while a request is transmitted to the server and a response is returned to the client. La biblioteca de StackExchange proporciona versiones asincrónicas de muchos de los métodos que expone para ayudar a que las aplicaciones cliente siga respondiendo.The StackExchange library provides asynchronous versions of many of the methods that it exposes to help client applications remain responsive. Estos métodos admiten el patrón asincrónico basado en tareas en .NET Framework.These methods support the Task-based Asynchronous pattern in the .NET Framework.

El fragmento de código siguiente muestra un método llamado RetrieveItem.The following code snippet shows a method named RetrieveItem. Ilustra una implementación del patrón cache-aside basado en Redis y en la biblioteca StackExchange.It illustrates an implementation of the cache-aside pattern based on Redis and the StackExchange library. El método toma un valor de clave de cadena e intenta recuperar el elemento correspondiente de la caché en Redis mediante la llamada al método StringGetAsync (la versión asincrónica de StringGet).The method takes a string key value and attempts to retrieve the corresponding item from the Redis cache by calling the StringGetAsync method (the asynchronous version of StringGet).

Si no se encuentra el elemento, se captura desde el origen de datos subyacente mediante el método GetItemFromDataSourceAsync (que es un método local y no forma parte de la biblioteca StackExchange).If the item is not found, it is fetched from the underlying data source using the GetItemFromDataSourceAsync method (which is a local method and not part of the StackExchange library). Luego, se agrega a la caché mediante el método StringSetAsync para que se pueda recuperar más rápidamente la próxima vez.It's then added to the cache by using the StringSetAsync method so it can be retrieved more quickly next time.

// Connect to the Azure Redis cache
ConfigurationOptions config = new ConfigurationOptions();
config.EndPoints.Add("<your DNS name>.redis.cache.windows.net");
config.Password = "<Redis cache key from management portal>";
ConnectionMultiplexer redisHostConnection = ConnectionMultiplexer.Connect(config);
IDatabase cache = redisHostConnection.GetDatabase();
...
private async Task<string> RetrieveItem(string itemKey)
{
    // Attempt to retrieve the item from the Redis cache
    string itemValue = await cache.StringGetAsync(itemKey);

    // If the value returned is null, the item was not found in the cache
    // So retrieve the item from the data source and add it to the cache
    if (itemValue == null)
    {
        itemValue = await GetItemFromDataSourceAsync(itemKey);
        await cache.StringSetAsync(itemKey, itemValue);
    }

    // Return the item
    return itemValue;
}

Los métodos StringGet y StringSet no se limitan a la recuperación o el almacenamiento de valores de cadena.The StringGet and StringSet methods are not restricted to retrieving or storing string values. Pueden tomar cualquier elemento que se serializa como una matriz de bytes.They can take any item that is serialized as an array of bytes. Si necesita guardar un objeto .NET, puede serializarlo como una secuencia de bytes y usar el método StringSet para escribirlo en la caché.If you need to save a .NET object, you can serialize it as a byte stream and use the StringSet method to write it to the cache.

Del mismo modo, puede leer un objeto de la caché mediante el método StringGet y deserializarlo como un objeto. NET.Similarly, you can read an object from the cache by using the StringGet method and deserializing it as a .NET object. El código siguiente muestra un conjunto de métodos de extensión para la interfaz de IDatabase (el método GetDatabase de una conexión de Redis devuelve un objeto IDatabase) y parte del código de ejemplo que usa estos métodos para leer y escribir un objeto BlogPost en la caché:The following code shows a set of extension methods for the IDatabase interface (the GetDatabase method of a Redis connection returns an IDatabase object), and some sample code that uses these methods to read and write a BlogPost object to the cache:

public static class RedisCacheExtensions
{
    public static async Task<T> GetAsync<T>(this IDatabase cache, string key)
    {
        return Deserialize<T>(await cache.StringGetAsync(key));
    }

    public static async Task<object> GetAsync(this IDatabase cache, string key)
    {
        return Deserialize<object>(await cache.StringGetAsync(key));
    }

    public static async Task SetAsync(this IDatabase cache, string key, object value)
    {
        await cache.StringSetAsync(key, Serialize(value));
    }

    static byte[] Serialize(object o)
    {
        byte[] objectDataAsStream = null;

        if (o != null)
        {
            BinaryFormatter binaryFormatter = new BinaryFormatter();
            using (MemoryStream memoryStream = new MemoryStream())
            {
                binaryFormatter.Serialize(memoryStream, o);
                objectDataAsStream = memoryStream.ToArray();
            }
        }

        return objectDataAsStream;
    }

    static T Deserialize<T>(byte[] stream)
    {
        T result = default(T);

        if (stream != null)
        {
            BinaryFormatter binaryFormatter = new BinaryFormatter();
            using (MemoryStream memoryStream = new MemoryStream(stream))
            {
                result = (T)binaryFormatter.Deserialize(memoryStream);
            }
        }

        return result;
    }
}

El código siguiente muestra un método denominado RetrieveBlogPost que usa estos métodos de extensión para leer y escribir un objeto BlogPost serializable en la memoria caché que sigue al patrón cache-aside:The following code illustrates a method named RetrieveBlogPost that uses these extension methods to read and write a serializable BlogPost object to the cache following the cache-aside pattern:

// The BlogPost type
[Serializable]
public class BlogPost
{
    private HashSet<string> tags;

    public BlogPost(int id, string title, int score, IEnumerable<string> tags)
    {
        this.Id = id;
        this.Title = title;
        this.Score = score;
        this.tags = new HashSet<string>(tags);
    }

    public int Id { get; set; }
    public string Title { get; set; }
    public int Score { get; set; }
    public ICollection<string> Tags => this.tags;
}
...
private async Task<BlogPost> RetrieveBlogPost(string blogPostKey)
{
    BlogPost blogPost = await cache.GetAsync<BlogPost>(blogPostKey);
    if (blogPost == null)
    {
        blogPost = await GetBlogPostFromDataSourceAsync(blogPostKey);
        await cache.SetAsync(blogPostKey, blogPost);
    }

    return blogPost;
}

Redis admite la canalización de comandos si una aplicación cliente envía varias solicitudes asincrónicas.Redis supports command pipelining if a client application sends multiple asynchronous requests. Redis puede multiplexar las solicitudes con la misma conexión, en lugar de recibir y responder a comandos en una secuencia estricta.Redis can multiplex the requests using the same connection rather than receiving and responding to commands in a strict sequence.

Este enfoque ayuda a reducir la latencia haciendo un uso más eficaz de la red.This approach helps to reduce latency by making more efficient use of the network. El siguiente fragmento de código muestra un ejemplo que recupera los detalles de los dos clientes simultáneamente.The following code snippet shows an example that retrieves the details of two customers concurrently. El código envía dos solicitudes y después realiza algún otro procesamiento (no mostrado) antes de esperar para recibir los resultados.The code submits two requests and then performs some other processing (not shown) before waiting to receive the results. El método Wait del objeto de caché es similar al método Task.Wait de .NET Framework:The Wait method of the cache object is similar to the .NET Framework Task.Wait method:

ConnectionMultiplexer redisHostConnection = ...;
IDatabase cache = redisHostConnection.GetDatabase();
...
var task1 = cache.StringGetAsync("customer:1");
var task2 = cache.StringGetAsync("customer:2");
...
var customer1 = cache.Wait(task1);
var customer2 = cache.Wait(task2);

Para más información sobre cómo escribir aplicaciones cliente que puedan usar Azure Cache for Redis, consulte la documentación de Azure Cache for Redis.For additional information on writing client applications that can the Azure Cache for Redis, see the Azure Cache for Redis documentation. Hay más información disponible en StackExchange.Redis.More information is also available at StackExchange.Redis.

La página Pipelines and multiplexers (Canalizaciones y multiplexores) en el mismo sitio web, proporciona más información sobre las operaciones asincrónicas y la canalización con Redis y la biblioteca StackExchange.The page Pipelines and multiplexers on the same website provides more information about asynchronous operations and pipelining with Redis and the StackExchange library.

Uso del almacenamiento en caché en RedisUsing Redis caching

El uso más simple de Redis para los problemas de almacenamiento en caché son los pares clave-valor donde el valor es una cadena sin interpretar de longitud arbitraria que puede contener cualquier dato binario.The simplest use of Redis for caching concerns is key-value pairs where the value is an uninterpreted string of arbitrary length that can contain any binary data. (Es básicamente una matriz de bytes que se puede tratar como una cadena).(It is essentially an array of bytes that can be treated as a string). Este escenario se ilustró en la sección Implementar las aplicaciones cliente de caché en Redis anteriormente en este artículo.This scenario was illustrated in the section Implement Redis Cache client applications earlier in this article.

Tenga en cuenta que las claves también contienen datos no interpretados, así que puede usar cualquier información binaria como clave.Note that keys also contain uninterpreted data, so you can use any binary information as the key. No obstante, cuanto más larga es la clave, más espacio de almacenamiento ocupa y más se tardan en realizar operaciones de búsqueda.The longer the key is, however, the more space it will take to store, and the longer it will take to perform lookup operations. Para un mantenimiento fácil y un uso sencillo, diseñe cuidadosamente su espacio de claves y use claves significativas (pero no detalladas).For usability and ease of maintenance, design your keyspace carefully and use meaningful (but not verbose) keys.

Por ejemplo, use claves estructuradas como "cliente: 100" para representar la clave para el cliente con id. 100 en lugar de simplemente "100".For example, use structured keys such as "customer:100" to represent the key for the customer with ID 100 rather than simply "100". Este esquema le habilita para distinguir con facilidad entre valores que almacenan tipos de datos diferentes.This scheme enables you to easily distinguish between values that store different data types. Por ejemplo, también puede usar la clave "orders:100" para representar la clave para el pedido con el id. 100.For example, you could also use the key "orders:100" to represent the key for the order with ID 100.

Además de cadenas binarias unidimensionales, un valor en un par clave-valor de Redis también puede contener información más estructurada, incluidas listas, conjuntos (ordenados y sin clasificar) y algoritmos hash.Apart from one-dimensional binary strings, a value in a Redis key-value pair can also hold more structured information, including lists, sets (sorted and unsorted), and hashes. Redis ofrece un conjunto de comandos completo que puede manipular estos tipos y muchos de estos comandos están disponibles para las aplicaciones de .NET Framework a través de una biblioteca de cliente como StackExchange.Redis provides a comprehensive command set that can manipulate these types, and many of these commands are available to .NET Framework applications through a client library such as StackExchange. La página Introducción a las abstracciones y a los tipos de datos de Redis y del sitio web de Redis ofrece una visión general más detallada de estos tipos y de los comandos que puede usar para manipularlos.The page An introduction to Redis data types and abstractions on the Redis website provides a more detailed overview of these types and the commands that you can use to manipulate them.

En esta sección se resumen algunos casos de uso comunes de estos tipos de datos y comandos.This section summarizes some common use cases for these data types and commands.

Realizar operaciones atómicas y por lotesPerform atomic and batch operations

Redis admite una serie de operaciones atómicas de get y set en valores de cadena.Redis supports a series of atomic get-and-set operations on string values. Estas operaciones eliminan los posibles peligros de carrera que pueden producirse al usar los comandos GET y SET independientes.These operations remove the possible race hazards that might occur when using separate GET and SET commands. Las operaciones disponibles incluyen:The operations that are available include:

  • INCR, INCRBY, DECR y DECRBY que realizan operaciones atómicas de incremento y decremento en valores de datos numéricos enteros.INCR, INCRBY, DECR, and DECRBY, which perform atomic increment and decrement operations on integer numeric data values. La biblioteca StackExchange ofrece versiones sobrecargadas de los métodos IDatabase.StringIncrementAsync y IDatabase.StringDecrementAsync para realizar estas operaciones y devuelven el valor resultante almacenado en la caché.The StackExchange library provides overloaded versions of the IDatabase.StringIncrementAsync and IDatabase.StringDecrementAsync methods to perform these operations and return the resulting value that is stored in the cache. El siguiente fragmento de código muestra cómo usar estos métodos:The following code snippet illustrates how to use these methods:

    ConnectionMultiplexer redisHostConnection = ...;
    IDatabase cache = redisHostConnection.GetDatabase();
    ...
    await cache.StringSetAsync("data:counter", 99);
    ...
    long oldValue = await cache.StringIncrementAsync("data:counter");
    // Increment by 1 (the default)
    // oldValue should be 100
    
    long newValue = await cache.StringDecrementAsync("data:counter", 50);
    // Decrement by 50
    // newValue should be 50
    
  • GETSET, que recupera el valor asociado a una clave y lo cambia por un nuevo valor.GETSET, which retrieves the value that's associated with a key and changes it to a new value. La biblioteca de StackExchange hace que esta operación esté disponible a través del método IDatabase.StringGetSetAsync.The StackExchange library makes this operation available through the IDatabase.StringGetSetAsync method. El siguiente fragmento de código muestra un ejemplo de este método.The code snippet below shows an example of this method. Este código devuelve el valor actual que está asociado con la clave "data: counter" del ejemplo anterior.This code returns the current value that's associated with the key "data:counter" from the previous example. Luego, se restablece el valor de esta clave en cero, como parte de la misma operación:Then it resets the value for this key back to zero, all as part of the same operation:

    ConnectionMultiplexer redisHostConnection = ...;
    IDatabase cache = redisHostConnection.GetDatabase();
    ...
    string oldValue = await cache.StringGetSetAsync("data:counter", 0);
    
  • MGET y MSET, que pueden devolver o cambiar un conjunto de valores de cadena como una sola operación.MGET and MSET, which can return or change a set of string values as a single operation. Los métodos IDatabase.StringGetAsync y IDatabase.StringSetAsync están sobrecargados para admitir esta funcionalidad, como se muestra en el ejemplo siguiente:The IDatabase.StringGetAsync and IDatabase.StringSetAsync methods are overloaded to support this functionality, as shown in the following example:

    ConnectionMultiplexer redisHostConnection = ...;
    IDatabase cache = redisHostConnection.GetDatabase();
    ...
    // Create a list of key-value pairs
    var keysAndValues =
        new List<KeyValuePair<RedisKey, RedisValue>>()
        {
            new KeyValuePair<RedisKey, RedisValue>("data:key1", "value1"),
            new KeyValuePair<RedisKey, RedisValue>("data:key99", "value2"),
            new KeyValuePair<RedisKey, RedisValue>("data:key322", "value3")
        };
    
    // Store the list of key-value pairs in the cache
    cache.StringSet(keysAndValues.ToArray());
    ...
    // Find all values that match a list of keys
    RedisKey[] keys = { "data:key1", "data:key99", "data:key322"};
    // values should contain { "value1", "value2", "value3" }
    RedisValue[] values = cache.StringGet(keys);
    
    

También puede combinar varias operaciones en una sola transacción de Redis, como se ha descrito en la sección Lotes y transacciones de Redis anteriormente en este artículo.You can also combine multiple operations into a single Redis transaction as described in the Redis transactions and batches section earlier in this article. La biblioteca de StackExchange ofrece compatibilidad para las transacciones a través de la interfaz de ITransaction.The StackExchange library provides support for transactions through the ITransaction interface.

Se crea un objeto ITransaction con el método IDatabase.CreateTransaction.You create an ITransaction object by using the IDatabase.CreateTransaction method. Se invocan comandos para la transacción mediante los métodos proporcionados por el objeto ITransaction .You invoke commands to the transaction by using the methods provided by the ITransaction object.

La interfaz ITransaction proporciona acceso a un conjunto de métodos que son similares a aquellos a los que se accede con la interfaz IDatabase, con la excepción de que todos los métodos son asincrónicos.The ITransaction interface provides access to a set of methods that's similar to those accessed by the IDatabase interface, except that all the methods are asynchronous. Esto significa que solo se llevan a cabo cuando se invoca el método ITransaction.Execute .This means that they are only performed when the ITransaction.Execute method is invoked. El valor devuelto por el método ITransaction.Execute indica si la transacción se creó correctamente (true) o no (false).The value that's returned by the ITransaction.Execute method indicates whether the transaction was created successfully (true) or if it failed (false).

En el siguiente fragmento de código se muestra un ejemplo que incrementa y disminuye dos contadores como parte de la misma transacción:The following code snippet shows an example that increments and decrements two counters as part of the same transaction:

ConnectionMultiplexer redisHostConnection = ...;
IDatabase cache = redisHostConnection.GetDatabase();
...
ITransaction transaction = cache.CreateTransaction();
var tx1 = transaction.StringIncrementAsync("data:counter1");
var tx2 = transaction.StringDecrementAsync("data:counter2");
bool result = transaction.Execute();
Console.WriteLine("Transaction {0}", result ? "succeeded" : "failed");
Console.WriteLine("Result of increment: {0}", tx1.Result);
Console.WriteLine("Result of decrement: {0}", tx2.Result);

Recuerde que las transacciones de Redis son transacciones diferentes en bases de datos relacionales.Remember that Redis transactions are unlike transactions in relational databases. El método Execute simplemente pone en cola todos los comandos que componen la transacción que se va a ejecutar y, si alguno de ellos está mal formado, se detiene la transacción.The Execute method simply queues all the commands that comprise the transaction to be run, and if any of them is malformed then the transaction is stopped. Si todos los comandos se han puesto en cola correctamente, cada comando se ejecuta de forma asincrónica.If all the commands have been queued successfully, each command runs asynchronously.

Si algún comando genera un error, los demás continúan procesándose.If any command fails, the others still continue processing. Si necesita comprobar que un comando ha finalizado correctamente, debe capturar los resultados del comando mediante la propiedad Result de la tarea correspondiente, como se muestra en el ejemplo anterior.If you need to verify that a command has completed successfully, you must fetch the results of the command by using the Result property of the corresponding task, as shown in the example above. La lectura de la propiedad Result se bloqueará hasta que se complete la tarea.Reading the Result property will block the calling thread until the task has completed.

Para más información, consulte Transactions in Redis (Transacciones en Redis).For more information, see Transactions in Redis.

Al realizar operaciones por lotes, puede usar la interfaz IBatch de la biblioteca StackExchange.When performing batch operations, you can use the IBatch interface of the StackExchange library. Esta interfaz proporciona acceso a un conjunto de métodos que son similares a aquellos a los que se accede con la interfaz IDatabase , con la excepción de que todos los métodos son asincrónicos.This interface provides access to a set of methods similar to those accessed by the IDatabase interface, except that all the methods are asynchronous.

Crea un objeto IBatch mediante el método IDatabase.CreateBatch y luego ejecuta el lote con el método IBatch.Execute, como se muestra en el ejemplo siguiente.You create an IBatch object by using the IDatabase.CreateBatch method, and then run the batch by using the IBatch.Execute method, as shown in the following example. Este código simplemente establece un valor de cadena, aumenta y disminuye los mismos contadores usados en el ejemplo anterior y muestra los resultados:This code simply sets a string value, increments and decrements the same counters used in the previous example, and displays the results:

ConnectionMultiplexer redisHostConnection = ...;
IDatabase cache = redisHostConnection.GetDatabase();
...
IBatch batch = cache.CreateBatch();
batch.StringSetAsync("data:key1", 11);
var t1 = batch.StringIncrementAsync("data:counter1");
var t2 = batch.StringDecrementAsync("data:counter2");
batch.Execute();
Console.WriteLine("{0}", t1.Result);
Console.WriteLine("{0}", t2.Result);

Es importante comprender que, a diferencia de una transacción, si se produce un error en un comando en un lote porque el formato es incorrecto, los demás comandos podrían seguir funcionando.It is important to understand that unlike a transaction, if a command in a batch fails because it is malformed, the other commands might still run. El método IBatch.Execute no devuelve ninguna indicación de éxito o error.The IBatch.Execute method does not return any indication of success or failure.

Realizar operaciones de caché "Fire and Forget" (dispare y olvídese)Perform fire and forget cache operations

Redis admite operaciones "Fire and Forget" (dispare y olvídese) mediante marcadores de comando.Redis supports fire and forget operations by using command flags. En esta situación, el cliente simplemente inicia una operación, pero no tiene interés en el resultado y no espera a que se complete el comando.In this situation, the client simply initiates an operation but has no interest in the result and does not wait for the command to be completed. En el ejemplo siguiente se muestra cómo realizar el comando INCR como una operación "Fire and Forget":The example below shows how to perform the INCR command as a fire and forget operation:

ConnectionMultiplexer redisHostConnection = ...;
IDatabase cache = redisHostConnection.GetDatabase();
...
await cache.StringSetAsync("data:key1", 99);
...
cache.StringIncrement("data:key1", flags: CommandFlags.FireAndForget);

Especificar las claves de expiración automáticamenteSpecify automatically expiring keys

Al almacenar un elemento en una caché de Redis, puede especificar un tiempo de espera tras el cual el elemento se quitará automáticamente de la memoria caché.When you store an item in a Redis cache, you can specify a timeout after which the item will be automatically removed from the cache. También puede consultar de cuánto tiempo dispone una clave antes de expirar mediante el comando TTL .You can also query how much more time a key has before it expires by using the TTL command. Este comando está disponible para aplicaciones de StackExchange mediante el método IDatabase.KeyTimeToLive .This command is available to StackExchange applications by using the IDatabase.KeyTimeToLive method.

El siguiente fragmento de código muestra cómo establecer un tiempo de expiración de 20 segundos en una clave y consultar la duración restante de la clave:The following code snippet shows how to set an expiration time of 20 seconds on a key, and query the remaining lifetime of the key:

ConnectionMultiplexer redisHostConnection = ...;
IDatabase cache = redisHostConnection.GetDatabase();
...
// Add a key with an expiration time of 20 seconds
await cache.StringSetAsync("data:key1", 99, TimeSpan.FromSeconds(20));
...
// Query how much time a key has left to live
// If the key has already expired, the KeyTimeToLive function returns a null
TimeSpan? expiry = cache.KeyTimeToLive("data:key1");

También puede establecer el tiempo de expiración en una fecha y hora específicas mediante el comando EXPIRE, disponible en la biblioteca StackExchange como el método KeyExpireAsync :You can also set the expiration time to a specific date and time by using the EXPIRE command, which is available in the StackExchange library as the KeyExpireAsync method:

ConnectionMultiplexer redisHostConnection = ...;
IDatabase cache = redisHostConnection.GetDatabase();
...
// Add a key with an expiration date of midnight on 1st January 2015
await cache.StringSetAsync("data:key1", 99);
await cache.KeyExpireAsync("data:key1",
    new DateTime(2015, 1, 1, 0, 0, 0, DateTimeKind.Utc));
...

Sugerencia

Puede quitar manualmente un elemento de la caché con el comando DEL, que está disponible en la biblioteca StackExchange como el método IDatabase.KeyDeleteAsync.You can manually remove an item from the cache by using the DEL command, which is available through the StackExchange library as the IDatabase.KeyDeleteAsync method.

Usar etiquetas para correlacionar elementos en cachéUse tags to cross-correlate cached items

Un conjunto de Redis es una colección de varios elementos que comparten una sola clave.A Redis set is a collection of multiple items that share a single key. Puede crear un conjunto con el comando SADD.You can create a set by using the SADD command. Puede recuperar los elementos de un conjunto mediante el comando SMEMBERS.You can retrieve the items in a set by using the SMEMBERS command. La biblioteca StackExchange implementa el comando SADD con el método IDatabase.SetAddAsync y los comandos SMEMBERS con el método IDatabase.SetMembersAsync.The StackExchange library implements the SADD command with the IDatabase.SetAddAsync method, and the SMEMBERS command with the IDatabase.SetMembersAsync method.

También puede combinar los conjuntos existentes para crear nuevos conjuntos con los comandos SDIFF (diferencia de conjuntos), SINTER (intersección de conjuntos) y SUNION (unión de conjuntos).You can also combine existing sets to create new sets by using the SDIFF (set difference), SINTER (set intersection), and SUNION (set union) commands. La biblioteca StackExchange unifica estas operaciones en el método IDatabase.SetCombineAsync .The StackExchange library unifies these operations in the IDatabase.SetCombineAsync method. El primer parámetro a este método especifica la operación de conjunto que se realizará.The first parameter to this method specifies the set operation to perform.

Los fragmentos de código siguientes muestran de qué manera los conjuntos pueden ser útiles para almacenar y recuperar rápidamente las colecciones de elementos relacionados.The following code snippets show how sets can be useful for quickly storing and retrieving collections of related items. Este código utiliza el tipo BlogPost que se ha descrito en la sección Implementar las aplicaciones cliente de caché en Redis anteriormente en este artículo.This code uses the BlogPost type that was described in the section Implement Redis Cache Client Applications earlier in this article.

Un objeto BlogPost contiene cuatro campos: un identificador, un título, una puntuación de clasificación y una colección de etiquetas.A BlogPost object contains four fields—an ID, a title, a ranking score, and a collection of tags. El primer fragmento de código, a continuación, muestra los datos de ejemplo que se usan para rellenar una lista C# de objetos BlogPost :The first code snippet below shows the sample data that's used for populating a C# list of BlogPost objects:

List<string[]> tags = new List<string[]>
{
    new[] { "iot","csharp" },
    new[] { "iot","azure","csharp" },
    new[] { "csharp","git","big data" },
    new[] { "iot","git","database" },
    new[] { "database","git" },
    new[] { "csharp","database" },
    new[] { "iot" },
    new[] { "iot","database","git" },
    new[] { "azure","database","big data","git","csharp" },
    new[] { "azure" }
};

List<BlogPost> posts = new List<BlogPost>();
int blogKey = 1;
int numberOfPosts = 20;
Random random = new Random();
for (int i = 0; i < numberOfPosts; i++)
{
    blogKey++;
    posts.Add(new BlogPost(
        blogKey,                  // Blog post ID
        string.Format(CultureInfo.InvariantCulture, "Blog Post #{0}",
            blogKey),             // Blog post title
        random.Next(100, 10000),  // Ranking score
        tags[i % tags.Count]));   // Tags--assigned from a collection
                                  // in the tags list
}

Puede almacenar las etiquetas para cada objeto BlogPost como un conjunto en una caché en Redis y asociar cada conjunto con el id. de BlogPost.You can store the tags for each BlogPost object as a set in a Redis cache and associate each set with the ID of the BlogPost. Esto permite que una aplicación encuentre rápidamente todas las etiquetas que pertenecen a una entrada de blog específica.This enables an application to quickly find all the tags that belong to a specific blog post. Para habilitar la búsqueda en la dirección opuesta y encontrar todas las entradas que comparten una etiqueta específica, puede crear otro conjunto que contiene la entradas de blog que hacen referencia al id. de etiqueta de la clave:To enable searching in the opposite direction and find all blog posts that share a specific tag, you can create another set that holds the blog posts referencing the tag ID in the key:

ConnectionMultiplexer redisHostConnection = ...;
IDatabase cache = redisHostConnection.GetDatabase();
...
// Tags are easily represented as Redis Sets
foreach (BlogPost post in posts)
{
    string redisKey = string.Format(CultureInfo.InvariantCulture,
        "blog:posts:{0}:tags", post.Id);
    // Add tags to the blog post in Redis
    await cache.SetAddAsync(
        redisKey, post.Tags.Select(s => (RedisValue)s).ToArray());

    // Now do the inverse so we can figure out which blog posts have a given tag
    foreach (var tag in post.Tags)
    {
        await cache.SetAddAsync(string.Format(CultureInfo.InvariantCulture,
            "tag:{0}:blog:posts", tag), post.Id);
    }
}

Estas estructuras le permiten realizar muchas consultas comunes de manera muy eficaz.These structures enable you to perform many common queries very efficiently. Por ejemplo, puede buscar y mostrar todas las etiquetas para la entrada de blog 1 de la siguiente manera:For example, you can find and display all of the tags for blog post 1 like this:

// Show the tags for blog post #1
foreach (var value in await cache.SetMembersAsync("blog:posts:1:tags"))
{
    Console.WriteLine(value);
}

Puede encontrar todas las etiquetas que son comunes a la entrada de blog 1 y a la entrada de blog 2 realizando una operación de intersección de conjuntos, de la siguiente manera:You can find all tags that are common to blog post 1 and blog post 2 by performing a set intersection operation, as follows:

// Show the tags in common for blog posts #1 and #2
foreach (var value in await cache.SetCombineAsync(SetOperation.Intersect, new RedisKey[]
    { "blog:posts:1:tags", "blog:posts:2:tags" }))
{
    Console.WriteLine(value);
}

Además, puede encontrar todas las entradas de blog que contienen una etiqueta específica:And you can find all blog posts that contain a specific tag:

// Show the ids of the blog posts that have the tag "iot".
foreach (var value in await cache.SetMembersAsync("tag:iot:blog:posts"))
{
    Console.WriteLine(value);
}

Encontrar los elementos de acceso más recienteFind recently accessed items

Una tarea común requerida por muchas aplicaciones es encontrar los elementos a los que se ha accedido recientemente.A common task required of many applications is to find the most recently accessed items. Por ejemplo, puede que un sitio de blog desee mostrar información acerca de las entradas de blog leídas más recientemente.For example, a blogging site might want to display information about the most recently read blog posts.

Puede implementar esta funcionalidad mediante una lista de Redis.You can implement this functionality by using a Redis list. Una lista de Redis contiene varios elementos que comparten la misma clave.A Redis list contains multiple items that share the same key. La lista actúa como una cola de dos extremos.The list acts as a double-ended queue. Puede insertar elementos en cualquier extremo de la lista mediante los comandos LPUSH (inserción izquierda) y RPUSH (inserción derecha).You can push items to either end of the list by using the LPUSH (left push) and RPUSH (right push) commands. Puede recuperar elementos de cualquier extremo de la lista con los comandos LPOP y RPOP.You can retrieve items from either end of the list by using the LPOP and RPOP commands. También puede devolver un conjunto de elementos mediante los comandos LRANGE y RRANGE.You can also return a set of elements by using the LRANGE and RRANGE commands.

Los fragmentos de código siguientes muestran cómo realizar estas operaciones mediante la biblioteca de StackExchange.The code snippets below show how you can perform these operations by using the StackExchange library. Este código usa el tipo BlogPost de los ejemplos anteriores.This code uses the BlogPost type from the previous examples. A medida que un usuario lee una entrada de blog, el método IDatabase.ListLeftPushAsync inserta el título en una lista que está asociado con la clave "blog: recent_posts" en la caché de Redis.As a blog post is read by a user, the IDatabase.ListLeftPushAsync method pushes the title of the blog post onto a list that's associated with the key "blog:recent_posts" in the Redis cache.

ConnectionMultiplexer redisHostConnection = ...;
IDatabase cache = redisHostConnection.GetDatabase();
...
string redisKey = "blog:recent_posts";
BlogPost blogPost = ...; // Reference to the blog post that has just been read
await cache.ListLeftPushAsync(
    redisKey, blogPost.Title); // Push the blog post onto the list

Conforme se leen más entradas del blog, sus títulos se insertan en la misma lista.As more blog posts are read, their titles are pushed onto the same list. La lista está ordenada por la secuencia en la que se han agregado los títulos.The list is ordered by the sequence in which the titles have been added. Las entradas de blog leídas más recientemente están hacia el extremo izquierdo de la lista.The most recently read blog posts are toward the left end of the list. (Si la misma entrada de blog se lee más de una vez, tendrá varias entradas en la lista).(If the same blog post is read more than once, it will have multiple entries in the list.)

Puede mostrar los títulos de las entradas leídas más recientemente mediante el método IDatabase.ListRange .You can display the titles of the most recently read posts by using the IDatabase.ListRange method. Este método toma la clave que contiene la lista, un punto de partida y un punto final.This method takes the key that contains the list, a starting point, and an ending point. El código siguiente recupera los títulos de las 10 entradas de blog (elementos del 0 al 9) en el extremo que se encuentra más a la izquierda de la lista:The following code retrieves the titles of the 10 blog posts (items from 0 to 9) at the left-most end of the list:

// Show latest ten posts
foreach (string postTitle in await cache.ListRangeAsync(redisKey, 0, 9))
{
    Console.WriteLine(postTitle);
}

Tenga en cuenta que el método ListRangeAsync no quita elementos de la lista.Note that the ListRangeAsync method does not remove items from the list. Para ello, puede usar los métodos IDatabase.ListLeftPopAsync y IDatabase.ListRightPopAsync.To do this, you can use the IDatabase.ListLeftPopAsync and IDatabase.ListRightPopAsync methods.

Para evitar que la lista crezca de manera indefinida, puede seleccionar elementos periódicamente recortando la lista.To prevent the list from growing indefinitely, you can periodically cull items by trimming the list. El siguiente fragmento de código muestra cómo quitar todos los elementos de la lista, excepto los cinco del extremo izquierdo.The code snippet below shows you how to remove all but the five left-most items from the list:

await cache.ListTrimAsync(redisKey, 0, 5);

Implementar un panel de rellenoImplement a leader board

De forma predeterminada, los elementos de un conjunto no se mantienen en ningún orden específico.By default, the items in a set are not held in any specific order. Puede crear un conjunto ordenado mediante el comando ZADD (el método IDatabase.SortedSetAdd de la biblioteca StackExchange).You can create an ordered set by using the ZADD command (the IDatabase.SortedSetAdd method in the StackExchange library). Los elementos se ordenan mediante un valor numérico denominado puntuación, que se proporciona como parámetro para el comando.The items are ordered by using a numeric value called a score, which is provided as a parameter to the command.

El siguiente fragmento de código agrega el título de una entrada de blog a una lista ordenada.The following code snippet adds the title of a blog post to an ordered list. En el ejemplo, cada entrada de blog también tiene un campo de puntuación que contiene la clasificación de la entrada de blog.In this example, each blog post also has a score field that contains the ranking of the blog post.

ConnectionMultiplexer redisHostConnection = ...;
IDatabase cache = redisHostConnection.GetDatabase();
...
string redisKey = "blog:post_rankings";
BlogPost blogPost = ...; // Reference to a blog post that has just been rated
await cache.SortedSetAddAsync(redisKey, blogPost.Title, blogPost.Score);

Puede recuperar los títulos de la entrada de blog y las puntuaciones en orden de puntuación ascendente mediante el método IDatabase.SortedSetRangeByRankWithScores:You can retrieve the blog post titles and scores in ascending score order by using the IDatabase.SortedSetRangeByRankWithScores method:

foreach (var post in await cache.SortedSetRangeByRankWithScoresAsync(redisKey))
{
    Console.WriteLine(post);
}

Nota

La biblioteca StackExchange también ofrece el método IDatabase.SortedSetRangeByRankAsync, que devuelve los datos en orden de puntuación, pero no devuelve las puntuaciones.The StackExchange library also provides the IDatabase.SortedSetRangeByRankAsync method, which returns the data in score order, but does not return the scores.

También puede recuperar los elementos en orden descendente de puntuación y limitar el número de elementos devueltos proporcionando parámetros adicionales para el método IDatabase.SortedSetRangeByRankWithScoresAsync.You can also retrieve items in descending order of scores, and limit the number of items that are returned by providing additional parameters to the IDatabase.SortedSetRangeByRankWithScoresAsync method. En el ejemplo siguiente se muestran los títulos y las puntuaciones de las 10 entradas de blog clasificadas en primer lugar:The next example displays the titles and scores of the top 10 ranked blog posts:

foreach (var post in await cache.SortedSetRangeByRankWithScoresAsync(
                               redisKey, 0, 9, Order.Descending))
{
    Console.WriteLine(post);
}

En el ejemplo siguiente se utiliza el método IDatabase.SortedSetRangeByScoreWithScoresAsync , que puede emplear para limitar los elementos que se devuelven a aquellos que se encuentren dentro de un determinado intervalo de puntuación:The next example uses the IDatabase.SortedSetRangeByScoreWithScoresAsync method, which you can use to limit the items that are returned to those that fall within a given score range:

// Blog posts with scores between 5000 and 100000
foreach (var post in await cache.SortedSetRangeByScoreWithScoresAsync(
                               redisKey, 5000, 100000))
{
    Console.WriteLine(post);
}

Mensaje mediante canalesMessage by using channels

Además de actuar como una caché de datos, un servidor de Redis proporciona mensajería a través de un mecanismo de publicador y suscriptor de alto rendimiento.Apart from acting as a data cache, a Redis server provides messaging through a high-performance publisher/subscriber mechanism. Las aplicaciones cliente pueden suscribirse a un canal y otros servicios o aplicaciones pueden publicar mensajes en el canal.Client applications can subscribe to a channel, and other applications or services can publish messages to the channel. Las aplicaciones de suscripción recibirán entonces estos mensajes y podrán procesarlos.Subscribing applications will then receive these messages and can process them.

Redis proporciona el comando SUBSCRIBE para las aplicaciones cliente para suscribirse a los canales.Redis provides the SUBSCRIBE command for client applications to use to subscribe to channels. Este comando espera el nombre de uno o más canales en los que la aplicación aceptará mensajes.This command expects the name of one or more channels on which the application will accept messages. La biblioteca StackExchange incluye la interfaz ISubscription, que permite a una aplicación de .NET Framework suscribirse a canales y publicar en ellos.The StackExchange library includes the ISubscription interface, which enables a .NET Framework application to subscribe and publish to channels.

Se crea un objeto ISubscription mediante el método GetSubscriber de la conexión al servidor de Redis.You create an ISubscription object by using the GetSubscriber method of the connection to the Redis server. Después se escuchan los mensajes en un canal con el método SubscribeAsync de este objeto.Then you listen for messages on a channel by using the SubscribeAsync method of this object. En el ejemplo de código siguiente se muestra cómo suscribirse a un canal denominado "messages:blogPosts":The following code example shows how to subscribe to a channel named "messages:blogPosts":

ConnectionMultiplexer redisHostConnection = ...;
ISubscriber subscriber = redisHostConnection.GetSubscriber();
...
await subscriber.SubscribeAsync("messages:blogPosts", (channel, message) => Console.WriteLine("Title is: {0}", message));

El primer parámetro para el método Subscribe es el nombre del canal.The first parameter to the Subscribe method is the name of the channel. Este nombre sigue las mismas convenciones que se utilizan en las claves de la caché.This name follows the same conventions that are used by keys in the cache. El nombre puede contener cualquier dato binario, aunque es conveniente usar cadenas relativamente cortas y descriptivas para ayudar a garantizar un rendimiento y un mantenimiento óptimos.The name can contain any binary data, although it is advisable to use relatively short, meaningful strings to help ensure good performance and maintainability.

Tenga en cuenta también que el espacio de nombres utilizado por los canales es independiente del que utilizan las claves.Note also that the namespace used by channels is separate from that used by keys. Esto significa que puede tener canales y claves con el mismo nombre, aunque esto puede hacer que el código de aplicación sea más difícil de mantener.This means you can have channels and keys that have the same name, although this may make your application code more difficult to maintain.

El segundo parámetro es un delegado de acción.The second parameter is an Action delegate. Este delegado se ejecuta de forma asincrónica siempre que aparece un mensaje nuevo en el canal.This delegate runs asynchronously whenever a new message appears on the channel. En este ejemplo simplemente se muestra el mensaje en la consola (el mensaje incluirá el título de una entrada de blog).This example simply displays the message on the console (the message will contain the title of a blog post).

Para publicar en un canal, una aplicación puede usar el comando PUBLISH de Redis.To publish to a channel, an application can use the Redis PUBLISH command. La biblioteca StackExchange ofrece el método IServer.PublishAsync para realizar esta operación.The StackExchange library provides the IServer.PublishAsync method to perform this operation. El siguiente fragmento de código muestra cómo publicar un mensaje en el canal "messages:blogPosts":The next code snippet shows how to publish a message to the "messages:blogPosts" channel:

ConnectionMultiplexer redisHostConnection = ...;
ISubscriber subscriber = redisHostConnection.GetSubscriber();
...
BlogPost blogPost = ...;
subscriber.PublishAsync("messages:blogPosts", blogPost.Title);

Hay varios puntos que deben comprender acerca del mecanismo de publicación o suscripción:There are several points you should understand about the publish/subscribe mechanism:

  • Varios suscriptores pueden suscribirse al mismo canal y todos recibirán los mensajes publicados en ese canal.Multiple subscribers can subscribe to the same channel, and they will all receive the messages that are published to that channel.
  • Los suscriptores solo reciben mensajes que se han publicado después de haberse suscrito.Subscribers only receive messages that have been published after they have subscribed. Los canales no se almacenan en búfer y cuando se publica un mensaje, la infraestructura de Redis envía el mensaje a cada suscriptor y luego lo elimina.Channels are not buffered, and once a message is published, the Redis infrastructure pushes the message to each subscriber and then removes it.
  • De forma predeterminada, los suscriptores reciben los mensajes en el orden en que se envían.By default, messages are received by subscribers in the order in which they are sent. En un sistema muy activo, con un gran número de mensajes y muchos suscriptores y publicadores, la entrega secuencial garantizada de mensajes puede ralentizar el rendimiento del sistema.In a highly active system with a large number of messages and many subscribers and publishers, guaranteed sequential delivery of messages can slow performance of the system. Si cada mensaje es independiente y el orden es irrelevante, puede habilitar el procesamiento simultáneo por el sistema de Redis, lo que puede ayudar a mejorar la capacidad de respuesta.If each message is independent and the order is unimportant, you can enable concurrent processing by the Redis system, which can help to improve responsiveness. Puede conseguir esto en un cliente de StackExchange si establece el valor de PreserveAsyncOrder de la conexión usada por el suscriptor en false:You can achieve this in a StackExchange client by setting the PreserveAsyncOrder of the connection used by the subscriber to false:
ConnectionMultiplexer redisHostConnection = ...;
redisHostConnection.PreserveAsyncOrder = false;
ISubscriber subscriber = redisHostConnection.GetSubscriber();

Consideraciones acerca de la serializaciónSerialization considerations

Al elegir un formato de serialización, considere el equilibrio entre rendimiento, interoperabilidad, control de versiones, compatibilidad con los sistemas existentes, compresión de datos y sobrecarga de memoria.When you choose a serialization format, consider tradeoffs between performance, interoperability, versioning, compatibility with existing systems, data compression, and memory overhead. Al evaluar el rendimiento, recuerde que las pruebas comparativas dependen en gran medida del contexto.When you are evaluating performance, remember that benchmarks are highly dependent on context. Podrían no reflejar la carga de trabajo real y podrían no tener en cuenta las bibliotecas o versiones más recientes.They may not reflect your actual workload, and may not consider newer libraries or versions. No hay un solo serializador "más rápido" para todos los escenarios.There is no single "fastest" serializer for all scenarios.

Algunas opciones que debe considerar son:Some options to consider include:

  • Los búferes de protocolo son un formato de serialización desarrollado por Google para serializar datos estructurados de manera eficaz.Protocol Buffers (also called protobuf) is a serialization format developed by Google for serializing structured data efficiently. Usa archivos de definición fuertemente tipados para definir las estructuras de los mensajes.It uses strongly typed definition files to define message structures. Estos archivos de definición se compilan en código específico del lenguaje para serializar y deserializar los mensajes.These definition files are then compiled to language-specific code for serializing and deserializing messages. Los búferes de protocolos pueden usarse con mecanismos RPC existentes, o puede generar un servicio RPC.Protobuf can be used over existing RPC mechanisms, or it can generate an RPC service.

  • Apache Thrift usa un enfoque similar, con archivos de definición fuertemente tipados y un paso de compilación para generar el código de serialización y los servicios RPC.Apache Thrift uses a similar approach, with strongly typed definition files and a compilation step to generate the serialization code and RPC services.

  • Apache Avro proporciona una funcionalidad similar a los búferes de protocolo y Thrift, pero no hay ningún paso de compilación.Apache Avro provides similar functionality to Protocol Buffers and Thrift, but there is no compilation step. En su lugar, los datos serializados siempre incluyen un esquema que describe la estructura.Instead, serialized data always includes a schema that describes the structure.

  • JSON es un estándar abierto que usa campos de texto legibles por humanos.JSON is an open standard that uses human-readable text fields. Tiene una amplia compatibilidad multiplataforma.It has broad cross-platform support. JSON no usa esquemas de mensaje.JSON does not use message schemas. Al ser un formato basado en texto, no resulta muy eficaz para la transmisión.Being a text-based format, it is not very efficient over the wire. Sin embargo, en algunos casos puede devolver elementos almacenados en caché directamente a un cliente mediante HTTP; en este caso, almacenar el código JSON podría ahorrar el costo de deserializar desde otro formato y serializar a JSON.In some cases, however, you may be returning cached items directly to a client via HTTP, in which case storing JSON could save the cost of deserializing from another format and then serializing to JSON.

  • BSON es un formato de serialización binario que usa una estructura similar a JSON.BSON is a binary serialization format that uses a structure similar to JSON. BSON se diseñó para ser ligero, fácil de explorar y rápido para serializar y deserializar, con respecto a JSON.BSON was designed to be lightweight, easy to scan, and fast to serialize and deserialize, relative to JSON. Las cargas son comparables en tamaño a JSON.Payloads are comparable in size to JSON. En función de los datos, una carga BSON puede ser menor o mayor que una carga JSON.Depending on the data, a BSON payload may be smaller or larger than a JSON payload. BSON tiene algunos tipos de datos adicionales que no están disponibles en JSON, especialmente BinData (para las matrices de bytes) y Date.BSON has some additional data types that are not available in JSON, notably BinData (for byte arrays) and Date.

  • MessagePack es un formato de serialización binario que está diseñado para ser compacto para su transmisión.MessagePack is a binary serialization format that is designed to be compact for transmission over the wire. No hay esquemas de mensaje ni comprobación del tipo de mensaje.There are no message schemas or message type checking.

  • Bond es un entorno multiplataforma para trabajar con datos esquematizados.Bond is a cross-platform framework for working with schematized data. Admite la serialización y deserialización entre distintos lenguajes.It supports cross-language serialization and deserialization. Algunas diferencias importantes con respecto a otros sistemas que se indican aquí son la posibilidad de heredar, los alias de tipos y los genéricos.Notable differences from other systems listed here are support for inheritance, type aliases, and generics.

  • gRPC es un sistema RPC de código abierto desarrollado por Google.gRPC is an open-source RPC system developed by Google. De forma predeterminada, utiliza búferes de protocolo como lenguaje de definición y formato de intercambio de mensajes subyacente.By default, it uses Protocol Buffers as its definition language and underlying message interchange format.

Los patrones siguientes también pueden ser pertinentes para su escenario al implementar el almacenamiento en caché en sus aplicaciones:The following patterns might also be relevant to your scenario when you implement caching in your applications:

  • Patrón reservado en caché: este patrón describe cómo cargar datos a petición en una caché desde un almacén de datos.Cache-aside pattern: This pattern describes how to load data on demand into a cache from a data store. Este patrón también ayuda a mantener la coherencia entre los datos almacenados en la caché y los datos del almacén de datos original.This pattern also helps to maintain consistency between data that's held in the cache and the data in the original data store.

  • El patrón de particionamiento ofrece información sobre la implementación de la creación de particiones horizontal para ayudar a mejorar la escalabilidad al almacenar y tener acceso a grandes volúmenes de datos.The Sharding pattern provides information about implementing horizontal partitioning to help improve scalability when storing and accessing large volumes of data.

Más informaciónMore information