[Redis] Exploración en profundidad de los tipos de datos de Redis: cadena de cadena


Prefacio

string El tipo de cadena es el tipo de datos más básico en Redis. Se deben tener en cuenta los siguientes puntos sobre el tipo de cadena:

  1. En Redis, todos los tipos de claves son de tipo cadena y varios otros tipos de datos también se crean sobre la base de tipos de cadena. Por ejemplo, los elementos de listas y conjuntos son todos de tipo cadena.
  2. En Redis, las cadenas se almacenan directamente en formato binario, por lo que cuando se usa Redis, no es necesario considerar problemas de codificación como MySQL (la codificación no coincidente provocará caracteres confusos). Por lo tanto, Redis no manejará el problema de la codificación del juego de caracteres, sino que se almacenará la codificación del juego de caracteres utilizada en el comando pasado por el cliente.
  3. El valor del tipo de cadena en Redis puede ser una cadena, una cadena en formato JSON o XML, un número, un número entero, un número de punto flotante o incluso datos de flujo binario, como imágenes, audio, videos, etc. Sin embargo, el valor máximo de una cadena no puede exceder los 512 MB.

1. Comandos de operación de tipo cadena

Establecer y obtener comandos relacionados

1. ESTABLECER y OBTENER

un conjunto:

La función del comando SET es establecer el valor del tipo de cadena en Redis. Si la clave ya existe antes de la configuración, no importa cuál sea el tipo de datos original, el valor original se sobrescribirá y el TTL establecido por la clave tampoco será válido.

Establecer sintaxis:

SET key value [expiration EX seconds|PX milliseconds] [NX|XX]

Descripción de la opción:

  • EX seconds: Establece el tiempo de caducidad de la clave en segundos, que equivale a EXPIRE;
  • PX milliseconds: Establece el tiempo de caducidad de la clave en milisegundos, que equivale a PEXPIRE;
  • NX: Solo se configura cuando la clave no existe; si la clave ya existía antes, la configuración no se ejecutará;
  • XX: Solo se establece cuando la clave existe; si la clave no existe, la configuración no se ejecutará.

Precauciones:

  1. []Solo se puede seleccionar una de las opciones internas, []mientras que las opciones intermedias pueden existir al mismo tiempo. Es decir, EXlas PXopciones y no pueden existir al mismo tiempo, y NXlas opciones y XXno pueden existir al mismo tiempo, porque son mutuamente excluyentes.
  2. El comando SET con opciones se puede reemplazar por SETEX, PSETEX, SETNX y otros comandos.

valor de retorno:

  • Si la configuración es exitosa, se devuelve OK.
  • Si SET especifica la opción NX o XX pero la condición no se cumple, la ejecución falla y devuelve nil.

Ejemplo de uso:

EX y PX:

NX y XX

SET, SET NX, SET XXProceso de ejecución:

b) OBTENER

La función del comando GET es obtener el valor correspondiente a la clave. Si la clave no existe, devolverá nil, si el tipo de datos del valor no es una cadena, informará un error.

Ejemplo de uso:

2. MSET y MGET

La función de MSET es establecer múltiples pares clave-valor a la vez, mientras que la función de MGET es obtener el valor de múltiples claves a la vez. Si la clave correspondiente no existe o el tipo de datos correspondiente no es una cadena, será devuelto nil.

Casos de uso:

a)MSET:

b) MGET:

Precauciones:

Como se mencionó en el artículo anterior, Redis es una tarea de procesamiento de un solo subproceso y el cliente y el servidor de Redis se comunican a través de la red, por lo que al configurar u obtener varias claves, se recomienda operar al mismo tiempo para reducir el número. de solicitudes de red.

3. SETNX、SETEX、SETPX

a) La función del comando SETNX es configurar la clave si no existe, de lo contrario no se configurará, por ejemplo:


b) La función del comando SETEX es especificar el tiempo de vencimiento de segundo nivel al configurar la clave

gramática:

SETEX key seconds value

Por ejemplo:

c) El propósito del comando PSETEX es especificar el tiempo de vencimiento en milisegundos al configurar la clave.

gramática:

SETEX key milliseconds value

Por ejemplo:

Contar comandos relacionados

1. INCR y INCRBY

  1. INCR

INCRLa función del comando es sumar uno al número representado por la cadena correspondiente a la clave.

  • Si la clave no existe, el valor correspondiente a la clave se considera 0 y luego se agrega uno;
  • Si el valor correspondiente a la clave no es un número entero o su rango excede un entero con signo de 64 bits, se informará un error;
  • Si INCRla ejecución es exitosa, se devuelve el valor aumentado en uno; de lo contrario, se devuelve el mensaje de error correspondiente.

Ejemplo de uso:

  1. INCRBY

INCRBYLa función del comando es agregar un número entero especificado al número entero representado por la cadena correspondiente a la clave.

  • Si la clave no existe, el valor correspondiente a la clave se considera 0 y luego se agrega el número especificado;
  • Si el valor correspondiente a la clave no es un número entero o su rango excede un entero con signo de 64 bits, se informará un error;
  • Si INCRBYla ejecución es exitosa, se devuelve el valor agregado; de lo contrario, se devuelve el mensaje de error correspondiente.

Ejemplo de uso:

2. DECR y DECRBY

  1. DECR

DECR La función del comando es disminuir en uno el número representado por la cadena correspondiente a la clave.

  • Si la clave no existe, el valor correspondiente a la clave se considera 0 y luego se reduce en uno;
  • Si el valor correspondiente a la clave no es un número entero o su rango excede un entero con signo de 64 bits, se informará un error;
  • Si DECR la ejecución es exitosa, se devuelve el valor menos uno; de lo contrario, se devuelve el mensaje de error correspondiente.

Ejemplo de uso:

  1. DECRBY

DECRBYLa función del comando es restar un número entero especificado del número entero representado por la cadena correspondiente a la clave.

  • Si la clave no existe, el valor correspondiente a la clave se considera 0 y luego se resta por el número especificado;
  • Si el valor correspondiente a la clave no es un número entero o su rango excede un entero con signo de 64 bits, se informará un error;
  • Si DECRBYla ejecución es exitosa, se devuelve el valor restado; de lo contrario, se devuelve el mensaje de error correspondiente;
  • Si DECRBYel número especificado que se va a restar es un número negativo, significa sumar este número.

Ejemplo de uso:

3. INCRBYFLOAT

INCRBYFLOATLa función del comando es sumar el número de punto flotante representado por la cadena correspondiente a la clave al número especificado.

gramática:

INCRBYFLOAT key increment 
  • Si la clave no existe, el valor predeterminado es 0 y luego se realiza la operación de suma;
  • Si la cadena correspondiente a la clave no es un número, se informará un error
  • Si el número especificado es un número negativo, significa restar este número;
  • Si INCRBYFLOATla ejecución es exitosa, se devuelve el resultado de la operación; de lo contrario, se devuelve un mensaje de error;
  • Permite representar números de coma flotante en notación científica.

Ejemplo de uso:

Comandos relacionados con la operación de cadenas

1. AÑADIR

APPENDLa función del comando es agregar la cadena después de la cadena correspondiente a la clave.

gramática:

APPEND key value 
  • Si la clave no existe, su efecto es equivalente al comando SET;
  • Si APPENDla ejecución es exitosa, se devuelve la longitud de la cadena final.

2. EXTRAÑO

GETRANGELa función del comando es interceptar la subcadena en la cadena correspondiente a la clave.

gramática:

GETRANGE key start end
  • El contenido interceptado está determinado por el inicio y el final del desplazamiento especificado, y el intervalo se cierra hacia la izquierda y hacia la derecha;
  • El desplazamiento especificado puede ser un número negativo. Cuando se especifica como un número negativo, significa los últimos caracteres, como -1 significa el primer último carácter;
  • Las compensaciones que estén fuera de rango se ajustarán al valor correcto según la longitud de la cadena.

Ejemplo de uso:

3. ESTABLECERRANGO

SETRANGELa función del comando es sobrescribir una parte de la cadena correspondiente a la clave comenzando desde la posición especificada.

gramática:

SETRANGE key offset value 
  • La longitud del reemplazo es la longitud de la cadena de reemplazo. Si la longitud detrás de la cadena original es insuficiente, se reemplazará toda esta última;
  • Si la clave no existe y la posición de reemplazo especificada es mayor que 0, la posición anterior se reemplaza por 0 hexadecimal;
  • Si el reemplazo tiene éxito, se devuelve la longitud de la cadena final.

4. ESTRENAR

STRLENLa función del comando es obtener la longitud de la cadena correspondiente a la clave.

gramática:

STRLEN key
  • Su valor de retorno es la longitud de la cadena;
  • Si la clave no existe, devuelve 0;
  • Si el tipo de valor correspondiente a la clave no es una cadena, se informará un error;
  • La longitud de la cadena está determinada por las reglas de codificación actuales.

Ejemplo de uso:

Resumen de comandos relacionados con cadenas

El siguiente es un resumen de los comandos relacionados con el tipo de cadena en Redis, incluidos comandos, funciones y complejidad del tiempo:

Orden efecto complejidad del tiempo
COLOCAR Establezca el valor de la clave en la cadena especificada O(1)
CONSEGUIR Obtenga el valor de cadena correspondiente a la clave O(1)
MSET Establecer múltiples pares clave-valor en lotes O(N) (N es el número de pares clave-valor)
MGET Obtenga los valores de varias claves en lotes O(N) (N es el número de enlaces)
SETNX Establecer valor sólo si la clave no existe O(1)
SIETE Establecer el valor de la clave y el tiempo de vencimiento (segundos) O(1)
PSETEX Establecer el valor de la clave y el tiempo de vencimiento (milisegundos) O(1)
INCR Suma uno al valor numérico correspondiente a la clave O(1)
INCRBY Agregue el valor numérico correspondiente a la clave al número entero especificado O(1)
Dic Disminuir en uno el valor numérico correspondiente a la clave O(1)
DECRBY Reste el número entero especificado del valor numérico correspondiente a la clave O(1)
INCRBYFLOAT Agregue el valor de punto flotante correspondiente a la clave al número de punto flotante especificado O(1)
ADJUNTAR Agregue la cadena después del valor de la cadena correspondiente a la clave O(1)
AFECTADO Obtenga la subcadena de la cadena correspondiente a la clave O(N) (N es la longitud de la subcadena)
ESTABLECERRANGO Sobrescribe parte de la cadena correspondiente a la clave. O(N) (N es la longitud de la cadena de reemplazo)
ESTRENAR Obtenga la longitud de la cadena correspondiente a la clave. O(1)

2. Método de codificación de tipo cadena.

En Redis, los valores de tipo cadena (cadena) se pueden almacenar utilizando una variedad de métodos de codificación diferentes. El método de codificación específico se selecciona dinámicamente en función del contenido y el tamaño de los datos para ahorrar memoria y mejorar el rendimiento al máximo. Las siguientes son codificaciones comunes para tipos de cadenas en Redis:

  1. RAW (Cadena dinámica simple) : esta es la codificación de cadena más común. Se utiliza para almacenar cadenas más cortas cuya longitud no exceda el límite de la estructura de codificación de la cadena. Esta codificación no comprime la cadena, por lo que es eficaz al almacenar cadenas más pequeñas.

  2. INT (codificación de enteros) : cuando una cadena se puede interpretar como un número entero, Redis la codificará como un número entero para ahorrar memoria. La codificación de enteros se divide en los siguientes métodos de subcodificación:

    • int16_t: codificación de enteros de 16 bits, que almacena números enteros dentro de 16 bits.
    • int32_t: codificación de enteros de 32 bits, que almacena números enteros dentro de 32 bits.
    • int64_t: codificación de enteros de 64 bits, que almacena números enteros dentro de 64 bits.
  3. EMBSTR (codificación de cadenas anidadas) : se utiliza para almacenar cadenas más cortas, pero a diferencia de RAW, el método de codificación de EMBSTR también almacena la longitud de la cadena en la estructura de codificación para ahorrar memoria.

  4. Codificación compartida RAW y EMBSTR : en algunos casos, Redis utilizará un método de codificación especial que puede compartir las ventajas de los métodos de codificación RAW y EMBSTR. Esto significa que puede almacenar tanto cadenas más cortas como cadenas más grandes de manera eficiente.

  5. SDS (Simple Dynamic String) : SDS es una estructura de datos utilizada para representar cadenas que tiene un tamaño dinámico y se puede expandir sin necesidad de reasignar memoria. Esta codificación se utiliza para almacenar cadenas más grandes para ahorrar memoria y mejorar el rendimiento.

Cabe señalar que Redis seleccionará dinámicamente el método de codificación apropiado según el contenido y el tamaño de la cadena, por lo que los desarrolladores no necesitan especificar manualmente el método de codificación. Este método de codificación dinámica permite a Redis aprovechar al máximo la memoria en diferentes circunstancias y mejorar la eficiencia.

Puede usar OBJECT ENCODINGcomandos de Redis para ver cómo se codifica una clave específica, por ejemplo:

OBJECT ENCODING mykey

Esto devolverá mykeycómo está codificada la clave.

Por ejemplo:

3. Escenarios de uso de tipo cadena

1. caché

Debido a su rápida velocidad, Redis se utiliza a menudo para funciones de almacenamiento en caché. Un escenario típico de uso de caché es que Redis actúa como capa de búfer, MySQL actúa como capa de almacenamiento y la mayoría de los
datos solicitados se obtienen de Redis. Dado que Redis tiene la característica de admitir una alta concurrencia, el almacenamiento en caché generalmente puede desempeñar un papel en la aceleración de la lectura y la escritura y en la reducción de la presión del back-end.

Arquitectura de almacenamiento caché compuesta por Redis + MySQL:

A continuación se simula el proceso de acceso a los datos comerciales en la figura anterior mediante pseudocódigo:

1) Suponga que el negocio es obtener información del usuario en función del uid del usuario.

UserInfo getUserInfo(long uid) {
    
    
	...
}

2) Primero obtenga la información del usuario de Redis, asumimos que la información del usuario se almacena en la clave correspondiente a "usuario: información:"

// 根据 uid 得到 Redis 的键
String key = "user:info:" + uid;
// 尝试从 Redis 中获取对应的值
String value = Redis 执⾏命令:get key;
// 如果缓存命中(hit)
if (value != null) {
    
    
	// 假设用户信息按照 JSON 格式存储
	UserInfo userInfo = JSON 反序列化(value);
	return userInfo;
}

3) Si la información del usuario no se obtiene de Redis o el caché falla (falla), la información correspondiente se obtiene de MySQL y luego se escribe en el caché y se devuelve.

// 如果缓存未命中(miss)
if (value == null) {
    
    
	// 从数据库中,根据 uid 获取⽤⼾信息
	UserInfo userInfo = MySQL 执⾏ SQL:select * from user_info where uid = <uid>
	// 如果表中没有 uid 对应的⽤⼾信息
	if (userInfo == null) {
    
    
		// 响应 404
		return null;
	}

	// 将用户信息序列化成 JSON 格式
	String value = JSON 序列化(userInfo);
	
	// 写⼊缓存,为了防⽌数据腐烂(rot),设置过期时间为 1 ⼩时(3600 秒)
	Redis 执⾏命令:set key value ex 3600

	// 返回用户信息
	return userInfo;
}

Al agregar la función de caché, en circunstancias ideales, la información de cada usuario solo tendrá una consulta MySQL por hora, lo que mejora en gran medida la eficiencia de la consulta y también reduce la cantidad de accesos a MySQL.

PD: principios de diseño y ejemplos de nombres clave de Redis

  1. Prefijo del nombre de la empresa: comience el nombre de la clave con el nombre de la empresa para aislar claves para diferentes empresas o proyectos. Esto ayuda a garantizar que las claves no colisionen entre diferentes aplicaciones o equipos.
    Ejemplo:
    información_usuario:6379
    información_pedido:1234
  2. Nombre del objeto: especifique el nombre del objeto en el nombre de la clave para describir lo que se almacena. Esto ayuda a proporcionar una comprensión clara del tipo de datos u objeto comercial almacenado por la clave.
    Ejemplo:
    perfil_usuario:6379
    catálogo_producto:5678
  3. Identificación única: si lo desea, puede incluir un identificador único en el nombre de la clave para identificar más específicamente los datos almacenados. Esto ayuda a segmentar los datos en diferentes entidades.
    Ejemplo:
    usuario:12345:perfil
    producto:7890:detalles
  4. Propiedades: si sus datos tienen varias propiedades, puede incluir el nombre de la propiedad en el nombre de la clave para refinar aún más el propósito de la clave.
    Ejemplo:
    usuario:12345:perfil:nombre
    producto:7890:detalles:precio
  5. Abreviatura de clave: si el nombre de una clave se vuelve demasiado largo, puede usar abreviaturas para reducir la longitud del nombre de la clave, pero asegúrese de que la abreviatura sea clara y comprensible dentro del equipo.
    Ejemplo:
    u:12345:pr:n (versión abreviada)

Al utilizar esta convención de espacio de nombres de claves, las claves de Redis pueden estar más organizadas y ser más fáciles de mantener y administrar. También puede ayudar a evitar conflictos de nombres de claves, especialmente si varias aplicaciones o equipos utilizan la misma instancia de Redis. Sin embargo, tenga en cuenta que los nombres de clave demasiado largos pueden provocar una degradación del rendimiento, por lo que debe equilibrar los requisitos de legibilidad y rendimiento del nombre de clave.

2. Contar (Contador)

La función Contador es una de las funciones comunes y útiles en Redis, que se puede utilizar para registrar y consultar rápidamente el valor de recuento de un objeto. Este tipo de función es muy útil en muchas aplicaciones, como el recuento de visitas al sitio web, el recuento de me gusta, el recuento de comentarios, el recuento de reproducciones, etc.

Por ejemplo, registre la cantidad de reproducciones de video:

pseudocódigo:

// 在 Redis 中统计某视频的播放次数
long incrVideoCounter(long vid) {
    
    
	key = "video:" + vid;
	long count = Redis 执⾏命令:incr key
	return counter;
}

Sin embargo, existen muchos desafíos y complejidades cuando se trata de desarrollar un sistema de conteo maduro y estable. A continuación se presentan algunos desafíos y consideraciones que pueden necesitar ser abordados:

  1. Anti-trampas : es fundamental garantizar que el sistema de conteo no sea fácilmente manipulado por actores malintencionados. Las medidas antifraude comunes incluyen limitar la tasa de recuento de cada usuario o dirección IP, utilizar códigos o tokens de verificación para verificar el comportamiento del usuario, etc.
  2. Conteo por diferentes dimensiones : En ocasiones es necesario contar según diferentes dimensiones, como por tiempo, ubicación geográfica, tipo de usuario, etc. Para lograr esta flexibilidad, es necesario diseñar una arquitectura de sistema de conteo adaptable.
  3. Evite puntos únicos de problema : un punto único de falla puede provocar la indisponibilidad del sistema de conteo. Para garantizar una alta disponibilidad, considere utilizar la replicación maestro-esclavo o el modo de clúster de Redis, o utilice otros sistemas de recuento distribuido.
  4. Persistencia de datos : Redis almacena datos en la memoria de forma predeterminada, pero para conservar los datos, puede realizar instantáneas periódicas de los datos en el disco o utilizar opciones de persistencia como AOF (Append-Only File).
  5. Optimización del rendimiento : el procesamiento de solicitudes de gran cantidad puede suponer una carga para el rendimiento. Es necesario optimizar la configuración de Redis, considerar el uso de una capa de almacenamiento en caché, un sistema de conteo distribuido o una estrategia de equilibrio de carga para manejar situaciones de carga alta.
  6. Control de concurrencia : las operaciones simultáneas pueden dar como resultado recuentos inconsistentes. Para garantizar la atomicidad del recuento, se pueden utilizar técnicas como transacciones de Redis o bloqueo optimista.
  7. Monitoreo y registro : Establezca un sistema de monitoreo y registro para rastrear el desempeño y operación del sistema de conteo en tiempo real y detectar problemas potenciales.
  8. Planificación de capacidad : considere la planificación de capacidad para el sistema de conteo, incluidas las necesidades de almacenamiento de datos, memoria y espacio en el disco duro, etc., para respaldar el crecimiento futuro.
  9. Limpieza de datos : limpie periódicamente los datos de recuento que ya no son necesarios para evitar la sobrecarga de datos y el uso excesivo de memoria.

En resumen, desarrollar un sistema de conteo realista es una tarea compleja que requiere la consideración de numerosos factores. Elegir la pila de tecnología adecuada, diseñar una buena arquitectura, implementar medidas de seguridad y antifraude, garantizar una alta disponibilidad y establecer una estrategia de monitoreo y mantenimiento son pasos importantes para una implementación exitosa del sistema de conteo. Estos desafíos requieren una planificación e implementación cuidadosas para satisfacer las necesidades del proyecto específico.

3. Sesión compartida (Session)

En un servicio web distribuido, la información de la sesión del usuario generalmente se almacena en el servidor respectivo, que incluye el estado de inicio de sesión del usuario y otros datos relacionados con la sesión. Sin embargo, debido a la necesidad de equilibrio de carga, las solicitudes de los usuarios se distribuirán a diferentes servidores y los datos de la sesión en diferentes servidores no se compartirán.

Esto genera un problema: si las solicitudes del usuario se equilibran en diferentes servidores, es posible que el usuario necesite iniciar sesión nuevamente al actualizar la página o enviar la siguiente solicitud, lo cual es una experiencia inaceptable para el usuario .

Por ejemplo, el almacenamiento descentralizado de sesión que se muestra en la siguiente figura:

Para resolver este problema, se puede utilizar Redis para administrar de forma centralizada la información de la sesión del usuario. En este modo, siempre que se garantice que Redis sea altamente disponible y escalable, sin importar en qué servidor web esté el usuario, puede consultar y actualizar centralmente la información de la sesión desde Redis.

4. Código de verificación del teléfono móvil

Para mejorar la seguridad de los inicios de sesión de los usuarios, muchas aplicaciones siguen los siguientes pasos:

  • Cada vez que un usuario intenta iniciar sesión, se le pide que ingrese su número de teléfono móvil y se realiza una segunda verificación enviando un código de verificación a su teléfono móvil. Este código de verificación requiere que el usuario lo ingrese nuevamente para garantizar que la solicitud de inicio de sesión provenga del propio usuario.
  • Además, para evitar el abuso de la interfaz de SMS y mejorar la seguridad, la frecuencia de obtención de códigos de verificación por minuto suele ser limitada: por ejemplo, en un minuto, el mismo número de teléfono móvil solo puede obtener códigos de verificación hasta 5 veces.

Este proceso puede reducir eficazmente el riesgo de inicios de sesión maliciosos y códigos de verificación de spam, al tiempo que garantiza la seguridad de la cuenta del usuario.

Código de verificación por SMS:

esta función puede utilizar el siguiente pseudocódigo para ilustrar la idea básica de implementación:

String 发送验证码(phoneNumber) {
    
    
    key = "shortMsg:limit:" + phoneNumber;
    // 设置过期时间为 1 分钟(60 秒)
    // 使用 NX,只在不存在 key 时才能设置成功
    bool r = Redis 执行命令:set key 1 ex 60 nx
    if (r == false) {
    
    
        // 说明之前设置过该手机号的验证码了
        long c = Redis 执行命令:incr key
        if (c > 5) {
    
    
            // 说明超过了一分钟 5 次的限制了
            // 限制发送
            return null;
        }
    }
    // 说明要么之前没有设置过手机号的验证码;要么次数没有超过 5 次
    String validationCode = 生成随机的 6 位数的验证码();
    validationKey = "validation:" + phoneNumber;
    // 验证码 5 分钟(300 秒)内有效
    Redis 执行命令:set validationKey validationCode ex 300;
    // 返回验证码,随后通过手机短信发送给用户
    return validationCode;
}

// 验证用户输入的验证码是否正确
bool 验证验证码(phoneNumber, validationCode) {
    
    
    validationKey = "validation:" + phoneNumber;
    String value = Redis 执行命令:get validationKey;
    if (value == null) {
    
    
        // 说明没有这个手机号的验证码记录,验证失败
        return false;
    }
    if (value == validationCode) {
    
    
        return true;
    } else {
    
    
        return false;
    }
}

Lo anterior presenta la aplicación del uso del tipo de datos de cadena de Redis en escenarios como almacenamiento en caché, conteo, administración de sesiones y códigos de verificación de teléfonos móviles. Sin embargo, los escenarios aplicables del tipo de cadena de Redis son mucho más que estos: los desarrolladores pueden dar rienda suelta a su creatividad e imaginación y aplicarla a varios escenarios comerciales según las características del tipo de cadena y los comandos proporcionados.

Supongo que te gusta

Origin blog.csdn.net/qq_61635026/article/details/132744418
Recomendado
Clasificación