3 formas de almacenar en caché listas paginadas, recopilación rápida ~

Resumen: este artículo presenta tres formas de implementar el almacenamiento en caché de listas paginadas.

Este artículo se comparte desde Huawei Cloud Community " Caché de lista de paginación, ¿realmente lo sabe ", autor: Brother Yong java intercambio de combate real.

1 Guarda en caché directamente los resultados de la lista paginada

Obviamente, esta es la forma más fácil y comprensible.

Almacenamos en caché los resultados de paginación de acuerdo con diferentes condiciones de paginación, el pseudocódigo es el siguiente:

public List<Product> getPageList(String param,int page,int size) {
 String key = "productList:page:" + page + ”size:“ + size + 
 "param:" + param ;
 List<Product> dataList = cacheUtils.get(key);
 if(dataList != null) {
 return dataList;
 }
 dataList = queryFromDataBase(param,page,size);
 if(dataList != null) {
 cacheUtils.set(key , dataList , Constants.ExpireTime);
 }
} 

La ventaja de esta solución es que el proyecto es simple y el rendimiento es rápido, pero hay un defecto genético muy obvio: la granularidad de la lista de caché es muy grande .

Si los datos de la lista se agregan o eliminan, para garantizar la coherencia de los datos, es necesario modificar la memoria caché de la lista de paginación.

Hay dos maneras:

1. Confíe en la caducidad de la memoria caché para implementarla de forma perezosa, pero los escenarios comerciales deben ser tolerantes;

2. Use las claves de Redis para encontrar el caché de paginación de la empresa y ejecute el comando de eliminación. Sin embargo, el comando de teclas tiene un gran impacto en el rendimiento y provocará un gran retraso en Redis.

Es peligroso utilizar el comando de teclas en el entorno de producción y la probabilidad de accidentes es alta, por lo que no se recomienda .

2 Consulte la lista de ID de objetos y luego almacene en caché cada entrada de objeto

Aunque el almacenamiento en caché de los resultados de la paginación es fácil de usar, la granularidad del almacenamiento en caché es demasiado grande y es problemático garantizar la coherencia de los datos.

Por lo tanto, nuestro objetivo es un control más detallado del almacenamiento en caché  .

Consultamos la lista de ID de objeto de paginación del producto y luego creamos un caché para cada objeto de producto, agregamos el ID de producto y el caché de objeto de producto en una lista y lo devolvemos al front-end.

El pseudocódigo es el siguiente:

Proceso central:

1. Consulta la lista de ID de página de la base de datos.

// 从数据库中查询分页商品 ID 列表
List<Long> productIdList = queryProductIdListFromDabaBase(
                           param, 
                           page, 
                           size);

El SQL correspondiente es similar a:

SELECT id FROM products
ORDER BY id 
LIMIT (page - 1) * size , size 

2. Obtenga objetos básicos del caché en lotes

Map<Long, Product> cachedProductMap = cacheUtils.mget(productIdList);

Si usamos un caché local, también es extremadamente rápido agregar directamente desde el caché local uno por uno.

Si usamos caché distribuida, Redis naturalmente admite comandos de consulta por lotes, como mget y hmget.

3. Montar el ID del producto que no pega

List<Long> noHitIdList = new ArrayList<>(cachedProductMap.size());
for (Long productId : productIdList) {
 if (!cachedProductMap.containsKey(productId)) {
 noHitIdList.add(productId);
 }
}

Debido a que el caché puede perderse debido a la caducidad u otras razones, necesitamos averiguar qué elementos no están en el caché.

4. Consulte la lista de información de productos faltantes de la base de datos en lotes y vuelva a cargarlos en el caché

Primero, consulte la lista de información de productos faltantes de la base de datos en lotes , tenga en cuenta que es un lote .

List<Product> noHitProductList = batchQuery(noHitIdList);

El parámetro es una lista de ID de productos que pierden el caché, ensamblados en el SQL correspondiente, para que el rendimiento sea más rápido:

SELECT * FROM products WHERE id IN
 (1,
 2,
 3,
 4);

Luego, esta información faltante del producto se almacena en el caché, utilizando el comando mset de Redis.

//将没有命中的商品加入到缓存里
Map<Long, Product> noHitProductMap =
 noHitProductList.stream()
 .collect(
 Collectors.toMap(Product::getId, Function.identity())
 );
cacheUtils.mset(noHitProductMap);
//将没有命中的商品加入到聚合map里
cachedProductMap.putAll(noHitProductMap);

5. Recorrer la lista de ID de productos y ensamblar la lista de objetos

for (Long productId : productIdList) {
 Product product = cachedProductMap.get(productId);
 if (product != null) {
 result.add(product);
 }
}

En la solución actual, cuando se alcanza la memoria caché, después de dos E/S de red, la primera E/S de consulta de base de datos y la segunda E/S de consulta de Redis, el rendimiento será mejor.

Todas las operaciones son operaciones por lotes, incluso si hay una pérdida de caché, la velocidad general es más rápida.

" Consultar la lista de ID de objetos y luego almacenar en caché cada entrada de objeto " Esta solución es más flexible. Cuando consultamos la lista de ID de objetos , es posible que no se limite a la base de datos, sino también a los motores de búsqueda, Redis, etc.

La siguiente figura muestra el proceso de búsqueda de Open Source China:

La esencia es: los resultados paginados de la búsqueda solo contienen la ID del objeto comercial, y la información detallada del objeto debe obtenerse del caché + MySQL.

3 Almacene en caché la lista de ID de objetos, mientras almacena en caché cada entrada de objeto

El autor una vez refactorizó un servicio similar al círculo de amigos, ingresó a la página de la clase y mostró toda la dinámica de los miembros de la clase en forma de cascada.

Usamos el modo push para almacenar cada ID dinámico en la estructura de datos Redis ZSet. Redis ZSet es una estructura de datos de tipo de conjunto ordenado, que consta de múltiples elementos de cadena únicos ordenados, cada elemento está asociado con un valor de coma flotante.

ZSet usa la estructura miembro -> puntuación:

  • miembro: el identificador ordenado, que también es la segunda dimensión de ordenación predeterminada (cuando la puntuación es la misma, Redis ordena en el orden lexicográfico del miembro)
  • puntuación: la puntuación ordenada, el tipo de almacenamiento es doble

Como se muestra en la figura anterior: ZSet almacena la lista de ID dinámicos, el valor de miembro es el número dinámico y el valor de puntaje es el tiempo de creación .

El efecto de paginación se puede realizar a través del comando ZREVRANGE de ZSet. 

ZREVRANGE es uno de los comandos para el conjunto ordenado en Redis. Se utiliza para devolver los miembros del rango especificado en el conjunto ordenado según la puntuación de los miembros de mayor a menor.

Para lograr el efecto de paginación, pase los siguientes parámetros de paginación:

A través del comando ZREVRANGE, podemos consultar la lista de ID dinámicos.

Después de consultar la lista de ID dinámicos, cada entrada de objeto dinámico debe almacenarse en caché. Los objetos dinámicos incluyen detalles, comentarios, Me gusta y favoritos. Necesitamos proporcionar configuraciones de caché separadas para estos datos.

Ya sea consultando el caché o reescribiéndolo, para mejorar el rendimiento del sistema, las operaciones por lotes son más eficientes.

Si la estructura del objeto de caché es simple, use los comandos mget y hmget; si la estructura es compleja, puede considerar usar el modo de secuencia de comandos pipleline y Lua. La solución por lotes elegida por el autor es la función de canalización de Redis.

Simulemos nuevamente el proceso de obtención de una lista de paginación dinámica:

  1. Utilice el comando ZREVRANGE de ZSet para pasar los parámetros de paginación para consultar la lista de ID dinámicos;
  2. Pase los parámetros de la lista de ID dinámicos y use la función pipleline de Redis para obtener detalles dinámicos, comentarios, Me gusta y favoritos de la memoria caché en lotes, y reúna estos datos funcionales en una lista.

4 Resumen

Este artículo describe tres formas de implementar una caché de lista paginada:

  1. Almacenar en caché los resultados de la lista paginada directamente
  2. Consulte la lista de ID de objetos, solo almacene en caché cada entrada de objeto
  3. Almacene en caché una lista de ID de objetos, mientras que cada entrada de objeto se almacena en caché

Estos tres métodos son progresivos capa por capa.La clave es: control detallado del almacenamiento en caché y carga masiva de objetos .

 

Haga clic para seguir y conocer las nuevas tecnologías de Huawei Cloud por primera vez~

{{o.nombre}}
{{m.nombre}}

Supongo que te gusta

Origin my.oschina.net/u/4526289/blog/9008398
Recomendado
Clasificación