Está en la página 1de 25

Spanner: La base de datos distribuida globalmente de Google

Resumen.

Spanner es la base de datos escalable, de múltiples versiones, distribuida globalmente y replicada


sincrónicamente. Es el primer sistema que distribuye datos a escala global y admite transacciones
distribuidas externamente consistentes.

A continuación, se describirá

- Cómo se estructura Spanner


- Su conjunto de características
- La lógica subyacente a varias decisiones de diseño
- Una API de tiempo novedosa que expone la incertidumbre del reloj. Esta API y su implementación
son fundamentales para admitir la coherencia externa y una variedad de características potentes:
lecturas sin bloqueo en el pasado, transacciones de solo lectura sin bloqueo y cambios de
esquema atómico, en todo Spanner.

1. Introducción.

Spanner es una base de datos escalable y distribuida globalmente. Diseñada, construida e


implementada en Google. En el nivel más alto de abstracción, es una base de datos que fragmenta
datos en muchos conjuntos de máquinas de estado de Paxos [21] en datacenters repartidos por todo
el mundo. La replicación se utiliza para la disponibilidad global y la localidad geográfica; los clientes
conmutan automáticamente por error (failover) entre réplicas. Spanner vuelve a dividir
automáticamente en fragmentos los datos en las máquinas a medida que cambia la cantidad de datos
o el número de servidores, y migra automáticamente los datos entre las máquinas (incluso entre los
datacenters) para equilibrar la carga y en respuesta a fallas. Spanner está diseñado para escalar
millones de máquinas en cientos de datacenters y billones de filas de bases de datos.

Las aplicaciones pueden usar Spanner para alta disponibilidad, incluso ante desastres naturales de
área extensa, replicando sus datos dentro o incluso a través de continentes. F1, un sistema de base
de datos relacional distribuido de Google para respaldar el negocio de AdWords, se basa en
Spanner. F1 utiliza cinco réplicas repartidas por los Estados Unidos. La mayoría de las otras
aplicaciones probablemente replicarán sus datos en 3 a 5 datacenters en una región geográfica,
pero con modos de fallos relativamente independientes. Es decir, la mayoría de las aplicaciones
elegirán una latencia más baja en lugar de una mayor disponibilidad, siempre que puedan
sobrevivir a 1 o 2 fallas del datacenter.

El enfoque principal de Spanner es administrar los datos replicados entre los datacenters, pero
también hemos dedicado mucho tiempo a diseñar e implementar características importantes de la
base de datos en la parte superior de nuestra infraestructura de sistemas distribuidos. A pesar de
que muchos proyectos utilizan Bigtable sin ningún problema [9], también hemos recibido
constantemente quejas de los usuarios de que Bigtable puede ser difícil de usar para algunos tipos
de aplicaciones: aquellas que tienen esquemas complejos y evolutivos, o aquellas que desean una
fuerte consistencia en presencia de replicación de área amplia. (Afirmaciones similares han sido
hechas por otros autores [37].) Muchas aplicaciones en Google han optado por usar Megastore [5]
debido a su modelo de datos semi-relacionales y soporte para replicación sincrónica, a pesar de su
relativamente bajo rendimiento de escritura. Como consecuencia, Spanner ha evolucionado desde
un almacén clave-valor versionado similar a Bigtable a una base de datos temporal de múltiples
versiones. Los datos se almacenan en tablas semi-relacionales esquematizadas; los datos se
versionan y cada versión se marca automáticamente con su tiempo de confirmación (commit time);
versiones anteriores de los datos están sujetos a políticas configurables de recolección de basura; y
las aplicaciones pueden leer datos con marcas de tiempo antiguas. Spanner admite transacciones de
propósito general y proporciona un lenguaje de consulta basado en SQL.

Como una base de datos distribuida globalmente, Spanner ofrece varias características interesantes.
Primero, las aplicaciones pueden controlar dinámicamente las configuraciones de replicación para
datos. Las aplicaciones pueden especificar restricciones para controlar qué datacenters contienen
qué datos, qué tan lejos están los datos de sus usuarios (para controlar la latencia de lectura), qué
tan lejos están las réplicas entre sí (para controlar la latencia de escritura) y cuántas réplicas se
mantienen (para controlar la durabilidad, disponibilidad y rendimiento de lectura). El sistema
también puede mover datos de forma dinámica y transparente entre datacenters para equilibrar el
uso de recursos en los datacenters. En segundo lugar, Spanner tiene dos características que son
difíciles de implementar en una base de datos distribuida: proporciona lecturas y escrituras
externamente consistentes [16] y lecturas consistentes globalmente en la base de datos en una
marca de tiempo. Estas características permiten a Spanner admitir copias de seguridad consistentes,
ejecuciones MapReduce consistentes [12] y actualizaciones de esquemas atómicos, todo a escala
global e incluso en presencia de transacciones en curso.

Estas características están habilitadas por el hecho de que Spanner asigna marcas de tiempo de
confirmación globalmente significativas a las transacciones, aunque las transacciones se puedan
distribuir. Las marcas de tiempo reflejan el orden de serialización. Además, el orden de serialización
satisface la consistencia externa (o, de manera equivalente, la linealizabilidad [20]): si una transacción
T1 se confirma antes de que comience otra transacción T2, la marca de tiempo de confirmación de
T1 es menor que la de T2. Spanner es el primer sistema en proporcionar tales garantías a escala
global.

El habilitador clave (key enabler) de estas propiedades es una nueva API TrueTime y su
implementación. La API expone directamente la incertidumbre del reloj, y las garantías en las marcas
de tiempo de Spanner dependen de los límites que proporciona la implementación. Si la
incertidumbre es grande, Spanner disminuye la velocidad para esperar esa incertidumbre. El
software de administración de clústeres de Google proporciona una implementación de la API
TrueTime. Esta implementación mantiene la incertidumbre pequeña (generalmente menos de 10 ms)
mediante el uso de múltiples referencias de reloj modernas (GPS y relojes atómicos).

La Sección 2 describe la estructura de la implementación de Spanner, su conjunto de características


y las decisiones de ingeniería que se incluyeron en su diseño. La Sección 3 describe nuestra nueva
API TrueTime y esboza su implementación. La Sección 4 describe cómo Spanner utiliza TrueTime para
implementar transacciones distribuidas externamente consistentes, transacciones de solo lectura sin
bloqueo y actualizaciones de esquemas atómicos. La Sección 5 proporciona algunos puntos de
referencia sobre el rendimiento de Spanner y el comportamiento de TrueTime, y analiza las
experiencias de F1. Las secciones 6, 7 y 8 describen trabajos relacionados y futuros, y resumen
nuestras conclusiones.

2. Implementación.
Esta sección describe la estructura y el fundamento de la implementación de Spanner. Luego describe
la abstracción directory, que se utiliza para administrar la replicación y la localidad, y es la unidad de
movimiento de datos. Finalmente, describe nuestro modelo de datos, por qué Spanner parece una
base de datos relacional en lugar de un almacén clave-valor y cómo las aplicaciones pueden controlar
la localidad de los datos.

Una implementación de Spanner es llamada universo. Dado que Spanner administra datos
globalmente, solo habrá un puñado de universos en ejecución. Actualmente ejecutamos un universo
de prueba/playground, un universo de desarrollo/producción y un universo solo de producción.

Spanner está organizado como un conjunto de zonas, donde cada zona es el análogo aproximado de
una implementación de servidores Bigtable [9]. Las zonas son la unidad de implementación
administrativa. El conjunto de zonas también es el conjunto de ubicaciones en las que se pueden
replicar los datos. Se pueden agregar o eliminar zonas de un sistema en ejecución a medida que se
ponen en servicio nuevos datacenters y se apagan los antiguos, respectivamente. Las zonas también
son la unidad de aislamiento físico: puede haber una o más zonas en un datacenter, por ejemplo, si
los datos de diferentes aplicaciones deben dividirse en diferentes conjuntos de servidores en el
mismo datacenter.

Figura 1. Organización del servidor Spanner.


La Figura 1 ilustra los servidores en un universo Spanner. Una zona tiene una zonemaster y entre cien
y varios miles de spanservers. El primero asigna datos a los spanservers; los últimos sirven datos a los
clientes. Los clientes utilizan los location proxies por zona para localizar los spanservers asignados
para servir sus datos. El universemaster y el placement driver son actualmente singletons. El universo
maestro (universemaster) es principalmente una consola que muestra información de estado sobre
todas las zonas para la depuración interactiva. El controlador de ubicación (placement driver) maneja
el movimiento automatizado de datos entre zonas en una escala de tiempo de minutos. El
controlador de ubicación se comunica periódicamente con los spanservers para encontrar datos que
se deben mover, ya sea para cumplir con las restricciones de replicación actualizadas o para equilibrar
la carga. Por razones de espacio, solo describiremos el spanserver en detalle.

2.1. Pila de software del Spanserver

Figura 2. Pila de software del Spanserver

Esta sección se centra en la implementación del spanserver para ilustrar cómo la replicación y las
transacciones distribuidas se han superpuesto en nuestra implementación basada en Bigtable. La pila
de software se muestra en la Figura 2. En la parte inferior, cada spanserver es responsable de entre
100 y 1000 instancias de una estructura de datos llamada tablet. Una tableta (tablet) es similar a la
abstracción de tableta de Bigtable, ya que implementa un bag de las siguientes asignaciones:

(clave:string, timestamp:int64) -> string

A diferencia de Bigtable, Spanner asigna marcas de tiempo a los datos, la cual es una forma
importante en la que Spanner se parece más a una base de datos de múltiples versiones que a un
almacén clave-valor. El estado de una tableta se almacena en un conjunto de archivos en forma de
árbol-B y un registro de escritura anticipada, todo en un sistema de archivos distribuido llamado
Colossus (el sucesor del sistema de archivos de Google, GFS [15]).

Para admitir la replicación, cada spanserver implementa una única máquina de estado de Paxos en
la parte superior de cada tableta. (Una encarnación temprana de Spanner admitía múltiples
máquinas de estado de Paxos por tableta, lo que permitió configuraciones de replicación más
flexibles. La complejidad de ese diseño nos llevó a abandonarlo). Cada máquina de estado almacena
sus metadatos y accede a su tableta correspondiente. Nuestra implementación de Paxos respalda a
los líderes de larga duración con arrendamientos de líderes basados en el tiempo, cuya duración
predeterminada es de 10 segundos. La implementación actual de Spanner registra cada escritura de
Paxos dos veces: una en el registro de la tableta y otra en el registro de Paxos. Esta elección se tomó
por conveniencia, y es probable que lo solucionemos eventualmente. Nuestra implementación de
Paxos está canalizada, para mejorar el rendimiento de Spanner en presencia de latencias WAN; pero
las escrituras son aplicadas por Paxos en orden (un hecho del cual dependemos en la Sección 4).

Las máquinas de estado de Paxos se utilizan para implementar un bag de mapeos o asignaciones que
se replica de manera consistente. El estado de asignación de clave-valor de cada réplica se almacena
en su tableta correspondiente. Las escrituras deben iniciar el protocolo de Paxos en el líder; las
lecturas acceden al estado directamente desde la tableta subyacente en cualquier réplica que esté
suficientemente actualizada. El conjunto de réplicas es colectivamente un Paxos group (grupo Paxos).

En cada réplica que es un líder, cada spanserver implementa un lock table (tabla de bloqueo) para
implementar el control de concurrencia. La tabla de bloqueo contiene el estado del bloqueo de dos
fases: asigna rangos de claves a estados de bloqueo. (Tenga en cuenta que tener un líder de Paxos
de larga duración es fundamental para administrar de manera eficiente la tabla de bloqueo). Tanto
en Bigtable como en Spanner, diseñamos para transacciones de larga duración (por ejemplo, para la
generación de informes, que pueden tardar unos minutos), que funcionan mal bajo un control de
concurrencia optimista en presencia de conflictos. Las operaciones que requieren sincronización,
como las lecturas transaccionales, adquieren bloqueos en la tabla de bloqueos; otras operaciones
omiten la tabla de bloqueo.

En cada réplica que es líder, cada spanserver también implementa un transaction manager
(administrador de transacciones) para admitir transacciones distribuidas. El administrador de
transacciones se utiliza para implementar un participant leader (líder participante); las otras réplicas
del grupo se denominarán participant slaves (esclavos participantes). Si una transacción involucra
solo a un grupo de Paxos (como es el caso de la mayoría de las transacciones), puede pasar por alto
el administrador de transacciones, ya que la tabla de bloqueo y Paxos juntos brindan
transaccionalidad. Si una transacción involucra a más de un grupo de Paxos, los líderes de esos grupos
se coordinan para realizar una confirmación en dos fases. Uno de los grupos participantes se elige
como coordinador: el líder participante de ese grupo se denominará coordinator leader (líder
coordinador) y los esclavos de ese grupo como coordinator slaves (esclavos coordinadores). El estado
de cada administrador de transacciones se almacena en el grupo Paxos subyacente (y por lo tanto se
replica).

2.2. Directorios y ubicación.

Además de la bolsa de asignaciones de clave-valor, la implementación de Spanner admite una


abstracción de agrupamiento llamada directory (directorio), que es un conjunto de claves contiguas
que comparten un prefijo común. (La elección del término directory es un accidente histórico; un
término mejor podría ser bucket, cubo). Explicaremos la fuente de ese prefijo en la Sección 2.3. Los
directorios compatibles permiten que las aplicaciones controlen la ubicación de sus datos eligiendo
las claves con cuidado.

Figura 3: Los directorios son la unidad de movimiento de datos entre los grupos de Paxos.

Un directorio es la unidad de ubicación de datos. Todos los datos de un directorio tienen la misma
configuración de replicación. Cuando los datos se mueven entre grupos de Paxos, se mueven
directorio por directorio, como se muestra en la Figura 3. Spanner podría mover un directorio para
eliminar la carga de un grupo de Paxos; poner directorios a los que se accede con frecuencia juntos
en el mismo grupo; o mover un directorio a un grupo que esté más cerca de sus accesos. Los
directorios se pueden mover mientras las operaciones del cliente están en curso. Se podría esperar
que un directorio de 50 MB se pueda mover en unos pocos segundos.

El hecho de que un grupo de Paxos pueda contener múltiples directorios implica que una tableta
Spanner es diferente de una tableta Bigtable: la primera no es necesariamente una única partición
lexicográficamente contigua del espacio de filas. En cambio, una tableta Spanner es un contenedor
que puede encapsular múltiples particiones del espacio de filas. Tomamos esta decisión para que
fuera posible colocar varios directorios a los que se accede con frecuencia juntos.

Movedir es la tarea en segundo plano que se utiliza para mover directorios entre grupos de Paxos
[14]. Movedir también se usa para agregar o eliminar réplicas a grupos de Paxos [25], porque
Spanner aún no admite cambios de configuración en Paxos. Movedir no se implementa como una
única transacción, para evitar bloquear las lecturas y escrituras en curso en un movimiento de datos
voluminoso. En cambio, movedir registra el hecho de que está comenzando a mover datos y mueve
los datos en segundo plano. Cuando ha movido todos los datos excepto una cantidad nominal, utiliza
una transacción para mover atómicamente esa cantidad nominal y actualizar los metadatos de los
dos grupos de Paxos.

Un directorio es también la unidad más pequeña cuyas propiedades de replicación geográfica (o


placement, ubicación, para abreviar) pueden ser especificadas por una aplicación. El diseño de
nuestro lenguaje de especificación de ubicación separa las responsabilidades para administrar las
configuraciones de replicación. Los administradores controlan dos dimensiones: el número y los tipos
de réplicas, y la ubicación geográfica de esas réplicas. Crean un menú de opciones nombradas en
estas dos dimensiones (por ejemplo, Norteamérica, replicado de 5 formas con 1 testigo). Una
aplicación controla cómo se replican los datos, etiquetando cada base de datos y/o directorios
individuales con una combinación de esas opciones. Por ejemplo, una aplicación podría almacenar
los datos de cada usuario final en su propio directorio, lo que permitiría que los datos del usuario A
tuvieran tres réplicas en Europa y los datos del usuario B tuvieran cinco réplicas en Norteamérica.

Para mayor claridad expositiva, hemos simplificado demasiado. De hecho, Spanner fragmentará un
directorio en varios fragmentos si crece demasiado. Los fragmentos pueden ser servidos desde
diferentes grupos de Paxos (y por lo tanto diferentes servidores). Movedir en realidad mueve
fragmentos, y no directorios completos, entre grupos.

2.3. Modelo de datos

Spanner expone el siguiente conjunto de características de datos a las aplicaciones: un modelo de


datos basado en tablas semi-relacionales esquematizadas, un lenguaje de consulta y transacciones
de propósito general. El movimiento hacia el soporte de estas características fue impulsado por
muchos factores. La necesidad de soportar tablas semi-relacionales esquematizadas y replicación
síncrona está respaldada por la popularidad de Megastore [5]. Al menos 300 aplicaciones de Google
utilizan Megastore (a pesar de su rendimiento relativamente bajo) porque su modelo de datos es
más sencillo de administrar que el de Bigtable y porque admite la replicación sincrónica en los
datacenters. (Bigtable solo admite la replicación eventualmente consistente en todos los
datacenters). Ejemplos de aplicaciones de Google conocidas que usan Megastore son Gmail, Picasa,
Calendar, Android. Market y AppEngine. La necesidad de soportar un lenguaje de consulta similar a
SQL en Spanner también fue clara, dada la popularidad de Dremel [28] como herramienta interactiva
de análisis de datos. Finalmente, la falta de transacciones entre filas en Bigtable generó quejas
frecuentes; Percolador [32] fue construido en parte para abordar esta falla. Algunos autores han
afirmado que la confirmación general de dos fases es demasiado cara de soportar, debido a los
problemas de rendimiento o disponibilidad que conlleva [9, 10, 19]. Creemos que es mejor que los
programadores de aplicaciones se ocupen de los problemas de rendimiento debido al uso excesivo
de transacciones a medida que surgen cuellos de botella, en lugar de codificar siempre en torno a la
falta de transacciones. La ejecución de una confirmación de dos fases sobre Paxos mitiga los
problemas de disponibilidad.

El modelo de datos de la aplicación se superpone a las asignaciones de clave-valor agrupadas en


directorios que admite la implementación. Una aplicación crea una o más bases de datos en un
universo. Cada base de datos puede contener un número ilimitado de tablas esquematizadas. Las
tablas se ven como tablas de bases de datos relacionales, con filas, columnas y valores versionados.
No entraremos en detalles sobre el lenguaje de consulta de Spanner. Se parece a SQL con algunas
extensiones para admitir campos con valores de búfer de protocolo.
El modelo de datos de Spanner no es puramente relacional, ya que las filas deben tener nombres.
Más precisamente, se requiere que cada tabla tenga un conjunto ordenado de una o más columnas
de clave primaria. Este requisito es donde Spanner todavía parece un almacén de clave-valor: las
claves primarias forman el nombre de una fila, y cada tabla define una asignación de las columnas de
clave primaria a las columnas de clave no primaria. Una fila solo tiene existencia si se define algún
valor (incluso si es NULL) para las claves de la fila. La imposición de esta estructura es útil porque
permite que las aplicaciones controlen la localidad de los datos a través de sus elecciones de claves.
CREATE TABLE Users {
uid INT64 NOT NULL, email STRING
} PRIMARY KEY (uid), DIRECTORY;

CREATE TABLE Albums {


uid INT64 NOT NULL, aid INT64 NOT NULL,
name STRING
} PRIMARY KEY (uid, aid),
INTERLEAVE IN PARENT Users ON DELETE CASCADE;

Figura 4: Ejemplo de esquema de Spanner para metadatos de fotografías y el entrelazado que


implica INTERLEAVE IN

La Figura 4 contiene un ejemplo de esquema de Spanner para almacenar metadatos de fotografías


por usuario y por álbum. El lenguaje de esquema es similar al de Megastore, con el requisito adicional
de que cada base de datos de Spanner debe ser particionada por los clientes en una o más jerarquías
de tablas. Las aplicaciones cliente declaran las jerarquías en los esquemas de la base de datos
mediante las declaraciones INTERLEAVE IN. La tabla en la parte superior de una jerarquía es un
directory table (tabla de directorio). Cada fila de una tabla de directorio con la clave K, junto con
todas las filas de las tablas descendientes que comienzan con K en orden lexicográfico, forman un
directorio. ON DELETE CASCADE dice que eliminar una fila en la tabla de directorio elimina cualquier
fila secundaria (hija) asociada. La figura también ilustra el diseño intercalado para la base de datos
de ejemplo: por ejemplo, Albums (2,1) representa la fila de la tabla Albums para user_id 2,
album_id 1. Este entrelazado de tablas para formar directorios es significativo porque permite a
los clientes para describir las relaciones de localidad que existen entre varias tablas, lo cual es
necesario para un buen rendimiento en una base de datos distribuida y fragmentada. Sin él, Spanner
no conocería las relaciones de localidad más importantes.

3. TrueTime.

Método Retorna
TT.now() TTinterval: [earliest, latest]
TT.after(t) true si t definitivamente ha pasado
TT.before(t) true si t definitivamente no ha llegado
Tabla 1: API TrueTime. El argumento t es de tipo TTstamp.

Esta sección describe la API TrueTime y esboza su implementación. Dejamos la mayoría de los detalles
para otro artículo: nuestro objetivo es demostrar el poder de tener una API de este tipo. La Tabla 1
enumera los métodos de la API. TrueTime representa explícitamente el tiempo como un TTinterval,
que es un intervalo con incertidumbre de tiempo limitado (a diferencia de las interfaces de tiempo
estándar que no dan a los clientes noción de incertidumbre). Los puntos finales de un TTinterval son
de tipo TTstamp. El método TT.now() devuelve un TTinterval que se garantiza que contiene el
tiempo absoluto durante el cual se invocó TT.now(). La época de tiempo es análoga al tiempo UNIX
con manchas de segundos intercalares (leap-second smearing). Defina el límite de error instantáneo
como 𝜖, que es la mitad del ancho del intervalo, y el límite de error promedio como 𝜖̅. Los métodos
TT.after() y TT.before() son envoltorios de conveniencia alrededor de TT.now().

Denote el tiempo absoluto de un evento 𝑒 con la función 𝑡𝑎𝑏𝑠 (𝑒). En términos más formales,
TrueTime garantiza que para una invocación tt = TT.now(), tt.earliest ≤ 𝐭 𝐚𝐛𝐬 (𝐞𝐧𝐨𝐰 ) ≤ tt.latest,
donde 𝒆𝒏𝒐𝒘 es el evento de invocación.

Las referencias de tiempo subyacentes utilizadas por TrueTime son GPS y relojes atómicos. TrueTime
usa dos formas de referencia de tiempo porque tienen diferentes modos de falla. Las
vulnerabilidades de la fuente de referencia de GPS incluyen fallas de antena y receptor, interferencia
de radio local, fallas correlacionadas (por ejemplo, fallas de diseño como manejo incorrecto de
segundo intercalar y falsificación) y cortes del sistema GPS. Los relojes atómicos pueden fallar de
formas no relacionadas con el GPS y entre sí, y durante largos períodos de tiempo pueden desviarse
significativamente debido a errores de frecuencia.

TrueTime se implementa mediante un conjunto de máquinas time master (maestras de tiempo) por
datacenter y un timeslave daemon (demonio de esclavo de tiempo) por máquina. La mayoría de los
maestros tienen receptores GPS con antenas dedicadas; estos maestros están separados físicamente
para reducir los efectos de fallas de antena, interferencias de radio y falsificación. Los maestros
restantes (a los que nos referimos como Armageddon masters o maestros del Armagedón) están
equipados con relojes atómicos. Un reloj atómico no es tan caro: el costo de un maestro de
Armagedón es del mismo orden que el de un maestro de GPS. Las referencias de tiempo de todos los
maestros se comparan regularmente entre sí. Cada maestro también verifica la velocidad a la que su
referencia avanza en el tiempo con su propio reloj local y se desaloja a sí mismo si existe una
divergencia sustancial. Entre sincronizaciones, los maestros de Armagedón anuncian una
incertidumbre temporal que aumenta lentamente y que se deriva de la desviación del reloj en el peor
de los casos aplicada de manera conservadora. Los maestros de GPS anuncian una incertidumbre que
suele ser cercana a cero.
Cada demonio sondea una variedad de maestros [29] para reducir la vulnerabilidad a errores de
cualquier maestro. Algunos son maestros de GPS elegidos de datacenters cercanos; el resto son
maestros de GPS de datacenters más lejanos, así como algunos maestros de Armagedón. Los
demonios aplican una variante del algoritmo de Marzullo [27] para detectar y rechazar a los
mentirosos y sincronizar los relojes de las máquinas locales con los que no son mentirosos. Para
protegerse contra relojes locales rotos, las máquinas que exhiben excursiones de frecuencia mayores
que el límite del peor de los casos derivado de las especificaciones de los componentes y el entorno
operativo son desalojadas.

Entre sincronizaciones, un demonio anuncia una incertidumbre de tiempo que aumenta lentamente.
𝜖 se deriva de la desviación del reloj local en el peor de los casos aplicada de forma conservadora. 𝜖
también depende de la incertidumbre del maestro de tiempo y del retraso de la comunicación con
los maestros de tiempo. En nuestro entorno de producción, 𝜖 es típicamente una función de diente
de sierra del tiempo, que varía de aproximadamente 1 a 7 ms en cada intervalo de sondeo. 𝜖̅ es por
tanto 4 ms la mayor parte del tiempo. El intervalo de sondeo del demonio es actualmente de 30
segundos y la tasa de deriva aplicada actual se establece en 200 microsegundos/segundo, que en
conjunto representan los límites del diente de sierra de 0 a 6 ms. El 1 ms restante proviene del retardo
de comunicación a los maestros de tiempo. Las excursiones desde este diente de sierra son posibles
en presencia de fallas. Por ejemplo, la indisponibilidad ocasional del maestro de tiempo puede causar
aumentos en 𝜖 en todo el datacenter. Del mismo modo, las máquinas y los enlaces de red
sobrecargados pueden provocar picos de 𝜖 localizados ocasionales.

4. Control de concurrencia.
En esta sección se describe cómo se usa TrueTime para garantizar las propiedades de corrección
en torno al control de concurrencia y cómo se usan esas propiedades para implementar
características como transacciones consistentes externamente, transacciones de solo lectura sin
bloqueo y lecturas sin bloqueo en el pasado. Estas características permiten, por ejemplo, la
garantía de que una auditoría de la base de datos completa leída en una marca de tiempo t verá
exactamente los efectos de cada transacción que se ha confirmado a partir de t.

En el futuro, será importante distinguir las escrituras como las ve Paxos (a las que nos referiremos
como escrituras de Paxos a menos que el contexto sea claro) de las escrituras del cliente de
Spanner. Por ejemplo, la confirmación en dos fases genera una escritura de Paxos para la fase de
preparación que no tiene una escritura de cliente Spanner correspondiente.

Discusión de
Control de
Operación la marca de Se requiere réplica
concurrencia
tiempo
Transacción de lectura y §4.1.2 pesimista Líder
escritura
Transacción de solo lectura §4.1.4 Libre de bloqueo líder para la marca de
tiempo; cualquiera para
leer, sujeto a §4.1.3
Lectura de instantánea, - Libre de bloqueo Cualquiera, sujeto a §4.1.3
marca de tiempo
proporcionada por el cliente
Lectura de instantánea, §4.1.3 Libre de bloqueo Cualquiera, sujeto a §4.1.3
encuadernada por el cliente
Tabla 2: Tipos de lecturas y escrituras en Spanner y cómo se comparan.

4.1. Gestión de marcas de tiempo


La Tabla 2 enumera los tipos de operaciones que admite Spanner. La implementación de Spanner
admite transacciones de lectura y escritura, transacciones de solo lectura (transacciones de
aislamiento de instantáneas declaradas previamente) y lecturas de instantáneas. Las escrituras
independientes se implementan como transacciones de lectura y escritura; Las lecturas
independientes que no son instantáneas se implementan como transacciones de solo lectura.
Ambos se reintentan internamente (los clientes no necesitan escribir sus propios bucles de
reintento).

Una transacción de solo lectura es un tipo de transacción que tiene los beneficios de rendimiento
del aislamiento de instantáneas [6]. Una transacción de solo lectura debe declararse previamente
como si no tuviera escrituras; no es simplemente una transacción de lectura y escritura sin
escrituras. Las lecturas en una transacción de solo lectura se ejecutan en una marca de tiempo
elegida por el sistema sin bloquear, de modo que las escrituras entrantes no se bloqueen. La
ejecución de las lecturas en una transacción de solo lectura puede continuar en cualquier réplica
que esté suficientemente actualizada (Sección 4.1.3).

Una lectura de instantánea es una lectura en el pasado que se ejecuta sin bloquearse. Un cliente
puede especificar una marca de tiempo para la lectura de una instantánea o proporcionar un
límite superior en la obsolescencia de la marca de tiempo deseada y permitir que Spanner elija
una marca de tiempo. En cualquier caso, la ejecución de una lectura de instantánea procede en
cualquier réplica que esté suficientemente actualizada.

Tanto para las transacciones de solo lectura como para las lecturas de instantáneas, la
confirmación es inevitable una vez que se ha elegido una marca de tiempo, a menos que los datos
de esa marca de tiempo hayan sido recolectados como basura. Como resultado, los clientes
pueden evitar almacenar en búfer los resultados dentro de un ciclo de reintento. Cuando falla un
servidor, los clientes pueden continuar internamente la consulta en un servidor diferente
repitiendo la marca de tiempo y la posición de lectura actual.

4.1.1. Arrendamientos de Líder de Paxos


La implementación de Spanner en Paxos utiliza arrendamiento cronometrados para hacer que el
liderazgo sea duradero (10 segundos por defecto). Un líder potencial envía solicitudes de lease
votes (votos de arrendamiento) cronometrados; al recibir un quórum de votos de arrendamiento,
el líder sabe que tiene un arrendamiento. Una réplica extiende su voto de arrendamiento
implícitamente en una escritura exitosa, y el líder solicita extensiones de voto de arrendamiento
si están cerca de su vencimiento. Define el lease interval (intervalo de arrendamiento) de un líder
como que comienza cuando descubre que tiene un quórum de votos de arrendamiento y finaliza
cuando ya no tiene quórum de votos de arrendamiento (porque algunos han expirado). Spanner
depende de la siguiente invariante de disyunción: para cada grupo de Paxos, el intervalo de
arrendamiento de cada líder de Paxos es disjunto del de todos los demás líderes. El Apéndice A
describe cómo se aplica este invariante.

La implementación de Spanner permite a un líder de Paxos abdicar liberando a sus esclavos de


sus votos de arrendamiento. Para preservar el invariante de disyunción, Spanner restringe cuándo
la abdicación está permitida. Define 𝑠𝑚𝑎𝑥 para que sea la marca de tiempo máxima utilizada por
un líder. Las secciones siguientes describirán cuándo se avanza 𝑠𝑚𝑎𝑥 . Antes de abdicar, un líder
debe esperar hasta que TT.after (𝑠𝑚𝑎𝑥 ) sea verdadero (true).

4.1.2. Asignación de marcas de tiempo a transacciones RW


Las lecturas y escrituras transaccionales utilizan el bloqueo de dos fases. Como resultado, se les
pueden asignar marcas de tiempo en cualquier momento cuando se hayan adquirido todos los
bloqueos, pero antes de que se hayan liberado los bloqueos. Para una transacción determinada,
Spanner le asigna la marca de tiempo que Paxos asigna a la escritura de Paxos que representa la
confirmación de la transacción.

Spanner depende de la siguiente invariante de monotonicidad: dentro de cada grupo de Paxos,


Spanner asigna marcas de tiempo a las escrituras de Paxos en un orden monótonamente
creciente, incluso entre líderes. Una única réplica de líder puede asignar trivialmente marcas de
tiempo en orden monótonamente creciente. Este invariante se aplica en todos los líderes
haciendo uso de la invariante de disyunción: un líder solo debe asignar marcas de tiempo dentro
del intervalo de su arrendamiento de líder. Tenga en cuenta que cada vez que se asigna una marca
de tiempo 𝑠, 𝑠𝑚𝑎𝑥 avanza a 𝑠 para preservar la disyunción.

Spanner también aplica la siguiente invariante de consistencia externa: si el inicio de una


transacción T2 ocurre después de la confirmación de una transacción T1, entonces la marca de
tiempo de confirmación de T2 debe ser mayor que la marca de tiempo de confirmación de T1.
Defina los eventos de inicio y confirmación para una transacción 𝑇𝑖 mediante 𝑒𝑖𝑖𝑛𝑖𝑐𝑖𝑜 y
𝑒𝑖𝑐𝑜𝑛𝑓𝑖𝑟𝑚𝑎𝑐𝑖ó𝑛 ; y la marca de tiempo de confirmación de una transacción 𝑇𝑖 por 𝑠𝑖 . El invariante se
vuelve en 𝑡𝑎𝑏𝑠 (𝑒1𝑐𝑜𝑛𝑓𝑖𝑟𝑚𝑎𝑐𝑖ó𝑛 ) < 𝑡𝑎𝑏𝑠 (𝑒2𝑖𝑛𝑖𝑐𝑖𝑜 ) ⇒ 𝑠1 < 𝑠2 . El protocolo para ejecutar
transacciones y asignar marcas de tiempo obedece a dos reglas, que juntas garantizan este
invariante, como se muestra a continuación. Defina el evento de llegada de la solicitud de
confirmación en el líder del coordinador para que una escritura 𝑇𝑖 sea 𝑒𝑖𝑠𝑒𝑟𝑣𝑖𝑑𝑜𝑟 .

Inicio El líder coordinador para una escritura 𝑇𝑖 asigna una marca de tiempo de confirmación 𝑠𝑖 no
menor que el valor de TT.now().latest, calculado después de 𝑒𝑖𝑠𝑒𝑟𝑣𝑖𝑑𝑜𝑟 . Tenga en cuenta que los
líderes participantes no importan aquí; la Sección 4.2.1 describe cómo están involucrados en la
implementación de la siguiente regla.
Espera de confirmación El líder coordinador se asegura de que los clientes no puedan ver ningún
dato confirmado por 𝑇𝑖 hasta que TT.after(𝑠𝑖 ) sea verdadero (true). La espera de confirmación
asegura que 𝑠𝑖 es menor que el tiempo de confirmación absoluto de 𝑇𝑖 , o 𝑠𝑖 <
𝑐𝑜𝑛𝑓𝑖𝑟𝑚𝑎𝑐𝑖ó𝑛
𝑡𝑎𝑏𝑠 (𝑒𝑖 ). La implementación de la espera de confirmación se describe en la Sección
4.2.1. Prueba:

𝑠1 < 𝑡𝑎𝑏𝑠 …(espera de confirmación)


𝑡𝑎𝑏𝑠 (𝑒1𝑐𝑜𝑛𝑓𝑖𝑟𝑚𝑎𝑐𝑖ó𝑛 ) < 𝑡𝑎𝑏𝑠 (𝑒2𝑖𝑛𝑖𝑐𝑖𝑜 ) …(suposición)
𝑡𝑎𝑏𝑠 (𝑒2𝑖𝑛𝑖𝑐𝑖𝑜 ) ≤ 𝑡𝑎𝑏𝑠 (𝑒2𝑠𝑒𝑟𝑣𝑖𝑑𝑜𝑟 ) …(causalidad)
𝑡𝑎𝑏𝑠 (𝑒2𝑠𝑒𝑟𝑣𝑖𝑑𝑜𝑟 ) ≤ 𝑠2 …(inicio)
𝑠1 < 𝑠2 …(transitividad)

4.1.3. Publicación de lecturas en una marca de tiempo


El invariante de monotonicidad descrito en la Sección 4.1.2 permite a Spanner determinar
correctamente si el estado de una réplica está lo suficientemente actualizado para satisfacer una
lectura. Cada réplica rastrea un valor llamado safe time (tiempo seguro) 𝑡𝑠𝑒𝑔𝑢𝑟𝑜 , que es la marca
de tiempo máxima en la que una réplica está actualizada. Una réplica puede satisfacer una lectura
en una marca de tiempo t si 𝑡 ≤ 𝑡𝑠𝑒𝑔𝑢𝑟𝑜 .

𝑃𝑎𝑥𝑜𝑠 𝑇𝑀 ), donde cada máquina de estado de Paxos tiene un tiempo


Defina 𝑡𝑠𝑒𝑔𝑢𝑟𝑜 = 𝑚𝑖𝑛(𝑡𝑠𝑒𝑔𝑢𝑟𝑜 , 𝑡𝑠𝑒𝑔𝑢𝑟𝑜
𝑃𝑎𝑥𝑜𝑠 𝑇𝑀 𝑃𝑎𝑥𝑜𝑠
seguro 𝑡𝑠𝑒𝑔𝑢𝑟𝑜 y cada administrador de transacciones tiene un tiempo seguro 𝑡𝑠𝑒𝑔𝑢𝑟𝑜 . 𝑡𝑠𝑒𝑔𝑢𝑟𝑜 es
más simple: es la marca de tiempo de la escritura de Paxos más aplicada. Debido a que las marcas
de tiempo aumentan de manera monótona y las escrituras se aplican en orden, las escrituras ya
𝑃𝑎𝑥𝑜𝑠
no ocurrirán en o por debajo de 𝑡𝑠𝑒𝑔𝑢𝑟𝑜 con respecto a Paxos.

𝑇𝑀
𝑡𝑠𝑒𝑔𝑢𝑟𝑜 es ∞ en una réplica si no hay transacciones preparadas (pero no confirmadas), es decir,
transacciones entre las dos fases de la confirmación en dos fases. (Para un esclavo participante,
𝑇𝑀
𝑡𝑠𝑒𝑔𝑢𝑟𝑜 en realidad se refiere al administrador de transacciones del líder de la réplica, cuyo estado
el esclavo puede inferir a través de los metadatos transmitidos en las escrituras de Paxos). Si
existen tales transacciones, entonces el estado afectado por esas transacciones es indeterminado:
una réplica del participante aún no sabe si dichas transacciones se confirmarán. Como discutimos
en la Sección 4.2.1, el protocolo de confirmación asegura que cada participante conozca un límite
inferior en la marca de tiempo de una transacción preparada. Cada líder participante (para un
𝑝𝑟𝑒𝑝𝑎𝑟𝑎𝑐𝑖ó𝑛
grupo g) para una transacción 𝑇𝑖 asigna una marca de tiempo de preparación 𝑠𝑖,𝑔 a su
registro de preparación. El líder coordinador se asegura de que la marca de tiempo de
𝑝𝑟𝑒𝑝𝑎𝑟𝑎𝑐𝑖ó𝑛
confirmación de la transacción 𝑠𝑖 ≥ 𝑠𝑖,𝑔 sobre todos los grupos de participantes g. Por lo
𝑇𝑀
tanto, para cada réplica en un grupo g, sobre todas las transacciones 𝑇𝑖 preparadas en g, 𝑡𝑠𝑒𝑔𝑢𝑟𝑜 =
𝑝𝑟𝑒𝑝𝑎𝑟𝑎𝑐𝑖ó𝑛
𝑚𝑖𝑛𝑖 (𝑠𝑖,𝑔 ) − 1 sobre todas las transacciones preparadas en g.

4.1.4. Asignación de marcas de tiempo a transacciones de RO


Una transacción de solo lectura se ejecuta en dos fases: asigna una marca de tiempo 𝑠𝑙𝑒𝑐𝑡𝑢𝑟𝑎 [8]
y luego ejecuta las lecturas de la transacción como lecturas instantáneas en 𝑠𝑙𝑒𝑐𝑡𝑢𝑟𝑎 . Las lecturas
de instantáneas se pueden ejecutar en cualquier réplica que esté suficientemente actualizada.

La simple asignación de 𝑠𝑙𝑒𝑐𝑡𝑢𝑟𝑎 = 𝑇𝑇. 𝑛𝑜𝑤( ). 𝑙𝑎𝑡𝑒𝑠𝑡, en cualquier momento después del inicio
de una transacción, preserva la consistencia externa mediante un argumento análogo al
presentado para escrituras en la Sección 4.1.2. Sin embargo, tal marca de tiempo puede requerir
la ejecución de las lecturas de datos en 𝑠𝑙𝑒𝑐𝑡𝑢𝑟𝑎 para bloquear si 𝑡𝑠𝑒𝑔𝑢𝑟𝑜 no ha avanzado lo
suficiente. (Además, tenga en cuenta que la elección de un valor de 𝑠𝑙𝑒𝑐𝑡𝑢𝑟𝑎 también puede hacer
avanzar 𝑠𝑚𝑎𝑥 para preservar la disyunción). Para reducir las posibilidades de bloqueo, Spanner
debe asignar la marca de tiempo más antigua que conserve la consistencia externa. La sección
4.2.2 explica cómo se puede elegir dicha marca de tiempo.

4.2. Detalles
Esta sección explica algunos de los detalles prácticos de las transacciones de lectura-escritura y
las transacciones de solo lectura eludidas anteriormente, así como la implementación de un tipo
de transacción especial que se usa para implementar cambios de esquema atómico. Luego
describe algunos refinamientos de los esquemas básicos como se describe.

4.2.1. Transacciones de lectura y escritura (RW)


Al igual que Bigtable, las escrituras que ocurren en una transacción se almacenan en búfer en el
cliente hasta que se confirman. Como resultado, las lecturas de una transacción no ven los efectos
de las escrituras de la transacción. Este diseño funciona bien en Spanner porque una lectura
devuelve las marcas de tiempo de cualquier lectura de datos, y las escrituras no confirmadas aún
no tienen marcas de tiempo asignadas.

Las lecturas dentro de las transacciones de lectura y escritura utilizan wode-wait (herida-espera)
[33] para evitar interbloqueos. El cliente emite lecturas a la réplica del líder del grupo apropiado,
que adquiere bloqueos de lectura y luego lee los datos más recientes. Mientras la transacción de
un cliente permanece abierta, envía mensajes keepalive para evitar que los líderes participantes
agoten el tiempo de su transacción. Cuando un cliente ha completado todas las lecturas y
almacenado en búfer todas las escrituras, comienza la confirmación en dos fases. El cliente elige
un grupo de coordinadores y envía un mensaje de confirmación al líder de cada participante con
la identidad del coordinador y cualquier escritura almacenada. Hacer que el cliente controle la
confirmación en dos fases evita el envío de datos dos veces a través de enlaces de área amplia.

Un líder participante no coordinador primero adquiere bloqueos de escritura. Luego elige una
marca de tiempo de preparación que debe ser más grande que cualquier marca de tiempo que
haya asignado a transacciones anteriores (para preservar la monotonicidad) y registra un registro
de preparación a través de Paxos. Luego, cada participante notifica al coordinador de su marca de
tiempo de preparación.

El líder coordinador también adquiere primero los bloqueos de escritura, pero se salta la fase de
preparación. Elige una marca de tiempo para toda la transacción después de escuchar a todos los
demás líderes participantes. La marca de tiempo de confirmación s debe ser mayor o igual a todas
las marcas de tiempo de preparación (para satisfacer las restricciones discutidas en la Sección
4.1.3), mayor que TT.now().latest en el momento en que el coordinador recibió su mensaje de
confirmación, y mayor que cualquier marca de tiempo que el líder haya asignado a transacciones
anteriores (nuevamente, para preservar la monotonicidad). El líder coordinador luego registra un
registro de confirmación a través de Paxos (o un aborto si se agotó el tiempo mientras esperaba
a los otros participantes).

Antes de permitir que cualquier réplica de coordinador aplique el registro de confirmación, el líder
del coordinador espera hasta TT.after(s), para obedecer la regla de espera de confirmación
descrita en la Sección 4.1.2. Debido a que el líder coordinador eligió s basado en TT.now().latest,
y ahora espera hasta que se garantice que la marca de tiempo está en el pasado, la espera
esperada es de al menos 2 ∗ 𝜖̅. Esta espera generalmente se superpone con la comunicación de
Paxos. Después de la espera de confirmación, el coordinador envía la marca de tiempo de
confirmación al cliente y a todos los demás líderes participantes. Cada líder participante registra
el resultado de la transacción a través de Paxos. Todos los participantes aplican en la misma marca
de tiempo y luego liberan bloqueos.

4.2.2. Transacciones de solo lectura (RO)


La asignación de una marca de tiempo requiere una fase de negociación entre todos los grupos
de Paxos que participan en las lecturas. Como resultado, Spanner requiere una expresión de
alcance (scope) para cada transacción de solo lectura, que es una expresión que resume las claves
que serán leídas por toda la transacción. Spanner infiere automáticamente el alcance de las
consultas independientes.

Si los valores del alcance son servidos por un solo grupo de Paxos, entonces el cliente emite la
transacción de solo lectura al líder de ese grupo. (La implementación actual de Spanner solo elige
una marca de tiempo para una transacción de solo lectura en un líder de Paxos). Ese líder asigna
𝑠𝑙𝑒𝑐𝑡𝑢𝑟𝑎 y ejecuta la lectura. Para una lectura de un solo sitio, Spanner generalmente funciona
mejor que TT.now().latest. Define LastTS() para que sea la marca de tiempo de la última escritura
de confirmación en un grupo de Paxos. Si no hay transacciones preparadas, la asignación 𝑠𝑙𝑒𝑐𝑡𝑢𝑟𝑎 =
LastTS() satisface trivialmente la consistencia externa: la transacción verá el resultado de la última
escritura y, por lo tanto, se ordenará después de ella.

Si los valores del alcance son servidos por varios grupos de Paxos, hay varias opciones. La opción
más complicada es hacer una ronda de comunicación con todos los líderes de los grupos para
negociar 𝑠𝑙𝑒𝑐𝑡𝑢𝑟𝑎 basado en LastTS(). Spanner actualmente implementa una opción más simple.
El cliente evita una ronda de negociación y solo hace que sus lecturas se ejecuten en 𝑠𝑙𝑒𝑐𝑡𝑢𝑟𝑎 =
TT.now().latest (que puede esperar el tiempo seguro para avanzar). Todas las lecturas de la
transacción se pueden enviar a réplicas que estén suficientemente actualizadas.

4.2.3. Transacciones de cambio de esquema


TrueTime permite a Spanner admitir cambios de esquema atómico. No sería factible utilizar una
transacción estándar, porque el número de participantes (el número de grupos en una base de
datos) podría ser de millones. Bigtable admite cambios de esquema atómico en un datacenter,
pero sus cambios de esquema bloquean todas las operaciones.

Una transacción de cambio de esquema de Spanner es generalmente una variante sin bloqueo de
una transacción estándar. Primero, se le asigna explícitamente una marca de tiempo en el futuro,
que se registra en la fase de preparación. Como resultado, los cambios de esquema en miles de
servidores pueden completarse con una interrupción mínima de otra actividad concurrente. En
segundo lugar, las lecturas y escrituras, que dependen implícitamente del esquema, se
sincronizan con cualquier marca de tiempo de cambio de esquema registrada en el momento t:
pueden continuar si sus marcas de tiempo preceden a t, pero deben bloquearse detrás de la
transacción de cambio de esquema si sus marcas de tiempo son posteriores a t. Sin TrueTime,
definir el cambio de esquema para que suceda en t no tendría sentido.

4.2.4. Refinamientos
𝑇𝑀
𝑡𝑠eguro como se define arriba tiene una debilidad, ya que una sola transacción preparada evita
que 𝑡𝑠𝑒𝑔𝑢𝑟𝑜 avance. Como resultado, no se pueden realizar lecturas en marcas de tiempo
posteriores, incluso si las lecturas no entran en conflicto con la transacción. Estos falsos conflictos
𝑇𝑀
se pueden eliminar aumentando 𝑡𝑠𝑒𝑔𝑢𝑟𝑜 con una asignación detallada o de grano fino (fine-
grained) de rangos clave a marcas de tiempo de transacciones preparadas. Esta información se
puede almacenar en la tabla de bloqueo, que ya asigna rangos de claves a metadatos de bloqueo.
Cuando llega una lectura, solo es necesario compararla con el tiempo seguro detallado o de grano
fino (fine-grained) para los rangos de claves con los que la lectura entra en conflicto.

LastTS() como se define arriba tiene una debilidad similar: si una transacción se acaba de
confirmar, una transacción de solo lectura no conflictiva todavía debe asignarse un 𝑠𝑙𝑒𝑐𝑡𝑢𝑟𝑎 para
seguir esa transacción. Como resultado, la ejecución de la lectura podría retrasarse. Esta debilidad
se puede remediar de manera similar aumentando LastTS() con una asignación detallada o de
grano fino (fine-grained) de los rangos de claves a marcas de tiempo de confirmación en la tabla
de bloqueo. (Aún no hemos implementado esta optimización). Cuando llega una transacción de
solo lectura, su marca de tiempo se puede asignar tomando el valor máximo de LastTS() para los
rangos de claves con los que la transacción entra en conflicto, a menos que haya una transacción
preparada en conflicto (que se puede determinar a partir del tiempo seguro detallado o de grano
fino, fine-grained).

𝑃𝑎𝑥𝑜𝑠
𝑡𝑠𝑒𝑔𝑢𝑟𝑜 como se define arriba tiene una debilidad en el sentido de que no puede avanzar en
ausencia de escrituras de Paxos. Es decir, una lectura de instantánea en t no se puede ejecutar en
grupos de Paxos cuya última escritura ocurrió antes de t. Spanner aborda este problema
aprovechando la desunión de los intervalos de arrendamiento de líder. Cada líder de Paxos avanza
𝑃𝑎𝑥𝑜𝑠
𝑡𝑠𝑒𝑔𝑢𝑟𝑜 manteniendo un umbral por encima del cual ocurrirán las marcas de tiempo de las
escrituras futuras: mantiene una asignación MinNextTS(n) del número de secuencia de Paxos n a
la marca de tiempo mínima que puede asignarse al número de secuencia de Paxos n + 1. Una
𝑃𝑎𝑥𝑜𝑠
réplica puede avanzar de 𝑡𝑠𝑒𝑔𝑢𝑟𝑜 a MinNextTS (n) - 1 cuando se ha aplicado a través de n.
Un solo líder puede hacer cumplir sus promesas MinNextTS() fácilmente. Debido a que las marcas
de tiempo prometidas por MinNextTS() se encuentran dentro del arrendamiento de un líder, el
invariante de desunión refuerza las promesas de MinNextTS() entre los líderes. Si un líder desea
avanzar MinNextTS() más allá del final de su arrendamiento de líder, primero debe extender su
arrendamiento. Tenga en cuenta que 𝑠𝑚𝑎𝑥 siempre avanza al valor más alto en MinNextTS() para
preservar la disyunción.

Un líder avanza por defecto los valores MinNextTS() cada 8 segundos. Por lo tanto, en ausencia
de transacciones preparadas, los esclavos sanos en un grupo Paxos inactivo pueden servir lecturas
en marcas de tiempo de más de 8 segundos en el peor de los casos. Un líder también puede
avanzar los valores de MinNextTS() a pedido de los esclavos.

5. Evaluación.
Primero medimos el rendimiento de Spanner con respecto a la replicación, las transacciones y la
disponibilidad. Luego proporcionamos algunos datos sobre el comportamiento de TrueTime y
un estudio de caso de nuestro primer cliente, F1.

Latencia (ms) Rendimiento (Kops/s)


Transacción Transacción
replicas Lectura de Lectura de
escritura de solo escritura de solo
instantánea instantánea
lectura lectura
1D 9.4±.6 - - 4.0±.3 - -
1 14.4±1.0 1.4±.1 1.3±.1 4.1±.05 10.9±.4 13.5±.1
3 13.9±.6 1.3±.1 1.2±.1 2.2±.5 13.8±3.2 38.5±.3
5 14.4±.4 1.4±.05 1.3±.04 2.8±.3 25.3±5.2 50.0±1.1
Tabla 3: Microbenchmarks de operación. Desviación estándar y media en 10 ejecuciones. 1D
significa una réplica con espera de confirmación desactivada.

5.1. Microbenchmarks
La Tabla 3 presenta algunos microbenchmarks para Spanner. Estas medidas se tomaron en
máquinas de tiempo compartido: cada spanserver se ejecutó en unidades de programación de 4
GB de RAM y 4 núcleos (AMD Barcelona 2200MHz). Los clientes se ejecutaron en máquinas
independientes. Cada zona contenía un spanserver. Los clientes y las zonas se colocaron en un
conjunto de datacenters con una distancia de red de menos de 1 ms. (Este diseño debería ser
trivial: la mayoría de las aplicaciones no necesitan distribuir todos sus datos en todo el mundo).
La base de datos de prueba se creó con 50 grupos Paxos con 2500 directorios. Las operaciones
eran lecturas y escrituras independientes de 4 KB. Todas las lecturas se entregaron sin memoria
después de una compactación, por lo que solo estamos midiendo la sobrecarga de la pila de
llamadas de Spanner. Además, primero se realizó una ronda no medida de lecturas para calentar
cualquier caché de ubicación. (Ver: warm caché).

Para los experimentos de latencia, los clientes realizaron un número suficiente de operaciones
como para evitar las colas en los servidores. De los experimentos de 1 réplica, la espera de
confirmación es de aproximadamente 5 ms y la latencia de Paxos es de aproximadamente 9 ms.
A medida que aumenta el número de réplicas, la latencia se mantiene aproximadamente
constante con menos desviación estándar porque Paxos se ejecuta en paralelo en las réplicas de
un grupo. A medida que aumenta el número de réplicas, la latencia para lograr un quórum se
vuelve menos sensible a la lentitud en una réplica esclava.

Para los experimentos de rendimiento, los clientes realizaron un número suficiente de


operaciones para saturar las CPU de los servidores. Las lecturas de instantáneas se pueden
ejecutar en cualquier réplica actualizada, por lo que su rendimiento aumenta casi linealmente con
la cantidad de réplicas. Las transacciones de solo lectura de lectura única solo se ejecutan en los
líderes porque la asignación de marca de tiempo debe ocurrir en los líderes. El rendimiento de las
transacciones de solo lectura aumenta con el número de réplicas porque el número de
spanservers efectivos aumenta: en la configuración experimental, el número de spanservers era
igual al número de réplicas y los líderes se distribuían aleatoriamente entre las zonas. El
rendimiento de escritura se beneficia del mismo artefacto experimental (que explica el aumento
de rendimiento de 3 a 5 réplicas), pero ese beneficio se ve superado por el aumento lineal en la
cantidad de trabajo realizado por escritura, a medida que aumenta el número de réplicas.

Latencia (ms)
participantes
media Percentil 99
1 17.0 ±1.4 75.0 ±34.9
2 24.5 ±2.5 87.6 ±35.9
5 31.5 ±6.2 104.5 ±52.2
10 30.0 ±3.7 95.6 ±25.4
25 35.5 ±5.6 100.4 ±42.7
50 42.7 ±4.1 93.7 ±22.9
100 71.4 ±7.6 131.2 ±17.6
200 150.5 ±11.0 320.3 ±35.1
Tabla 4: Escalabilidad de confirmación en dos fases. Desviaciones estándar y medias en 10
ejecuciones.

La Tabla 4 demuestra que la confirmación de dos fases puede escalar a un número razonable de
participantes: resume un conjunto de experimentos ejecutados en 3 zonas, cada una con 25
spanservers. Escalar hasta 50 participantes es razonable tanto en la media como en el percentil
99, y las latencias comienzan a aumentar notablemente a los 100 participantes.

Figura 5: Efecto de matar servidores en el rendimiento.


5.2. Disponibilidad
La Figura 5 ilustra los beneficios de disponibilidad de ejecutar Spanner en varios datacenters.
Muestra los resultados de tres experimentos sobre el rendimiento en presencia de fallas en el
datacenter, todos los cuales se superponen en la misma escala de tiempo. El universo de prueba
constaba de 5 zonas 𝑍𝑖 , cada una de las cuales tenía 25 spanservers. La base de datos de prueba
se dividió en 1250 grupos de Paxos, y 100 clientes de prueba emitieron constantemente lecturas
que no eran instantáneas a una tasa agregada de 50K lecturas/segundo. Todos los líderes se
colocaron explícitamente en 𝑍1 . Cinco segundos después de cada prueba, todos los servidores de
una zona fueron eliminados: el non-leader (no líder) elimina a 𝑍2 ; leader-hard (líder-duro) mata a
𝑍1 ; el leader-soft (líder suave) mata a 𝑍1 , pero envía notificaciones a todos los servidores que
deben traspasar el liderazgo primero.

Matar 𝑍2 no tiene ningún efecto sobre el rendimiento de lectura. Matar a 𝑍1 mientras se les da
tiempo a los líderes para traspasar el liderazgo a una zona diferente tiene un efecto menor: la
caída del rendimiento no es visible en el gráfico, pero es de alrededor del 3-4%. Por otro lado,
matar a 𝑍1 sin previo aviso tiene un efecto severo: la tasa de finalización cae casi a 0. Sin embargo,
a medida que los líderes son reelegidos, el rendimiento del sistema aumenta a aproximadamente
100K lecturas/segundo debido a dos artefactos de nuestro experimento: hay capacidad adicional
en el sistema, y las operaciones se ponen en cola mientras el líder no está disponible. Como
resultado, el rendimiento del sistema aumenta antes de estabilizarse nuevamente a su tasa de
estado estable.

También podemos ver el efecto del hecho de que los arrendamientos de líderes de Paxos se
establecen en 10 segundos. Cuando matamos la zona, los tiempos de vencimiento del
arrendamiento de líder para los grupos deben distribuirse uniformemente durante los próximos
10 segundos. Poco después de que expira el arrendamiento de un líder fallecido, se elige un nuevo
líder. Aproximadamente 10 segundos después del tiempo de finalización (kill time), todos los
grupos tienen líderes y el rendimiento se ha recuperado. Los tiempos de arrendamiento más
cortos reducirían el efecto de las muertes del servidor en la disponibilidad, pero requerirían
mayores cantidades de tráfico de red de renovación de arrendamiento. Estamos en el proceso de
diseñar e implementar un mecanismo que hará que los esclavos liberen los arrendamientos de
líderes de Paxos si el líder falla.

5.3. TrueTime
Se deben responder dos preguntas con respecto a TrueTime: ¿es 𝜖 realmente un límite en la
incertidumbre del reloj, y qué tan malo se pone 𝜖? Para el primero, el problema más serio sería si
la desviación de un reloj local fuera superior a 200us/seg: eso rompería las suposiciones hechas
por TrueTime. Las estadísticas de nuestras máquinas muestran que las CPU defectuosas son 6
veces más probabilidades que los relojes defectuosos. Es decir, los problemas de reloj son
extremadamente infrecuentes, en relación con problemas de hardware mucho más graves. Como
resultado, creemos que la implementación de TrueTime es tan confiable como cualquier otro
software del que dependa Spanner.
Figura 6: Distribución de valores 𝜖 de TrueTime, muestreados justo después de que el demonio
de esclavo de tiempo (timeslave) sondea a los maestros del tiempo. Se grafican los percentiles
90, 99 y 99,9.

La Figura 6 presenta los datos de TrueTime tomados en varios miles de máquinas spanserver en
datacenters con una separación de hasta 2200 km. Grafica los percentiles 90, 99 y 99,9 de 𝜖,
muestreados en demonios de esclavos de tiempo inmediatamente después de sondear a los
maestros del tiempo. Este muestreo elude el diente de sierra en 𝜖 debido a la incertidumbre del
reloj local y, por lo tanto, mide la incertidumbre del maestro de tiempo (que generalmente es 0)
más el retardo de comunicación con los maestros de tiempo.

Los datos muestran que estos dos factores para determinar el valor base de 𝜖 generalmente no
son un problema. Sin embargo, puede haber problemas importantes de latencia de cola que
provoquen valores más altos de 𝜖. La reducción en las latencias de cola a partir del 30 de marzo
se debió a las mejoras de la red que redujeron la congestión transitoria de los enlaces de red. El
aumento de 𝜖 el 13 de abril, de aproximadamente una hora de duración, se debió al cierre de 2
maestros de tiempo en un datacenter para el mantenimiento de rutina. Seguimos investigando y
eliminando las causas de los picos de TrueTime.

5.4. F1
Spanner comenzó a ser evaluado experimentalmente bajo cargas de trabajo de producción a
principios de 2011, como parte de una reescritura del backend publicitario de Google llamado F1
[35]. Este backend se basó originalmente en una base de datos MySQL que se fragmentó
manualmente de muchas maneras. El conjunto de datos sin comprimir tiene decenas de
terabytes, que es pequeño en comparación con muchas instancias de NoSQL, pero era lo
suficientemente grande como para causar dificultades con MySQL fragmentado. El esquema de
fragmentación de MySQL asignó a cada cliente y todos los datos relacionados a una fragmentación
fija. Este diseño permitió el uso de índices y el procesamiento de consultas complejas por cliente,
pero requirió cierto conocimiento de la fragmentación en la lógica empresarial de la aplicación.
Volver a fragmentar esta base de datos crítica para los ingresos, a medida que aumentaba el
número de clientes y sus datos, era extremadamente costoso. La última refragmentación requirió
más de dos años de intenso esfuerzo, e implicó la coordinación y las pruebas en docenas de
equipos para minimizar el riesgo. Esta operación era demasiado compleja para realizarla con
regularidad: como resultado, el equipo tuvo que limitar el crecimiento en la base de datos MySQL
almacenando algunos datos en Bigtables externos, lo que comprometió el comportamiento
transaccional y la capacidad de consultar todos los datos.
El equipo de F1 decidió utilizar Spanner por varias razones. Primero, Spanner elimina la necesidad
de volver a fragmentar manualmente. En segundo lugar, Spanner proporciona replicación
sincrónica y conmutación por error (failover) automática. Con la replicación maestro-esclavo de
MySQL, la conmutación por error (failover) era difícil y corría el riesgo de pérdida de datos y
tiempo de inactividad. En tercer lugar, F1 requiere una semántica transaccional sólida, lo que hizo
que el uso de otros sistemas NoSQL no fuera práctico. La semántica de la aplicación requiere
transacciones a través de datos arbitrarios y lecturas consistentes. El equipo de F1 también
necesitaba índices secundarios en sus datos (dado que Spanner aún no proporciona soporte
automático para índices secundarios) y pudo implementar sus propios índices globales
consistentes utilizando transacciones de Spanner.

Todas las escrituras de aplicaciones se envían ahora de forma predeterminada a través de F1 a


Spanner, en lugar de la pila de aplicaciones basada en MySQL. F1 tiene 2 réplicas en la costa oeste
de EE.UU. Y 3 en la costa este. Esta elección de sitios de réplica se hizo para hacer frente a las
interrupciones debido a posibles desastres naturales importantes, y también la elección de sus
sitios frontend. Como anécdota, la conmutación por error (failover) automática de Spanner ha
sido casi invisible para ellos. Aunque ha habido fallas de clúster no planificadas en los últimos
meses, lo máximo que ha tenido que hacer el equipo de F1 es actualizar el esquema de su base
de datos para decirle a Spanner dónde ubicar preferentemente a los líderes de Paxos, para
mantenerlos cerca de donde se movieron sus frontends.

La semántica de marca de tiempo de Spanner hizo que, de manera eficiente, F1 mantuviera las
estructuras de datos en memoria calculadas a partir del estado de la base de datos. F1 mantiene
un registro de historial de todos los cambios, que se escribe en Spanner como parte de cada
transacción. F1 toma instantáneas completas de los datos en una marca de tiempo para inicializar
sus estructuras de datos y luego lee los cambios incrementales para actualizarlos.

# de fragmentos # de directorios
1 >100M
2-4 341
5-9 5336
10-14 232
15-99 34
100-500 7
Tabla 5: Distribución de las cuentas directorio-fragmento en F1.

La Tabla 5 ilustra la distribución del número de fragmentos por directorio en F1. Cada directorio
normalmente corresponde a un cliente en la pila de aplicaciones por encima de F1. La gran
mayoría de los directorios (y por lo tanto de los clientes) constan de un solo fragmento, lo que
significa que se garantiza que las lecturas y escrituras de los datos de esos clientes se realizarán
en un solo servidor. Los directorios con más de 100 fragmentos son todas tablas que contienen
índices secundarios F1: las escrituras en más de unos pocos fragmentos de tales tablas son
extremadamente poco comunes. El equipo de F1 solo ha visto este comportamiento cuando
realizan cargas de datos masivas sin ajustar como transacciones.

Latencia (ms)
operación cuenta
media Desviación estándar
Todas las lecturas 8.7 376.4 21.5B
Confirmación de un 72.3 112.8 31.2M
solo sitio
Confirmación de 103.0 52.2 32.1M
varios sitios
Tabla 6: Latencias de funcionamiento percibidas en F1 medidas en el transcurso de 24 horas.

La Tabla 6 presenta las latencias de operación de Spanner medidas desde los servidores F1. Las
réplicas en los datacenters de la costa este tienen mayor prioridad al elegir a los líderes de Paxos.
Los datos de la tabla se miden desde servidores F1 en esos datacenters. La gran desviación
estándar en las latencias de escritura se debe a una cola bastante gruesa debido a los conflictos
de bloqueo. La desviación estándar aún mayor en las latencias de lectura se debe en parte al
hecho de que los líderes de Paxos se distribuyen en dos datacenters, de los cuales solo uno tiene
máquinas con SSD. Además, la medición incluye todas las lecturas del sistema de dos datacenters:
la media y la desviación estándar de los bytes leídos fueron de aproximadamente 1,6 KB y 119 KB,
respectivamente.

6. Trabajo Relacionado.
Megastore [5] y DynamoDB [3] han proporcionado una replicación consistente en los datacenters
como un servicio de almacenamiento. DynamoDB presenta una interfaz clave-valor y solo se
replica dentro de una región. Spanner sigue a Megastore al proporcionar un modelo de datos
semi-relacional, e incluso un lenguaje de esquema similar. Megastore no alcanza un alto
rendimiento. Está superpuesto a Bigtable, lo que impone altos costos de comunicación. Tampoco
admite líderes de larga duración: varias réplicas pueden iniciar escrituras. Todas las escrituras de
diferentes réplicas necesariamente entran en conflicto en el protocolo de Paxos, incluso si no
entran en conflicto lógicamente: el rendimiento colapsa en un grupo de Paxos a varias escrituras
por segundo. Spanner proporciona mayor rendimiento, transacciones de propósito general y
consistencia externa.

Pavlo et al. [31] han comparado el rendimiento de las bases de datos y MapReduce [12]. Señalan
varios otros esfuerzos que se han realizado para explorar la funcionalidad de la base de datos en
capas en almacenes distribuidos de clave-valor [1, 4, 7, 41] como evidencia de que los dos mundos
están convergiendo. Estamos de acuerdo con la conclusión, pero demostramos que la integración
de múltiples capas tiene sus ventajas: la integración del control de concurrencia con la replicación
reduce el costo de espera de confirmación en Spanner, por ejemplo.

La noción de superponer transacciones sobre un almacénoreplicada se remonta al menos a la


disertación de Gifford [16]. Scatter [17] es un almacén clave-valor basado en DHT que superpone
las transacciones a la replicación consistente. Spanner se centra en proporcionar una interfaz de
nivel superior que Scatter. Gray y Lamport [18] describen un protocolo de confirmación sin
bloqueo basado en Paxos. Su protocolo incurre en más costos de mensajería que la confirmación
en dos fases, lo que agravaría el costo del compromiso en grupos ampliamente distribuidos.
Walter [36] proporciona una variante de aislamiento de instantáneas que funciona dentro de los
datacenters, pero no entre ellos. Por el contrario, nuestras transacciones de solo lectura
proporcionan una semántica más natural, porque soportamos la consistencia externa en todas las
operaciones.

Ha habido una serie de trabajos recientes para reducir o eliminar los gastos generales de bloqueo.
Calvin [40] elimina el control de concurrencia: preasigna marcas de tiempo y luego ejecuta las
transacciones en orden de marca de tiempo. HStore [39] y Granola [11] apoyaron cada uno su
propia clasificación de tipos de transacciones, algunas de las cuales podrían evitar el bloqueo.
Ninguno de estos sistemas proporciona consistencia externa. Spanner aborda el problema de la
contención al brindar soporte para el aislamiento de instantáneas.

VoltDB [42] es una base de datos en memoria fragmentada que admite la replicación maestro-
esclavo en el área amplia para la recuperación de desastres, pero no configuraciones de
replicación más generales. Es un ejemplo de lo que se ha denominado NewSQL, que es un impulso
del mercado para admitir SQL escalable [38]. Varias bases de datos comerciales implementaron
lecturas en el pasado, como MarkLogic [26] y Total Recall de Oracle [30]. Lomet y Li [24] describen
una estrategia de implementación para dicha base de datos temporal.

Límites derivados de Farsite en la incertidumbre del reloj (mucho más flexibles que los de
TrueTime) en relación con una referencia de reloj confiable [13]: los arrendamientos de servidores
en Farsite se mantuvieron de la misma manera que Spanner mantiene los arrendamientos de
Paxos. Se han utilizado relojes débilmente sincronizados con fines de control de concurrencia en
trabajos anteriores [2, 23]. Hemos demostrado que TrueTime deja una razón sobre el tiempo
global en conjuntos de máquinas de estado de Paxos.

7. Trabajo Futuro.
Pasamos la mayor parte del último año trabajando con el equipo de F1 para realizar la transición
del backend publicitario de Google de MySQL a Spanner. Estamos mejorando activamente sus
herramientas de seguimiento y soporte, así como ajustando su rendimiento. Además, hemos
estado trabajando para mejorar la funcionalidad y el rendimiento de nuestro sistema de copia de
seguridad/restauración. Actualmente estamos implementando el lenguaje de esquema de
Spanner, el mantenimiento automático de índices secundarios y la refragmentación automática
basada en carga. A largo plazo, hay un par de características que planeamos investigar. Hacer
lecturas en paralelo de manera optimista puede ser una estrategia valiosa a seguir, pero los
experimentos iniciales han indicado que la implementación correcta no es trivial. Además,
planeamos eventualmente admitir cambios directos en las configuraciones de Paxos [22, 34].

Dado que esperamos que muchas aplicaciones repliquen sus datos en datacenters relativamente
cercanos entre sí, TrueTime 𝜖 puede afectar notablemente el rendimiento. No vemos ningún
obstáculo insuperable para reducir 𝜖 por debajo de 1 ms. Los intervalos de consulta del maestro
de tiempo se pueden reducir y los mejores cristales de reloj son relativamente baratos. La latencia
de las consultas del maestro de tiempo podría reducirse con una tecnología de red mejorada, o
posiblemente incluso evitarse mediante una tecnología de distribución de tiempo alternativa.

Finalmente, hay áreas obvias de mejora. Aunque Spanner es escalable en el número de nodos, las
estructuras de datos locales de nodo tienen un rendimiento relativamente bajo en consultas SQL
complejas, porque fueron diseñadas para accesos simples de clave-valor. Los algoritmos y las
estructuras de datos de la literatura sobre bases de datos podrían mejorar mucho el rendimiento
de un solo nodo. En segundo lugar, mover datos automáticamente entre datacenters en
respuesta a cambios en la carga de clientes ha sido durante mucho tiempo uno de nuestros
objetivos, pero para que ese objetivo sea efectivo, también necesitaríamos la capacidad de mover
procesos de aplicaciones cliente entre datacenters de forma automatizada y coordinada. El
traslado de procesos plantea el problema aún más difícil de administrar la adquisición y asignación
de recursos entre datacenters.

8. Conclusiones.
Para resumir, Spanner combina y amplía ideas de dos comunidades de investigación: de la
comunidad de bases de datos, una interfaz familiar, fácil de usar y semi-relacional, transacciones
y un lenguaje de consulta basado en SQL; de la comunidad de sistemas, escalabilidad,
fragmentación automática, tolerancia a fallas, replicación consistente, consistencia externa y
distribución de área amplia. Desde el inicio de Spanner, hemos tardado más de 5 años en iterar
hasta el diseño y la implementación actuales. Parte de esta larga fase de iteración se debió a una
lenta comprensión de que Spanner debería hacer más que abordar el problema de un espacio de
nombres replicado globalmente, y también debería centrarse en las características de la base de
datos que Bigtable no tenía.

Un aspecto de nuestro diseño se destaca: el eje del conjunto de funciones de Spanner es


TrueTime. Hemos demostrado que reificar la incertidumbre del reloj en la API de tiempo hace
posible construir sistemas distribuidos con una semántica de tiempo mucho más sólida. Además,
a medida que el sistema subyacente impone límites más estrictos a la incertidumbre del reloj, la
sobrecarga de la semántica más fuerte disminuye. Como comunidad, ya no deberíamos depender
de relojes débilmente sincronizados y API de tiempo débiles para diseñar algoritmos distribuidos.

Anexo A. Gestión de arrendamiento de líderes de Paxos


El medio más simple para asegurar la disyunción de los intervalos de arrendamiento de los líderes
de Paxos sería que un líder emita una escritura de Paxos sincrónica del intervalo de
arrendamiento, siempre que se extienda. Un líder posterior leería el intervalo y esperaría hasta
que ese intervalo haya pasado.

TrueTime se puede utilizar para garantizar la disyunción sin estas escrituras de registro
adicionales. El i-ésimo líder potencial mantiene un límite inferior al inicio de un voto de
𝑙í𝑑𝑒𝑟 𝑒𝑛𝑣𝑖𝑎𝑟
arrendamiento de la réplica r como 𝑣𝑖,𝑟 = 𝑇𝑇. 𝑛𝑜𝑤(). 𝑒𝑎𝑟𝑙𝑖𝑒𝑠𝑡, calculado antes de 𝑒𝑖,𝑟
(definido como cuando la solicitud de arrendamiento es enviada por el líder). Cada réplica r
𝑜𝑡𝑜𝑟𝑔𝑎𝑟 𝑟𝑒𝑐𝑖𝑏𝑖𝑟
otorga un arrendamiento en el arrendamiento 𝑒𝑖,𝑟 , que ocurre después de 𝑒𝑖,𝑟 , (cuando
𝑓𝑖𝑛
la réplica recibe una solicitud de arrendamiento); el arrendamiento termina en 𝑡𝑖,𝑟 =
𝑟𝑒𝑐𝑖𝑏𝑖𝑟
𝑇𝑇. 𝑛𝑜𝑤(). 𝑙𝑎𝑡𝑒𝑠𝑡 + 10, calculado después de 𝑒𝑖,𝑟 . Una réplica r obedece la regla del voto
𝑓𝑖𝑛
único: no otorgará otro voto de arrendamiento hasta que 𝑇𝑇. 𝑎𝑓𝑡𝑒𝑟(𝑡𝑖,𝑟 ) sea verdadero (true).
Para hacer cumplir esta regla en diferentes encarnaciones de r, Spanner registra un voto de
arrendamiento en la réplica que otorga antes de otorgar el arrendamiento; esta escritura de
registro puede combinarse con las escrituras de registro del protocolo Paxos existentes.

𝑒𝑞𝑢𝑜𝑟𝑢𝑚
Cuando el i-ésimo líder recibe un quórum de votos (evento 𝑒𝑖 ), calcula su intervalo de
𝑙í𝑑𝑒𝑟
arrendamiento como 𝑎𝑟𝑟𝑒𝑛𝑑𝑎𝑚𝑖𝑒𝑛𝑡𝑜𝑖 = [𝑇𝑇. 𝑛𝑜𝑤( ). 𝑙𝑎𝑡𝑒𝑠𝑡, 𝑚𝑖𝑛𝑟 (𝑣𝑖,𝑟 ) + 10]. Se
𝑙í𝑑𝑒𝑟
considera que el arrendamiento ha expirado en el líder cuando 𝑇𝑇. 𝑏𝑒𝑓𝑜𝑟𝑒(𝑚𝑖𝑛𝑟 (𝑣𝑖,𝑟 ) + 10)
es falso (false). Para demostrar la disyinción, utilizamos el hecho de que el i-ésimo y el (i + 1)-
ésimo líderes deben tener una réplica en común en sus quórumes. Llame a esa réplica r0. Prueba:

𝑙í𝑑𝑒𝑟
𝑎𝑟𝑟𝑒𝑛𝑑𝑎𝑚𝑖𝑒𝑛𝑡𝑜𝑖 . 𝑒𝑛𝑑 = 𝑚𝑖𝑛𝑟 (𝑣𝑖,𝑟 ) + 10 por definición
𝑙í𝑑𝑒𝑟 𝑙í𝑑𝑒𝑟
𝑚𝑖𝑛𝑟 (𝑣𝑖,𝑟 ) + 10 ≤ 𝑣𝑖,𝑟0 + 10 min
𝑙í𝑑𝑒𝑟 𝑒𝑛𝑣𝑖𝑎𝑟
𝑣𝑖,𝑟0 + 10 ≤ 𝑡𝑎𝑏𝑠 (𝑒𝑖,𝑟0 )
+ 10 por definición
𝑒𝑛𝑣𝑖𝑎𝑟 𝑟𝑒𝑐𝑖𝑏𝑖𝑟
𝑡𝑎𝑏𝑠 (𝑒𝑖,𝑟0 ) + 10 ≤ 𝑡𝑎𝑏𝑠 (𝑒𝑖,𝑟0 ) + 10 causalidad
𝑟𝑒𝑐𝑖𝑏𝑖𝑟 𝑓𝑖𝑛
𝑡𝑎𝑏𝑠 (𝑒𝑖,𝑟0 ) + 10 ≤ 𝑡𝑖,𝑟0 por definición
𝑓𝑖𝑛 𝑜𝑡𝑜𝑟𝑔𝑎𝑟
𝑡𝑖,𝑟0 < 𝑡𝑎𝑏𝑠 (𝑒𝑖+1,𝑟0 ) un solo voto
𝑜𝑡𝑜𝑟𝑔𝑎𝑟 𝑞𝑢𝑜𝑟𝑢𝑚
𝑡𝑎𝑏𝑠 (𝑒𝑖+1,𝑟0 ) ≤ 𝑡𝑎𝑏𝑠 (𝑒𝑖+1 ) causalidad
𝑞𝑢𝑜𝑟𝑢𝑚
𝑡𝑎𝑏𝑠 (𝑒𝑖+1 ) ≤ 𝑎𝑟𝑟𝑒𝑛𝑑𝑎𝑚𝑖𝑒𝑛𝑡𝑜𝑖+1 . 𝑠𝑡𝑎𝑟𝑡 por definición

También podría gustarte