He estado leyendo sobre las diferencias entre la serialización y la linealización , que son criterios de consistencia para los sistemas replicados, como las bases de datos replicadas. Sin embargo, no sé en qué casos sería necesaria la linealización, a pesar de que es más fuerte que la serialización.
¿Podría pensar en escenarios en los que una propiedad tan fuerte sería realmente necesaria?
concurrency
databases
Eduardo Bezerra
fuente
fuente
Respuestas:
Considere el diseño de estructuras de datos concurrentes, sin espera (o sin bloqueo, que es más débil). En este escenario, generalmente se requiere linealización, aunque en algunos casos, el rendimiento y la escalabilidad se pueden mejorar al satisfacer una condición de corrección más débil. Si una implementación que satisface una condición tan débil es útil, generalmente depende de la aplicación. En contraste, una implementación linealizable siempre es utilizable, porque los diseñadores pueden verla como atómica.
Además, la linealización es una propiedad que no bloquea: nunca se requiere una operación total (definida para todos los estados de objeto) para bloquear. En cambio, la serialización no es una propiedad no bloqueante. Por lo tanto, para aumentar el grado de concurrencia, los diseñadores de estructuras de datos concurrentes siempre confían en la linealización.
fuente
He releído a Herlihy y Wing muchas veces en los últimos 15 años. Es una lectura muy difícil. Y eso es lamentable, porque si bien hay algunas sutilezas en los bordes, la idea básica es bastante razonable.
En resumen: la linealización es como la serialización, pero con el requisito adicional de que la serialización respete restricciones de orden adicionales entre las transacciones. El objetivo es permitirle razonar rigurosamente sobre una estructura de datos atómicos individuales en lugar de tener que razonar sobre todo el sistema a la vez.
La linealización también es fácil de lograr: simplemente asocie un mutex con el objeto que desea linealizar. Cada transacción en ese objeto comienza bloqueando el mutex y termina desbloqueando el mutex.
Aquí están las definiciones que usaré:
La serialización no permite la apariencia de intercalación de operaciones entre diferentes transacciones, y requiere que el orden elegido de las transacciones satisfaga la causalidad (si la transacción A escribe el valor x, y la transacción B lee el valor x que A escribió, entonces la transacción A debe preceder a la transacción B en el orden en serie elegido.) Pero no dice nada sobre otras restricciones en el orden de las transacciones (en particular, no dice nada sobre los procesos y el orden en que los procesos perciben los eventos).
Hay otra idea relacionada que agrega restricciones sobre el orden en que los procesos ejecutan las operaciones (pero no habla de transacciones solo de operaciones de lectura / escritura individuales):
Implícito en la definición de consistencia secuencial es que solo aceptamos órdenes secuenciales donde para cada ubicación de memoria (objeto) el orden secuencial de operaciones inducido obedece a la regla de que el valor devuelto por cada operación de lectura a la ubicación
x
debe ser el mismo valor escrito por la operación de escritura inmediatamente anterior a la ubicaciónx
en el orden secuencial.La linealización tiene las buenas intenciones de (a) combinar la noción de transacciones (de la serialización) con la noción de que los procesos esperan que las operaciones que emitan se completen en orden (de consistencia secuencial) y (b) reducir los criterios de corrección para hablar sobre cada objetar de forma aislada, en lugar de obligarlo a razonar sobre el sistema en su conjunto. (Me gustaría poder decir que la implementación de mi objeto es correcta incluso en un sistema donde hay otros objetos que no son linealizables). Creo que Herlihy y Wing podrían haber estado tratando de definir rigurosamente un monitor .
La parte (a) es "fácil": un requisito de coherencia secuencial sería que las transacciones en el objeto emitido por cada proceso aparezcan en la secuencia resultante en el orden especificado por el programa. Un requisito similar a la serialización sería que las transacciones en el objeto sean mutuamente excluyentes (se pueden serializar).
La complejidad proviene del objetivo (b) (poder hablar sobre cada objeto independientemente de todos los demás).
En un sistema con varios objetos, es posible que las operaciones en el objeto B impongan restricciones en el orden en el que creemos que las operaciones fueron invocadas en el objeto A. Si observamos el historial completo del sistema, estaremos limitados a ciertos órdenes secuenciales, y tendrá que rechazar a los demás. Pero queríamos un criterio de corrección que pudiéramos utilizar de forma aislada (razonamiento sobre lo que le sucede al objeto A sin apelar al historial del sistema global).
Por ejemplo: suponga que estoy tratando de discutir sobre la corrección del objeto A, que es una cola, suponga que el objeto B es una ubicación de memoria y suponga que tengo los siguientes historiales de ejecución: Hilo 1: A.enqueue (x), A. dequeue () (devuelve y). Hilo 2: A.enqueue (y), A.dequeue () (devuelve x). ¿Existe un entrelazado de eventos que permita que esta implementación de la cola sea correcta? Si:
Pero ahora, ¿qué pasa si el historial ( incluido el objeto B ) es: B comienza con el valor 0. Hilo 1: A.enqueue (x), A.dequeue () (devuelve y), B.write (1). Hilo 2: B.read () (devuelve 1) A.enqueue (y), A.dequeue () (devuelve x).
Ahora nos gustaría que nuestra definición de "corrección" diga que este historial indica que nuestra implementación de A es defectuosa o que nuestra implementación de B es defectuosa, porque no hay serialización que "tenga sentido" (o bien el Tema 2 debe leerse) un valor de B que aún no se ha escrito, o el subproceso 1 necesita eliminar un valor de A que aún no se ha puesto en cola.) Entonces, aunque nuestra serialización original de las transacciones en A parecía razonable, si nuestra implementación permite un historial como el segundo, entonces es claramente incorrecto.
Por lo tanto, las restricciones que agrega la linealización son bastante razonables (y necesarias incluso para estructuras de datos simples como las colas FIFO). Son cosas como: "su implementación no debe permitir dequeue () un valor que no se pondrá en cola () hasta algún tiempo en el futuro." La linealización es bastante fácil (y natural) de lograr: simplemente asocie un mutex con su objeto, y cada transacción comienza bloqueándose y termina desbloqueándose. El razonamiento sobre la linealización comienza a ser complicado cuando intenta implementar su atomicidad con técnicas sin bloqueo o sin bloqueo o sin esperar en lugar de simples mutexes.
Si está interesado en algunos consejos sobre la literatura, encontré lo siguiente (aunque creo que la discusión sobre el "tiempo real" es una de las pistas falsas que hacen que la linealización sea más difícil de lo necesario). Https: // stackoverflow.com/questions/4179587/difference-between-linearizability-and-serializability
fuente
wait()
ynotify()
. La linealización ofrece una forma de hablar sobre la corrección de implementaciones de monitor mucho más complicadas / optimizadas.Related Work
parte del periódico de Herlihy y Wing. Mencionaronmonitor
como una ilustración de su reclamo queOur notion of linearizability generalizes and unifies similar notions found in specific examples in the literature
. Sin embargo, una pregunta general: ¿se ha adoptado ampliamente la noción de linealización en los sistemas multiprocesador (por ejemplo, hardware, compilador, lenguaje de programación y estructuras de datos concurrentes)? (Siendo miope, solo sé cosas como el monitor). Si no, ¿cuáles son los obstáculos? ¿Cuál es el estado del arte?Primero, la linealización y la serialización no son directamente comparables. Como muestra la tabla a continuación, la principal diferencia es que en el lado izquierdo, todas las operaciones individuales son atómicas (como tener un Java
synchronized
alrededor de cada operación . En el lado derecho, la unidad de atomicidad es una transacción; una operación individual no es atómica Es por eso que la serialización siempre ha sido parte de la literatura de la base de datos, mientras que el lado izquierdo ha sido el tema de la literatura de la memoria del procesador (la operación de lectura / escritura es atómica). memcached) comenzó en el lado izquierdo (get / put es atómico), pero los más nuevos respaldan cada vez más las transacciones (como la llave de Google).La linealización requiere que un sistema de objetos en una configuración concurrente se comporte de manera idéntica a un sistema secuencial que maneja una operación (un par de solicitud / respuesta) a la vez, en un universo paralelo, de tal manera que (a) los clientes en ambos universos ver exactamente las mismas respuestas (b) se conserva el orden temporal (más sobre esto a continuación).
La definición de Serializabilidad, como la Consistencia secuencial, solo requiere el primer criterio.
La preservación del orden temporal significa esto: si A: x.op1 () (A es un cliente, x es un objeto y op1 es una operación) finalizó antes de que comenzara otra operación B: y.op2 (), entonces en el universo secuencial Las solicitudes se manejan en el mismo orden. Esto no es necesario en la coherencia secuencial (SC); el objeto puede poner en cola la solicitud de un cliente, responder al cliente y luego evaluarlo más tarde. Además, el objeto puede manejar una solicitud posterior de algún otro cliente fuera de turno, evaluándolo antes de llegar al primero.
La no preservación del orden temporal es un problema. Después de A: x.op1 (), suponga que A levantó el teléfono y le contó a B al respecto, luego B llamó a la llamada x.op2 (). No hay forma de que el sistema sepa acerca de esta cadena de eventos causales, ya que el segundo paso involucra un mensaje que el sistema no rastrea. En muchos casos reales, no es irrazonable que A suponga que una vez que x le haya respondido, la invocación de B puede depender del estado actualizado. Si no se preserva el orden temporal, A y B se sorprenderán. Esto no sucedería en un sistema linealizable.
La segunda propiedad agradable de la preservación del orden temporal es la localidad y la composicionalidad, que un sistema construido de objetos linealizables es en sí mismo linealizable. Por lo tanto, en lugar de tener un almacén de valores clave monolíticos, puede dividirlo en muchas particiones separadas, cada una administrada por su propio servidor KV-store; Si cada uno de ellos es linealizable, toda la base de datos funciona como una tienda KV monolítica linealizable, sin esfuerzo adicional.
fuente