2011-06-08 37 views
10

Actualmente estoy construyendo un sistema donde S3 se utilizará como un conjunto de hash persistente (la URL S3 se deduce de los datos) por muchas computadoras en Internet. Si dos nodos almacenan los mismos datos, se almacenarán con la misma clave y, por lo tanto, no se almacenarán dos veces. Cuando se elimina un objeto, necesito saber si algunos otros nodos están usando también esos datos. En ese caso, no lo eliminaré.Concurrencia en Amazon S3

Ahora lo he implementado agregando una lista de nodos de almacenamiento como parte de los datos escritos en S3. Entonces, cuando un nodo está almacenando los datos, sucede lo siguiente:

  1. Lea el objeto de S3.
  2. Deserializar el objeto.
  3. Agregue el ID del nuevo nodo a la lista de nodos de almacenamiento.
  4. Serializar el nuevo objeto (los datos para almacenar y la lista de nodos).
  5. Escriba los datos serializados en S3.

Esto crea una forma de conteo de referencia idempotente. Dado que las solicitudes a través de Internet pueden ser poco fiables, no quiero simplemente contar la cantidad de nodos de almacenamiento. Es por eso que estoy almacenando una lista en lugar de un contador (en caso de que un nodo envíe la misma solicitud> 1 vez).

Este enfoque funciona siempre que dos nodos no estén escribiendo simultáneamente. S3 no (hasta donde yo sé) proporciona ninguna forma de bloquear el objeto para que todos estos 5 pasos se vuelvan atómicos.

¿Cómo resolvería este problema de simultaneidad? Estoy considerando implementar alguna forma de concurrencia optimista. ¿Cómo debería hacer eso para S3? ¿Debería quizás usar un enfoque completamente diferente?

Respuesta

4

Considere primero separar la lista de bloqueo de sus datos (protegidos). Cree un depósito específico específico para sus datos para contener la lista de bloqueo (el nombre del depósito debe ser un derivado del nombre de su objeto de datos). Use archivos individuales en ese segundo segmento (uno por nodo, con el nombre del objeto derivado del nombre del nodo). Los nodos agregan un nuevo objeto al segundo segmento antes de acceder a los datos protegidos, los nodos eliminan su objeto del segundo segmento cuando terminan.

Esto le permite enumerar el segundo segmento para determinar si sus datos están bloqueados. Y permite que dos nodos actualicen la lista de bloqueo simultáneamente sin conflicto.

+0

¡Me gusta la idea! Funciona para las escrituras, ya que S3 ahora tiene consistencia de lectura tras escritura, pero supongo que aún corremos el riesgo de no eliminar un objeto, ya que no tiene consistencia de lectura después de eliminación. – Yrlec

1

Puede ser una buena idea separar las referencias del recurso.

Puede generar simultaneidad además del control de versiones de S3. O deje que cada referer/nodo cree y elimine su propio recurso de bloqueo en S3. O utilice el servicio de base de datos relacional de Amazon (RDS).

+0

Gracias, pero estamos haciendo esto a una escala tan grande que preferimos evitar el uso de RDS (que tiene una escalabilidad limitada) y SimpleDB (que tiene altos costos de E/S). – Yrlec

3

Para agregar a lo que dijo amadeus, si sus necesidades no son relacionales, incluso puede utilizar SimpleDB de AWS, significativamente más barato.

+0

Gracias, pero el tamaño de nuestros objetos (un par de MB/objetos) hace que SimpleDB sea una opción muy costosa (incluso imposible). – Yrlec

2

No he trabajado con Amazon S3, pero esta es mi sugerencia de ignorancia de persistencia.

  1. ¿Se puede usar el comando de consulta de segregación? Sería bueno separar las lecturas de los comandos, ya que esta verificación solo ocurrirá para el comando (DELETE) y no es necesario para lecturas (si lo obtuve correctamente).

  2. Si no hay soporte nativo para tal sincronización, entonces su propia solución enrollada podría ser un cuello de botella en términos de carga alta (que puede ser resuelto por [3] y [4]). Todos tus DELETE deben pasar por un lugar central: cola de solicitudes.

  3. Haría un servicio dedicado (como WCF) con una cola de solicitudes simultáneas. Cada vez que necesite BORRAR un objeto, enrutará un elemento. El servicio, a su propio ritmo, dequeará el artículo y hará todos sus 5 pasos como una única transacción. Esto puede presentar algunas demoras, que sin embargo pueden no ser visibles si el sistema es pesado de lectura.

  4. Si el sistema es escritura pesada puede que tenga que añadir los trabajadores que ayudan a quitar de la cola la solicitud de la cola [3]

+0

¡Gracias! Sí, usar algún tipo de colas es una forma de resolverlo (por ejemplo, usando SQS). Sin embargo, tendría que escribir también, no solo eliminar (de lo contrario, algunos nodos añadidos podrían perderse). Mi preocupación con esto es que puede ser demasiado costoso (SQS tiene un costo adicional) o que el rendimiento no es lo suficientemente bueno. Hacer una concurrencia optimista podría resolver eso. Sin embargo, nunca he implementado algo así antes, así que estoy un poco preocupado de que introduzca algún error extraño (ya que es difícil probar problemas de simultaneidad). – Yrlec

+0

@Yrlec, no sabía que Amazon tiene * SQS *. Estaba pensando más en un servicio * WCF * independiente en * MSMQ *, o * Mass Transit * o * NServiceBus *. Lo bueno de las colas es que puede tener un único subproceso para hacer colas y varios trabajadores para desminarlo (cada solicitud es una operación atómica independiente que no comparte datos, si eso es posible). Tal vez también puedas probar técnicas de bloqueo para realizar las operaciones que necesitan sincronización, lo que es mucho más problemático. – oleksii

0

Se podría implementar su propio mecanismo de bloqueo como un servicio en su EC2 y usarlo para sincronizar accesos a S3. En este caso, puede almacenar recuentos de monitores en su S3 (por separado o no)

+0

En este caso, debe cumplir con el rendimiento de los servicios de Amazon en su implementación, o probablemente sea un cuello de botella en su cadena –