El problema fundamental que aborda este artículo es la dificultad inherente de escalar el alojamiento de repositorios Git, un sistema de control de versiones distribuido diseñado originalmente para un flujo de trabajo descentralizado como el del kernel de Linux. Aunque Git se ha convertido en el estándar de la industria, su naturaleza distribuida y su formato de almacenamiento basado en 'packfiles' presentan desafíos significativos para la disponibilidad y escalabilidad en entornos centralizados de empresas y proyectos de código abierto. La necesidad de mantener la consistencia estricta de los datos de Git, combinada con patrones de acceso aleatorio a los packfiles, ha llevado a soluciones complejas y costosas de operar.
La tesis central es que, si bien el diseño de Git es robusto para el cliente local, su modelo de almacenamiento y replicación no se traduce eficientemente a una arquitectura de servidor distribuida a gran escala. Las soluciones previas, como la distribución de sistemas de archivos o la replicación a nivel de packfile con algoritmos de consenso como 3PC (Spokes de GitHub), han encontrado limitaciones en escalabilidad horizontal y complejidad operativa. El artículo propone que un enfoque 'WAL-first' con almacenamiento de objetos como fuente de verdad puede resolver estas limitaciones, desacoplando la durabilidad de la consistencia y permitiendo una escalabilidad de lectura casi ilimitada.
Arquitectura del Sistema
El sistema 'Continuity' se basa en un Write-Ahead Log (WAL) persistido en un almacenamiento de objetos compatible con S3. Cada operación de 'push' se registra como una entrada en el WAL, que se almacena como un objeto separado en S3. La confirmación de un 'push' solo ocurre después de que se ha persistido completamente en el WAL y su transacción de referencia se ha preparado en una copia local del repositorio, actualizando un índice WAL que también es un objeto en S3. Esto asegura la linealizabilidad de todos los 'pushes'.
Las réplicas de los repositorios son copias locales en unidades NVMe rápidas, tratadas como una caché caliente. La fuente de verdad es siempre el WAL en S3, lo que permite que el sistema sea 'stateless' y elimine la necesidad de tablas de enrutamiento complejas o bases de datos externas para la ubicación de los repositorios. El consenso para las actualizaciones del WAL se logra mediante operaciones atómicas de 'compare-and-swap' (CAS) en S3, lo que permite que cualquier servidor actúe como primario y garantiza la corrección incluso en estados degradados. La replicación se realiza de forma optimista mediante paquetes UDP de 'gossip' que contienen metadatos para que las réplicas se pongan al día directamente desde S3. Las operaciones de lectura (fetches, clones) verifican la consistencia contra S3 mediante un GET condicional (ETag), asegurando que las réplicas siempre sirvan datos consistentes. La compactación de los packfiles, una operación intensiva en CPU, se realiza solo en el primario, y las réplicas descargan los packfiles ya compactados de S3, intercambiando ancho de banda por CPU.
Flujo de Push en Continuity
- 1 Cliente Git Envía packfile y transacción de referencia.
- 2 Servidor Primario Recibe push, escribe packfile a disco local y lo sube a S3.
- 3 Servidor Primario Prepara transacción de referencia en copia local del repo.
- 4 Servidor Primario Actualiza índice WAL en S3 con CAS, apuntando a nueva entrada WAL.
- 5 S3 Persiste entrada WAL y actualiza índice WAL atómicamente.
- 6 Servidor Primario Confirma push al cliente Git.
- 7 Servidor Primario Envía gossip UDP a réplicas con metadatos de actualización.
Flujo de Read (Fetch/Clone) en Continuity
- 1 Cliente Git Solicita fetch/clone a cualquier réplica.
- 2 Réplica Realiza GET condicional a S3 para índice WAL (usando ETag).
- 3 S3 Responde 304 (actualizado) o 200 (nueva versión del índice WAL).
- 4 Réplica (si 200) Descarga nueva versión del índice WAL y se pone al día desde S3.
- 5 Réplica Sirve la operación de lectura desde su copia local del repositorio.
| Capa | Tecnología | Justificación |
|---|---|---|
| storage | S3-compatible Object Storage | Fuente de verdad para el Write-Ahead Log (WAL) y packfiles. Proporciona durabilidad, disponibilidad y escalabilidad masiva. |
| storage | NVMe Drives | Almacenamiento local de alta velocidad para copias de repositorios Git, actuando como una caché caliente para operaciones de lectura y escritura. vs NFS, GFS, DRBD |
| messaging | UDP Gossip | Mecanismo de replicación optimista para notificar a las réplicas sobre nuevas entradas en el WAL, permitiendo que se pongan al día de forma asíncrona desde S3. |
| data-processing | Git (upstream) | Motor subyacente para todas las operaciones de control de versiones. Se utiliza de forma estándar en las copias locales de los repositorios. vs JGit (con DHT) |
Trade-offs
Ganancias
- ▲▲ Escalabilidad horizontal de lectura
- ▲ Consistencia global de lectura
- ▲ Simplicidad operativa (stateless)
- ▲ Durabilidad de datos
- ▲ Flexibilidad de réplicas (desde 1 hasta cientos)
Costes
- △ Latencia de push (limitada por S3 PUT)
- △ Ancho de banda (para descargas de packfiles compactados)
Fundamentos Teóricos
El diseño de 'Continuity' se conecta con principios fundamentales de sistemas distribuidos y bases de datos. El uso de un Write-Ahead Log (WAL) como fuente de verdad es un patrón clásico en sistemas de bases de datos para garantizar la durabilidad y la atomicidad de las transacciones, como se describe en el contexto de los sistemas de gestión de bases de datos relacionales desde los años 70 y 80. La persistencia en S3 y el uso de operaciones atómicas como 'compare-and-swap' para el consenso de escrituras reflejan los principios de los sistemas de almacenamiento de objetos y la construcción de primitivas de consistencia sobre ellos, similar a cómo se construyen sistemas distribuidos sobre Paxos o Raft, aunque en este caso, el consenso se delega a la atomicidad del almacenamiento subyacente y la linealizabilidad del WAL.
La discusión sobre la consistencia eventual versus la consistencia estricta en Git resalta el dilema de CAP Theorem (Brewer, 2000) o PACELC (Abadi, 2012). Git, por su diseño, requiere una consistencia fuerte para evitar estados confusos en el cliente o en los sistemas de CI, lo que hace que la 'C' (Consistency) sea una prioridad sobre la 'A' (Availability) o la 'L' (Latency) en muchos escenarios de replicación. El enfoque de 'Continuity' de verificar las lecturas contra S3 para garantizar la consistencia, incluso si los mensajes de replicación UDP se pierden, es una aplicación práctica del principio de 'read-your-writes' y 'linearizability' en un sistema distribuido, donde la fuente de verdad es el log inmutable.