¿Qué son los UUID y por qué son útiles? – CloudSavvy TI

Ilustración que muestra una computadora portátil y archivos de la caja de documentos encima de ella
Stokkete/Shutterstock.com

Un identificador único universal (UUID) es una forma específica de identificador que puede considerarse único con seguridad para la mayoría de los propósitos prácticos. Dos UUID generados correctamente tienen una posibilidad prácticamente insignificante de ser idénticos, incluso si se crean en dos entornos diferentes por partes separadas. Por eso se dice que los UUID son universalmente único.

En este artículo, veremos las características de los UUID, cómo funciona su singularidad y los escenarios en los que pueden simplificar la identificación de recursos. Aunque abordaremos los UUID desde la perspectiva común del software que interactúa con los registros de la base de datos, son ampliamente aplicables a cualquier caso de uso en el que se requiera la generación de ID única descentralizada.

¿Qué es realmente un UUID?

Un UUID es simplemente un valor que puede tratar con seguridad como único. El riesgo de colisión es tan bajo que razonablemente puede optar por ignorarlo por completo. Es posible que vea que se hace referencia a los UUID con diferentes términos (GUID, o Globally Unique Identifier, es la semántica preferida de Microsoft), pero el significado y el efecto siguen siendo los mismos.

Un UUID verdadero es un identificador único que se genera y representa mediante un formato estandarizado. Los UUID válidos están definidos por RFC 4122; esta especificación describe los algoritmos que se pueden usar para generar UUID que conservan la singularidad entre implementaciones, sin una autoridad emisora ​​central.

El RFC incluye cinco algoritmos diferentes, cada uno de los cuales utiliza un mecanismo diferente para generar un valor. He aquí un breve resumen de las «versiones» disponibles:

  • Versión 1: basada en el tiempo – Combina una marca de tiempo, una secuencia de reloj y un valor que es específico del dispositivo generador (generalmente su dirección MAC) para producir una salida que es única para ese host en ese momento.
  • Versión 2 – Seguridad DCE – Esta versión fue desarrollada como una evolución de la Versión 1 para su uso con Distributed Computing Environment (DCE). No es muy utilizado.
  • Versión 3: basada en nombres (MD5) – MD5 genera un «espacio de nombres» y un «nombre» para crear un valor que sea único para ese nombre dentro del espacio de nombres. La generación de otro UUID con el mismo espacio de nombres y el mismo nombre producirá un resultado idéntico, por lo que este método ofrece resultados reproducibles.
  • Versión 4 – Aleatorio – La mayoría de los sistemas modernos tienden a optar por UUID v4, ya que utiliza la fuente de números aleatorios o pseudoaleatorios del host para emitir sus valores. Las posibilidades de que el mismo UUID se produzca dos veces son prácticamente insignificantes.
  • Versión 5: basada en el nombre (SHA-1) – Esto es similar a la versión 3, pero utiliza el algoritmo SHA-1 más fuerte para codificar el nombre y el espacio de nombres de entrada.

Aunque el RFC se refiere a los algoritmos como versiones, eso no significa que siempre deba usar la versión 5 porque aparentemente es la más nueva. El que elija depende de su caso de uso; en muchos escenarios, se elige v4 debido a su naturaleza aleatoria. Esto lo convierte en el candidato ideal para escenarios simples de «dame un nuevo identificador».

Los algoritmos de generación emiten un entero sin signo de 128 bits. Sin embargo, los UUID se ven más comúnmente como cadenas hexadecimales y también se pueden almacenar como una secuencia binaria de 16 caracteres. Aquí hay un ejemplo de una cadena UUID:

16763be4-6022-406e-a950-fcd5018633ca

El valor se representa como cinco grupos de caracteres alfanuméricos separados por guiones. Los guiones no son un componente obligatorio de la cadena; su presencia es hasta los detalles históricos de la especificación UUID. También hacen que el identificador sea mucho más fácil de percibir para los ojos humanos.

Casos de uso de UUID

El principal caso de uso de los UUID es la generación descentralizada de identificadores únicos. Puede generar el UUID en cualquier lugar y considerarlo único de manera segura, ya sea que se origine en su código de back-end, un dispositivo cliente o su motor de base de datos.

Los UUID simplifican la determinación y el mantenimiento de la identidad de los objetos en entornos desconectados. Históricamente, la mayoría de las aplicaciones usaban un campo entero de incremento automático como clave principal. Cuando estás creando un nuevo objeto, no puedes saber su ID hasta que después se había insertado en la base de datos. Los UUID le permiten determinar la identidad mucho antes en su aplicación.

Aquí hay una demostración básica de PHP que demuestra la diferencia. Veamos primero el sistema basado en números enteros:

class BlogPost {
    public function __construct(
        public readonly ?int $Id,
        public readonly string $Headline,
        public readonly ?AuthorCollection $Authors=null) {}
}
 
#[POST("/posts")]
function createBlogPost(HttpRequest $Request) : void {
    $headline = $Request -> getField("Headline");
    $blogPost = new BlogPost(null, $headline);
}

Tenemos que inicializar el $Id propiedad con null porque no podemos saber su identificación real hasta después se ha persistido en la base de datos. Esto no es lo ideal – $Id no debería ser anulable y permite BlogPost instancias de existir en un estado incompleto.

Cambiar a UUID soluciona el problema:

class BlogPost {
    public function __construct(
        public readonly string $Uuid,
        public readonly string $Headline,
        public readonly ?AuthorCollection $Authors=null) {}
}
 
#[POST("/posts")]
function createBlogPost(HttpRequest $Request) : void {
    $headline = $Request -> getField("Headline");
    $blogPost = new BlogPost("16763be4-...", $headline);
}

Los identificadores de publicación ahora se pueden generar dentro de la aplicación sin correr el riesgo de valores duplicados. Esto garantiza que las instancias de objetos siempre representen un estado válido y no necesiten propiedades de ID anulables torpes. El modelo también facilita el manejo de la lógica transaccional; registros secundarios que necesitan una referencia a su padre (como nuestra publicación Author asociaciones) se pueden insertar de inmediato, sin un viaje de ida y vuelta a la base de datos para obtener el ID que se le asignó al padre.

En el futuro, su aplicación de blog podría transferir más lógica al cliente. Quizás la interfaz gane soporte para la creación completa de borradores sin conexión, creando efectivamente BlogPost instancias que se conservan temporalmente en el dispositivo del usuario. Ahora el cliente podría generar el UUID de la publicación y transmitirlo al servidor cuando se recupere la conectividad de la red. Si el cliente recuperó posteriormente la copia del borrador del servidor, podría compararlo con cualquier estado local restante, ya que el UUID ya se conocería.

Los UUID también lo ayudan a combinar datos de varias fuentes. Fusionar tablas de bases de datos y cachés que usan claves enteras puede ser tedioso y propenso a errores. Los UUID ofrecen unicidad no solo dentro de las tablas sino a nivel de todo el universo. Esto los convierte en mejores candidatos para estructuras replicadas y datos que se mueven con frecuencia entre diferentes sistemas de almacenamiento.

Advertencias cuando los UUID se encuentran con las bases de datos

Los beneficios de los UUID son bastante convincentes. Sin embargo, hay varios errores a tener en cuenta al usarlos en sistemas reales. Un factor importante a favor de los ID enteros es que son fáciles de escalar y optimizar. Los motores de bases de datos pueden indexar, clasificar y filtrar fácilmente una lista de números que solo van en una dirección.

No se puede decir lo mismo de los UUID. Para empezar, los UUID son cuatro veces más grandes que los números enteros (36 bytes frente a 4 bytes); para grandes conjuntos de datos, esto podría ser una consideración importante en sí misma. Los valores también son mucho más complicados de ordenar e indexar, particularmente en el caso de los UUID aleatorios más comunes. Su naturaleza aleatoria significa que no tienen un orden natural. Esto dañará el rendimiento de la indexación si usa un UUID como clave principal.

Estos problemas pueden agravarse en una base de datos bien normalizada que hace un uso intensivo de claves foráneas. Ahora puede tener muchas tablas relacionales, cada una de las cuales contiene referencias a sus UUID de 36 bytes. Eventualmente, la memoria adicional necesaria para realizar combinaciones y clasificaciones podría tener un impacto significativo en el rendimiento de su sistema.

Puede mitigar parcialmente los problemas almacenando sus UUID como datos binarios. Eso significa un BINARY(16) columna en lugar de VARCHAR(36). Algunas bases de datos como PostgreSQL incluyen un UUID tipo de datos; otros como mysql tienen funciones que pueden convertir una cadena UUID a su representación binaria, y viceversa. Este enfoque es más eficiente, pero recuerde que seguirá utilizando recursos adicionales para almacenar y seleccionar sus datos.

Una estrategia eficaz puede ser retener los números enteros como sus claves principales, pero agregar un campo UUID adicional para la referencia de su aplicación. Las tablas de vínculos relacionales podrían usar ID para mejorar el rendimiento mientras su código obtiene e inserta objetos de nivel superior con UUID. Todo se reduce a su sistema, su escala y sus prioridades: cuando necesita una generación de ID descentralizada y fusiones de datos sencillas, los UUID son la mejor opción, pero debe reconocer las ventajas y desventajas.

Resumen

Los UUID son valores únicos que puede usar de manera segura para la generación de identidad descentralizada. Colisiones son posible, pero debe ser tan raro que se puede descartar de la consideración. Si generó mil millones de UUID por segundo durante todo un siglo, la probabilidad de encontrar un duplicado sería alrededor del 50% suponiendo que se dispusiera de suficiente entropía.

Puede usar UUID para establecer la identidad independientemente de su base de datos, antes de que ocurra una inserción. Esto simplifica el código a nivel de aplicación y evita que existan objetos identificados incorrectamente en su sistema. Los UUID también ayudan a la replicación de datos al garantizar la exclusividad independientemente del almacén de datos, el dispositivo o el entorno, a diferencia de las claves enteras tradicionales que funcionan a nivel de tabla.

Si bien los UUID ahora son omnipresentes en el desarrollo de software, no son una solución perfecta. Los recién llegados tienden a obsesionarse con la posibilidad de colisiones, pero esta no debe ser su principal consideración, a menos que su sistema sea tan sensible que deba garantizarse la unicidad.

El desafío más evidente para la mayoría de los desarrolladores tiene que ver con el almacenamiento y la recuperación de los UUID generados. Usando ingenuamente un VARCHAR(36) (o quitando los guiones y usando VARCHAR(32)) podría paralizar su aplicación con el tiempo, ya que la mayoría de las optimizaciones de indexación de bases de datos serán ineficaces. Investigue las capacidades integradas de manejo de UUID de su sistema de base de datos para asegurarse de obtener el mejor rendimiento posible de su solución.

Deja un comentario

En esta web usamos cookies para personalizar tu experiencia de usuario.    Política de cookies
Privacidad