Redis: problema de eficiencia de cambio de nombre
rename es el comando para cambiar el nombre de la clave en redis. cambiar el nombre de la clave newkey significa cambiar el nombre de la clave a newkey.
La mayoría de los documentos que introducen el cambio de nombre solo lo describen como un comando con complejidad temporal O(1), pero olvidan explicar los problemas de rendimiento que puede causar (cuando se trata de sobrescribir valores antiguos, la complejidad temporal debe ser es O(1) O(M) ).
Hagamos un experimento sobre el cambio de nombre.
Construyamos un servidor Redis, versión 3.2, y observemos su memoria
. 2 y verifique su memoria.
Luego usaremos lua para crear una clave grande llamada prueba para redis. La prueba tiene campos de 500w, cada campo tiene un valor de 1.
Lo haremos con Lua. Se puede utilizar para crear una clave grande llamada prueba que tiene 5 millones de campos y el valor de cada campo es 1. El valor de cada campo es 1
En este punto, echemos un vistazo al uso de memoria de redis
Debido a la creación de la prueba de clave grande, el uso de memoria de redis supera los 300 MB.
A continuación, creamos una clave temporal y la usamos para cambiar el nombre de la prueba de clave grande.
En este punto, podemos ver la excepción del tiempo de ejecución, el cambio de nombre tarda 2,36 segundos en ejecutarse. ¿Por qué es esto? Echemos un vistazo al uso de memoria de redis:
A través de la información devuelta, podemos ver que después de realizar el cambio de nombre, redis eliminó y recicló la prueba de clave grande. El tamaño de este objeto de valor supera los 300 megabytes. Bytes, la complejidad temporal de la eliminación de claves de Redis es O (M), donde M es el miembro eliminado. Aquí M es el número de miembros eliminados: 500w. Es esta operación de eliminación "implícita" la que provoca una alta latencia.
Veamos cómo la documentación oficial describe el comportamiento de rename:
Si la nueva clave ya existe, redis sobrescribirá la nueva clave con el valor de la clave y el valor original de la nueva clave será reemplazado por redis Eliminación implícita. Sabemos que eliminar claves grandes generará una alta latencia (redis es un servicio de proceso único y durante la eliminación de claves grandes, el servidor impedirá la ejecución de otros comandos), lo que resulta en un cambio de nombre con una complejidad temporal de O (1 ) que también puede interferir con redis. Los desarrolladores que lean este documento pueden creer erróneamente que se trata de un comando O(1) particularmente seguro.
Ahora que la documentación establece claramente que este comportamiento existe, echaré un vistazo al código fuente para ver cómo funciona esta lógica:
Ordinario O(1) pesado La lógica La forma de nombrar se explica por sí misma y el proceso que implica la reescritura se puede simplificar a lo siguiente:
Antes de cambiar el puntero del puntero, redis primero usará if (lookupKeyWrite(c- gt; db, c- gt; argv[2]) ! = NULL) para determinar si newkey tiene un valor correspondiente y, de ser así, llame a dbDelete(c- gt; db, c-gt; argv[2]);
Cuando usamos redis, teclas, hgetall y del son comandos que debemos usar con precaución, porque llamar a estos comandos de manera irrazonable puede bloquear otras solicitudes de redis durante mucho tiempo o incluso causar un uso excesivo de la CPU. alto, interfiriendo así con todo el servidor. Sin embargo, el comando trivial cambiar nombre puede causar el mismo problema, por lo que debe usarse con precaución.
RENOMBRAR - Redis