Análisis y solución de problemas de operación difusa de Redis (basado en redisTemplate)

Antecedentes de la demanda

		redis存在多个前缀相同的key,有时需要对其进行批量查询,删除,插入。当key大了,会坑惨CPU,因为redis通过tcp对外提供服务,是要i一个多路复用的单线程,每次请求的命令都是生成一个连接,所以后面的命令会阻塞直到前面的服务处理完毕才会继续。所以呢,存在一个隐患,这个隐患也只有量起来后才会出现,当我们循环获取key的时候,一开一合,耗时啊。

solución

Por encima de la versión 2.8, demasiado bajo parece imposible.

Es el momento de introducir el pipeline, que es una tecnología que soluciona el retraso causado por un gran bloqueo al ejecutar una gran cantidad de comandos.

De hecho, el principio es muy simple. La canalización es enviar todos los comandos a la vez para evitar la sobrecarga de la red causada por el envío y la recepción frecuentes. Después de redis empaqueta y recibe un montón de comandos, los ejecutan en secuencia y luego empaquetan los resultados de vuelta al cliente.

De acuerdo con la situación real de la estructura de datos de la caché en el proyecto, la estructura de datos es de tipo cadena, usando el método multiGet de RedisTemplate; la estructura de datos es hash, usando Pipeline (tubería), combinando comandos y redis por lotes.

El llamado funcionamiento no inductivo.

escena 1

Lote insertar / consultar el valor de la clave con el prefijo especificado
Utilice multiGet para obtener en lotes

Ejemplo de versión completa

/**
 * 批量获取key的value
 *
 * @param keys
 * @return
 */
public List<Object> getMul(Collection<String> keys) {
    
    
    List<String> list= (List<String>) keys;
    //方法1
	redisTemplate.executePipelined(new SessionCallback<Object>() {
    
    
		@Override
		public <K, V> Object execute(RedisOperations<K, V> redisOperations) throws DataAccessException {
    
    
			for (String s : list) {
    
    
				//查询
				redisTemplate.opsForValue().get(s);
				//插入
				redisTemplate.opsForValue().set(s, "testValue");
			}
			return null;
		}
	});

	//方法2
	redisTemplate.executePipelined(new RedisCallback<Object>() {
    
    
		@Override
		public Object doInRedis(RedisConnection redisConnection) throws DataAccessException {
    
    
			StringRedisConnection stringRedisConnection = (StringRedisConnection) redisConnection;
			for (String s : list) {
    
    
				//查询
				stringRedisConnection.get(s);
				//插入
				stringRedisConnection.set(s, "testValue");
			}
			return null;
		}
	});
	return redisTemplate.opsForValue().multiGet(keys);
}

Escena 2

Para eliminar los valores de clave del prefijo especificado en lotes,
1. Puede usar el método de claves para realizar una coincidencia aproximada y luego llamar al método de eliminación para deshacerse de él, pero cuando la clave es demasiado grande, la coincidencia es demasiado lenta , que afecta el rendimiento.
2. Puede considerar procesar esta caché en dos pasos,
ya que necesita eliminar en lotes, debe insertarlos, el método de inserción en lotes es el mismo que el mencionado anteriormente. Sin embargo, al insertar, podemos hacer un paso más para poner estas claves con el mismo prefijo en un conjunto de lista. El código es como se muestra en la figura.
Inserte la descripción de la imagen aquí
Esto debe quedar claro. Eliminemos la clave con el prefijo especificado. Luego, primero saque todas las claves de esta lista y luego llame al método de eliminación. El método de eliminación que viene con redisTemplate admite la eliminación por lotes, y no es necesario introducir una canalización para reescribir esas cosas.
el código se muestra a continuación:
Inserte la descripción de la imagen aquí

Esto evita la coincidencia difusa de todos, por supuesto, este tipo de escritura debe considerar algunos detalles, como la coherencia.

Supongo que te gusta

Origin blog.csdn.net/NICVSY/article/details/112984072
Recomendado
Clasificación