Instituto Tecnológico de Acapulco Sistemas Distribuidos I |
Unidad 3 |
Uno de los ingredientes básicos en todo sistema tolerante a fallas es el mecanismo
de transacciones. Una transacción encierra un número de operaciones de forma
que todas o ninguna de las operaciones se llevan a cabo. Las transacciones hacen
que la recuperación de errores sea más fácil, ya que las transacciones sólo pueden
terminar en uno de dos estados: transacción completa o transacción incompleta.
Las transacciones resultan de gran importancia para simplificar la construcción
de aplicaciones distribuidas confiables y disponibles en todo momento, particularmente
aplicaciones que requieren acceso concurrente a datos compartidos. Las transacciones se definen como una colección de operaciones delimitadas por dos indicadores: Inicia_transacción y Termina_transacción, estas poseen tres propiedades que reducen la atención que un programador debe poner a la concurrencia y a las fallas. |
Introducción a las transacciones El modelo de la transacción atómica proviene del mundo de los negocios. Supongamos que la Compañía Internacional Dingbat necesita un lote de ciertos artefactos. Se comunican con un posible proveedor, Artefactos, S.A., conocido ampliamente por la calidad de sus artefactos, para que les proporcione 100.000 artefactos de color púrpura de 10 cm cada uno, para entregarse en junio. Artefactos, S.A., ofrece 100.000 artefactos de 4 pulgadas, en color malva, para entregarse en diciembre. Dingbat está de acuerdo con el precio, pero no le gusta el color malva, los desea en julio e insiste en la medida de 10 cm para sus clientes internacionales. Artefactos responde con un ofrecimiento de artefactos lavanda de 3 15/16 pulgadas en octubre. Después de varias negociaciones, coinciden en artefactos violeta, de 3 959/1024 pulgadas, para entregarse el 15 de agosto. Hasta este momento, ambas partes son libres de determinar la discusión, en cuyo caso el mundo regresa al estado en que se encontraba antes de comenzar las pláticas; sin embargo, una vez que las compañías firman un contrato, están obligadas legalmente a concluir la venta, pase lo que pase. Así, antes de que ambas partes firmen en la línea punteada, cualquiera puede retroceder como si nada hubiese pasado; pero al momento en que ambos firman, o pasan un punto sin retorno y la transacción debe llevarse a cabo. El modelo de la computadora es similar. Un proceso anuncia que desea comenzar una transacción con uno o más procesos. Pueden negociar varias opciones, crear y eliminar objetos y llevan a cabo ciertas operaciones durante unos momentos. Entonces, el iniciador anuncia que desea que todos los demás se comprometan con el trabajo realizado hasta entonces. Si todos coinciden, los resultados se vuelven permanentes. Si uno o más procesos se niegan (o fallan antes de expresar su acuerdo), entonces la situación regresa al estado que presentaba antes de comenzar la transacción, sin que existan efectos colaterales en los objetos, archivos, bases de datos, etc. Esta propiedad del todo o nada facilita el trabajo del programador. El uso de transacciones en los sistemas de cómputo data de la década de 1960. antes de la existencia de los discos y las bases de datos en línea, todos los archivos se mantenían en cintas magnéticas. Imaginemos un supermercado con un sistema automatizado para los inventarios. Cada días, después del cierre, la ejecución de la computadora se realizaba mediante dos cintas de entrada. La primera contenía todo el inventario al tiempo de la apertura en la mañana. La segunda contenía una lista de las actualizaciones del día: los productos vendidos a los clientes y los productos entregados por los proveedores. La computadora leía ambas cintas y producía una nueva cinta maestra de inventarios. La gran belleza de este esquema (aunque las personas que lo vivieron no se daban cuenta de ello) es que si una ejecución fallaba por cierta razón, todas las cintas se rebobinaban y el trabajo volvía a comenzar sin que hubiera algún daño. Aún siendo primitivo, el antiguo sistema de cintas magnéticas tenía la propiedad del todo o nada de la transacción atómica. |
Almacenamiento Estable |
El almacenamiento tiene tres categorías. En primer lugar, tenemos la memoria RAM
ordinaria, que se limpia al fallar el suministro de energía o en un fallo de la
máquina. A continuación tenemos el almacenamiento en disco, que sobrevive a las
fallas del CPU, pero que se pueden perder debido a problemas con la cabeza lectores
del disco. Por último tenemos el almacenamiento estable, diseñado para sobrevivir a todo, excepto catástrofes mayores, como las inundaciones y terremotos. El almacenamiento estable se puede implantar con una pareja de discos ordinarios. Cada bloque en la unidad 2 es una copia exacta del bloque correspondiente en la unidad 1. cuando se actualiza en un bloque, primero se actualiza y verifica el bloque de la unidad 1, para después encargarse del mismo bloqueo de la unidad 2. El almacenamiento estable es adecuado para las aplicaciones que se requieren de un alto grado de tolerancia de fallas, como las transacciones de nuevos para verificar si fueron escritos de manera correcta, la probabilidad de que se pierdan es muy pequeña. |
Primitivas de Transacción |
La programación con uso de transacciones requiere de primitivas especiales, las cuales
deben ser proporcionadas por el sistema operativo o por el compilador del
lenguaje. Algunos ejemplos son: 1.- BEGÍN_TRANSACTION: Señala el inicio de una transacción 2.- END_TRANSACTION: Termina la transacción y se intenta un compromiso. 3.- ABORT_TRANSACTIO: Se elimina la transacción; se recuperan los valores anteriores 4.- READ: Se leen datos de un archivo (o algún objeto). 5.- WRITE: Se escriben datos en un archivo (o algún objeto). La lista de primitivas depende del tipo de objetos que se utilicen en la transacción, en un sistema de correo, podían existir primitivas para el envío, recepción y direccionamiento del correo. En un sistema de contabilidad, podrían ser un poco distintas. Sin embargo, READ y WRITE son ejemplos típicos. Dentro de una transacción se permite también enunciados ordinarios, llamadas a procedimientos, etc. BEJÍN_TRANSACTION y END_TRANSACTION se utilizan para establecer los límites de una transacción. Las operaciones entre ellas forman el cuerpo de la transacción. Todas o ninguna de ellas deben ejecutarse. Estas operaciones deben ser llamadas al sistema, procedimiento de biblioteca o enunciados encapsulados en un lenguaje, según la implantación. Propiedades de las transacciones. Las transacciones tienen cuatro propiedades fundamentales. Las transacciones son: 1.- Atómica: Para el mundo exterior, la transacción ocurre de manera indivisible. 2.- Consistentes: Las transacción no viola los invariantes del sistema. 3.- Aisladas: Las transacciones concurrentes no interfieren entre sí. 4.- Durables: Una vez comprometido una transacción, los cambios son permanentes. Utilizamos las siglas ACID (las iniciales en inglés) para referirnos a estas propiedades. La primera propiedad fundamental de todas las transacciones que son atómicas. Esta propiedad garantiza que cada transacción no ocurre o bien, se realiza en sus totalidad; en este segundo caso, se presenta como acción instantánea e indivisible. Mientras se desarrolla una transacción, otros procesos (ya sea que estén o no relacionados con las transacciones) no pueden ver los estados intermedios. La segunda propiedad dice que son consistentes. Lo que esto significa es que si el sistema tiene ciertos invariantes que deben conservarse siempre, si éstos se conservan antes de la transacción, entonces también deben conservarse después de ellos. La tercera propiedad dice que las transacciones son aisladas o seriabizables. Lo que esto significa que si dos o más transacciones se ejecutan al mismo tiempo, para cada una de ellas y para los demás procesos, el resultado final aparece como si todas las transacciones se ejecutasen de manera secuencial en cierto orden (dependiente del sistema). La cuarta propiedad dice que las transacciones son durables, se refiere al hecho de que una vez comprometida una transacción, no importa que ocurra, la transacción sigue adelante y lso resultados se vuelven permanentes. Ninguna falla después del compromiso puede deshacerse los resultados o provocar la pérdida de los mismo. |
Transacciones Anidadas |
Las transacciones anidadas difieren de las transacciones de un sólo nivel de dos
importantes maneras. Primero, una transacción hija puede abortar sin forzar a su
padre a abortar, de hecho, se puede informar a la transacción padre cuando una
hija ha abortado y tomar diferentes caminos que cuando la transacción hija terminó
completa. Segundo, una transacción puede ejecutar varias subtransacciones
concurrentemente. Las transacciones anidadas son útiles por dos razones: Permiten la concurrencia dentro de una transacción. Una transacción puede ejecutar muchas subtransacciones en paralelo, con la garantía de que parecerá que se ejecutan secuencialmente. Proveen una mayor protección contra fallas, ya que establecen puntos de observación que se establecen dentro de una transacción. Cuando una subtransacción aborta, su padre puede continuar y probablemente terminar su tarea usando algún método alternativo. Existen dos formas de anidar transacciones, que se asemejan a los procedimientos y abstracciones de datos anidados. En el primer tipo, una subtransacción no es visible fuera de su padre, y si esta aborta, la subtransacción también es abortada. El segundo tipo es representado por algoritmos de control de concurrencias de tipos específicos. Las modificaciones de una subtransacción son visibles a otras transacciones al mismo nivel de abstracción tan pronto como se complete, aún si su padre está aún activo. Si la transacción padre aborta, se debe ejecutar una operación compensatoria para deshacer los efectos de la subtransacción terminada. |
Transacciones Distribuidas |
Una transacción que ejecuta operaciones en objetos dispersos en un sistema distribuido,
es llamada transacción distribuida. La distribución de objetos en múltiples
nodos de procesamiento permite un incremento en el desempeño y en la disponibilidad
del sistema, debido al paralelismo y a la réplica de la información. Un cliente comienza una transacción enviando una petición OpenTransaction (Inicia_transacción) a cualquier servidor. El servidor procesa la petición OpenTransaction y regresa el identificador resultante al cliente, el cual debe ser único en el sistema distribuido. El primer servidor en la transacción se vuelve el coordinador de la transacción y es responsable de terminarla (commit) o abortarla, además de agregar a otros servidores identificados como trabajadores. El coordinador crea una lista de trabajadores y cada trabajador registra el identificador del servidor que funciona como coordinador. Una transacción distribuida requiere de una función adicional para servicios de transacciones: AddServer(transacción, id_servidor-coordinador) Esa función debe ser utilizada por el cliente antes de cualquier operación solicitada a algún servidor que no haya sido incluido en la transacción. La función AddServer provee el identificador de la transacción y el identificador del coordinador de la transacción. Cuando un servidor nuevo recibe una petición con la función AddServer, éste inicializa una transacción local con el identificador de transacción indicado y envía una petición NewServer al coordinador; como se muestra a continuación: NewServer(id_transacción, id_servidor del trabajador) La petición NewServer suministra el identificador de la transacción y del servidor, que actualmente es un trabajador. Este hecho permitirá coleccionar toda la información requerida al momento de cometer la transacción. |
Protocolos de ejecución atómica |
Protocolo de ejecución atómica de una fase. Una transacción llega a su fin cuando un cliente solicita que una transacción debe
completarse o abortarse. Una forma simple de completar una transacción es que
el coordinador comunique la realización o cancelación de la transacción a todos
los servidores de la transacción y repetir el mensaje hasta que todos tengan
conocimiento de que ha terminado. Este tipo de protocolo resulta inadecuado, ya
que cuando un cliente solicita el cometido de una transacción, éste no le permite
al servidor tomar una decisión unilateral para abortar la transacción. Protocolo de ejecución atómica de dos fases. Este protocolo fue diseñado para permitir a los servidores abortar su participación en una transacción debido a la atomicidad, si una parte de la transacción es abortada, entonces toda la transacción debe ser abortada. El protocolo sigue este procedimiento: en la primera fase del protocolo, cada servidor decide si aborta o realiza una transacción y una vez que ha decidido, no se le permite abortarla; por lo tanto, antes de que un servidor decida abortar o cometer, éste se debe asegurar si será capaz de terminar su parte de la transacción, aún en caso de falla. En la segunda fase del protocolo, cada servidor lleva a cabo la decisión mayoritaria y si cualquier servidor decide abortar, entonces la decisión debe ser abortar la transacción. |
Control de concurrencias en transacciones distribuidas |
Cada servidor administra un conjunto de datos y es responsable de asegurarse que
se mantengan consistentes cuando son accesados por transacciones concurrentes.
Esto concluye en que cada servidor es responsable de aplicar cierto control de
concurrencias a la información que administra. Existen varias técnicas usadas para el control de concurrencias de transacciones en un sistema distribuido. Bloqueo. Cuando se usa el bloqueo en registros de información para el control de concurrencias, los registros se mantienen bloqueados y no están disponibles para otras transacciones. En una transacción distribuida, cada servidor mantiene bloqueos de su propia información. El administrador de bloqueos puede decidir entre conceder un bloqueo o hacer que la transacción que lo solicita espere. De cualquier manera, el servidor no puede liberar cualquier bloqueo hasta saber que la transacción ha sido realizada o abortada en todos los servidores envueltos en la transacción. Control de concurrencias por ordenamiento de registro de tiempo (timestamp). En una transacción que envuelve a un sólo servidor, este realiza un único registro de tiempo para cada transacción cuando estas inician. En las transacciones distribuidas se requiere que cada servidor tenga la posibilidad de registrar globalmente el tiempo. El registro o marca lo hace el primer servidor accesado por la transacción y después, esa marca de tiempo se dispersa a los demás servidores que intervienen en la transacción. Los servidores involucrados en una transacción distribuida son responsables de asegurarse que ejecutan la transacción de una manera equivalente a la serial. Por ejemplo, si la versión de la información accesada por la transacción U se realiza después de la transacción T en un servidor, entonces si T y U accesan el mismo registro de información en otro servidor, deben completarse en el mismo orden. Para lograr el mismo orden en todos los servidores, estos deben concordar con los registros de tiempo de las transacciones. Una marca o registro de tiempo consiste en pares de <registro local de tiempo, id_servidor> y en las comparaciones de estos pares, id_servidor es irrelevante. Control optimista de transacciones. Cada transacción debe ser validada antes de permitírsele llevarse a cabo (commit). Los servidores asignan números a las transacciones al inicio de su validación y posteriormente son serializadas de acuerdo con el número que se les asignó. Una transacción distribuida es validada por una colección de servidores independientes, cada uno de los cuales valida a las transacciones que accesarán a su información. |
Diseño de un servicio de transacciones. |
Modelo cliente/servidor. Por razones de seguridad, abstracción y mantenimiento, los objetos de datos son encapsulados
en subsistemas o servidores. En este modelo, los servidores manejan
objetos de datos recuperables. Un servidor define las operaciones que son exportadas
a los clientes. Los clientes invocan estas operaciones para manipular los
datos manejados por un servidor. Las operaciones son invocadas por medio de un
servicio de RPC (llamadas a procedimientos remotos, por sus siglas en inglés).
Los servidores pueden ser clientes de otros servidores. Típicamente, una aplicación
comenzará una transacción, ejecutará una o más llamadas a procedimientos
remotos a varios servidores, y terminará la transacción. Las llamadas a procedimientos
remotos actuarán a favor de la transacción, y permiten a los clientes
llamar operaciones en servidores ejecutando en el mismo o diferente nodo. Para
que un servidor pueda implementar las operaciones que se le soliciten, éste puede
hacer llamadas a procedimientos remotos en otros servidores. Modelo del sistema. El servicio de transacciones es provisto para las aplicaciones y servidores de datos. Este soporte puede implementarse en el sistema operativo, en varios servidores fuera del sistema operativo, en librerías que ejecuten en cada aplicación y servidor de datos, o usando alguna combinación de estas técnicas. El soporte de transacciones ayuda a los servidores de datos y a las aplicaciones a enfrentarse a fallas que no son previstas por dispositivos de hardware o su software controlador. Se consideran tres tipos de dispositivos: comunicaciones, procesador y almacenamiento. A continuación se describen seis de las funciones requeridas para implementar un servicio de transacciones: •El administrador de transacciones es el responsable de alcanzar el consenso entre los participantes en una transacción, así como la terminación completa o incompleta de la transacción. •La administración de recuperación es responsable de almacenar el estado después de una falla, por ejemplo; deshacer los efectos de una transacción incompleta. •La responsabilidad de la transferencia de información entre el almacenamiento volátil y el permanente es responsabilidad del administrador de búffer. •La administración de conexión se encarga de lograr las conexiones entre clientes y servidores. •Administración de bloqueos. Se encarga del control de concurrencias. El administrador de comunicaciones es responsable de que transparentemente se extiendan las comunicaciones a través de la red y de comunicar al administrador de transacciones cuando una transacción se hace distribuida. |