En informática , el hash consistente [1] [2] es un tipo especial de técnica de hash en el que, cuando se redimensiona una tabla hash , solo es necesario reasignar las claves en promedio, donde es el número de claves y es el número de ranuras. Por el contrario, en la mayoría de las tablas hash tradicionales, un cambio en el número de ranuras de la matriz hace que se reasignen casi todas las claves porque la asignación entre las claves y las ranuras está definida por una operación modular .
El hash consistente distribuye uniformemente las claves de caché entre los fragmentos , incluso si algunos de ellos fallan o no están disponibles. [3]
El término "hashing consistente" fue introducido por David Karger et al. en el MIT para su uso en el almacenamiento en caché distribuido , particularmente para la web . [4] Este artículo académico de 1997 en Symposium on Theory of Computing introdujo el término "hashing consistente" como una forma de distribuir solicitudes entre una población cambiante de servidores web. [5] Cada ranura está representada por un servidor en un sistema distribuido o clúster. La adición de un servidor y la eliminación de un servidor (durante la escalabilidad o la interrupción) requiere solo que los elementos se vuelvan a barajar cuando cambia el número de ranuras (es decir, servidores). Los autores mencionan el hash lineal y su capacidad para manejar la adición y eliminación secuencial de servidores, mientras que el hash consistente permite agregar y eliminar servidores en un orden arbitrario. [1] El artículo fue posteriormente reutilizado para abordar el desafío técnico de realizar un seguimiento de un archivo en redes peer to peer como una tabla hash distribuida . [6] [7]
Teradata utilizó esta técnica en su base de datos distribuida [ cita requerida ] , lanzada en 1986, aunque no utilizaron este término. Teradata todavía utiliza el concepto de tabla hash para cumplir exactamente este propósito. Akamai Technologies fue fundada en 1998 por los científicos Daniel Lewin y F. Thomson Leighton (coautores del artículo que acuñó el término "hashing consistente"). En la red de distribución de contenido de Akamai, [8] el hash consistente se utiliza para equilibrar la carga dentro de un clúster de servidores, mientras que un algoritmo de matrimonio estable se utiliza para equilibrar la carga entre clústeres. [2]
El hash consistente también se ha utilizado para reducir el impacto de fallos parciales del sistema en aplicaciones web de gran tamaño para proporcionar un almacenamiento en caché robusto sin incurrir en las consecuencias de un fallo en todo el sistema. [9] El hash consistente también es la piedra angular de las tablas hash distribuidas (DHT), que emplean valores hash para particionar un espacio de claves en un conjunto distribuido de nodos y luego construyen una red superpuesta de nodos conectados que proporcionan una recuperación eficiente de nodos por clave.
El algoritmo Rendezvous Hashing , diseñado en 1996, es una técnica más simple y más general [ cita requerida ] . Logra los objetivos de un algoritmo hash consistente utilizando el algoritmo de peso aleatorio más alto (HRW, por sus siglas en inglés), que es muy diferente.
En el problema del balanceo de carga , por ejemplo, cuando un BLOB tiene que ser asignado a uno de los servidores de un cluster , se podría usar una función hash estándar de tal manera que calculemos el valor hash para ese BLOB, suponiendo que el valor resultante del hash es , realizamos una operación modular con la cantidad de servidores ( en este caso) para determinar el servidor en el que podemos colocar el BLOB: ; por lo tanto, el BLOB se colocará en el servidor cuyo sucesor de en este caso. Sin embargo, cuando se agrega o elimina un servidor durante una interrupción o escalamiento (cuando cambia), todos los BLOB en cada servidor deben reasignarse y moverse debido al rehashing , pero esta operación es costosa.
El hash consistente fue diseñado para evitar el problema de tener que reasignar cada BLOB cuando se agrega o elimina un servidor en todo el clúster. La idea central es usar una función hash que asigna tanto el BLOB como los servidores a un círculo unitario, generalmente radianes. Por ejemplo, (donde es el hash de un BLOB o identificador de servidor, como dirección IP o UUID ). Luego, cada BLOB se asigna al siguiente servidor que aparece en el círculo en el sentido de las agujas del reloj. Por lo general, se utiliza un algoritmo de búsqueda binaria o una búsqueda lineal para encontrar un "punto" o servidor en el que colocar ese BLOB en particular o complejidades respectivamente; y en cada iteración, que ocurre en el sentido de las agujas del reloj, se realiza una operación (donde es el valor del servidor dentro del clúster) para encontrar el servidor en el que colocar el BLOB. Esto proporciona una distribución uniforme de los BLOB a los servidores. Pero, lo que es más importante, si un servidor falla y se elimina del círculo, solo los BLOB que se asignaron al servidor fallido deben reasignarse al siguiente servidor en el sentido de las agujas del reloj. Del mismo modo, si se agrega un nuevo servidor, se agrega al círculo unitario y solo es necesario reasignar los BLOB asignados a ese servidor.
Es importante destacar que, cuando se agrega o elimina un servidor, la gran mayoría de los BLOB mantienen sus asignaciones de servidor anteriores, y la adición de un servidor solo hace que una fracción de los BLOB se reubique. Aunque el proceso de mover BLOB entre servidores de caché en el clúster depende del contexto, comúnmente, el servidor de caché recientemente agregado identifica a su "sucesor" y mueve todos los BLOB, cuya asignación pertenece a este servidor (es decir, cuyo valor hash es menor que el del nuevo servidor), desde él. Sin embargo, en el caso de los cachés de páginas web , en la mayoría de las implementaciones no hay participación de movimiento o copia, suponiendo que el BLOB almacenado en caché sea lo suficientemente pequeño. Cuando una solicitud llega a un servidor de caché recientemente agregado, ocurre una falla de caché y se realiza una solicitud al servidor web real y el BLOB se almacena en caché localmente para futuras solicitudes. Los BLOB redundantes en los servidores de caché utilizados anteriormente se eliminarían según las políticas de desalojo de caché . [10]
Sean y las funciones hash utilizadas para el BLOB y el identificador único del servidor respectivamente. En la práctica, se utiliza un árbol binario de búsqueda (BST) para mantener dinámicamente el dentro de un clúster o hashring, y para encontrar el sucesor o mínimo dentro del BST, se utiliza el recorrido del árbol .
Para evitar la asimetría de múltiples nodos dentro del radián, que ocurre debido a la falta de una distribución uniforme de los servidores dentro del clúster, se utilizan múltiples etiquetas. Esas etiquetas duplicadas se denominan "nodos virtuales", es decir, múltiples etiquetas que apuntan a una única etiqueta o servidor "real" dentro del clúster. La cantidad de nodos virtuales o etiquetas duplicadas utilizadas para un servidor en particular dentro de un clúster se denomina "peso" de ese servidor en particular. [14]
Se necesitan varias extensiones de la técnica básica para usar de manera efectiva el hash consistente para equilibrar la carga en la práctica. En el esquema básico anterior, si falla un servidor, todos sus BLOB se reasignan al siguiente servidor en el sentido de las agujas del reloj, lo que potencialmente duplica la carga de ese servidor. Esto puede no ser deseable. Para garantizar una redistribución más uniforme de los BLOB en caso de falla del servidor, cada servidor puede ser asignado a múltiples ubicaciones en el círculo unitario. Cuando falla un servidor, los BLOB asignados a cada una de sus réplicas en el círculo unitario se reasignarán a un servidor diferente en el sentido de las agujas del reloj, redistribuyendo así los BLOB de manera más uniforme. Otra extensión se refiere a una situación en la que un solo BLOB se "calienta" y se accede a él una gran cantidad de veces y tendrá que alojarse en múltiples servidores. En esta situación, el BLOB puede asignarse a múltiples servidores contiguos recorriendo el círculo unitario en el sentido de las agujas del reloj. Una consideración práctica más compleja surge cuando dos BLOB se procesan en hash cerca uno del otro en el círculo unitario y ambos se "activan" al mismo tiempo. En este caso, ambos BLOB utilizarán el mismo conjunto de servidores contiguos en el círculo unitario. Esta situación se puede mejorar si cada BLOB elige una función hash diferente para asignar servidores al círculo unitario. [2]
El hash de rendezvous , diseñado en 1996, es una técnica más simple y más general, y permite un acuerdo totalmente distribuido sobre un conjunto de opciones de entre un conjunto posible de opciones. De hecho, se puede demostrar que el hash consistente es un caso especial de hash de rendezvous. Debido a su simplicidad y generalidad, el hash de rendezvous se está utilizando ahora en lugar del hash consistente en muchas aplicaciones.
Si los valores clave siempre aumentan de forma monótona , un enfoque alternativo que utilice una tabla hash con claves monótonas puede ser más adecuado que el hash consistente. [ cita requerida ]
Existe un costo promedio para la redistribución de claves y la complejidad para un hash consistente proviene del hecho de que se requiere una búsqueda binaria entre los ángulos de los nodos para encontrar el siguiente nodo en el anillo. [ cita requerida ]
Algunos ejemplos conocidos de uso consistente de hash incluyen:
El hash consistente es una técnica que evita estos problemas y la usamos para calcular la ubicación de cada clave en el clúster.