16

Actualmente estoy desarrollando una aplicación para Azure Table Storage. En esa aplicación tengo una tabla que tendrá relativamente pocas inserciones (un par de miles/día) y la clave principal de estas entidades se usará en otra tabla, que tendrá miles de millones de filas.Incremento automático en Azure Table Storage

Por lo tanto, estoy buscando una forma de utilizar un entero autoincrementado, en lugar de GUID, como clave principal en la tabla pequeña (ya que ahorrará mucho almacenamiento y la escalabilidad de las inserciones no es realmente un problema).

Hubo algunas discusiones sobre el tema, p. en http://social.msdn.microsoft.com/Forums/en/windowsazure/thread/6b7d1ece-301b-44f1-85ab-eeb274349797.

Sin embargo, dado que los problemas de concurrencia pueden ser muy difíciles de depurar y detectar, me siento un poco incómodo al implementar esto por mi cuenta. Mi pregunta es, por lo tanto, si hay un impelente bien probado de esto?

+0

Si realmente te preocupa, ¿tienes una tabla en SQL Azure que genere los valores de identidad? – Andrew

+0

Esa es una muy buena sugerencia. Sin embargo, eso me obligaría a configurar mi servidor SQL, porque Azure SQL Data Services no admite columnas de identidad: http://www.shanmcarthur.net/cloud-services/design-strategies-for-Azure-and-SDS . – Yrlec

Respuesta

4

no he implementado esto todavía, pero estoy trabajando en ello ...

Se podría sembrar una cola con los siguientes identificadores de usar, y luego simplemente recogerlos de la cola cuando los necesite.

Debe mantener una tabla para contener el valor del mayor número agregado a la cola. Si sabe que no va a utilizar una tonelada de enteros, puede hacer que un trabajador se despierte cada cierto tiempo y asegurarse de que la cola todavía contenga números enteros. También podría tener una cola int usada que el trabajador podría verificar para controlar el uso.

También podría enganchar a ese trabajador así que si la cola estaba vacía cuando su código necesitaba una identificación (por casualidad) podría interrumpir la siesta del trabajador para crear más claves lo antes posible.

Si esa llamada fallidos que se necesita una manera de (decirle al trabajador que se va a hacer el trabajo por ellos (bloqueo), y luego hacer trabajar a los obreros de conseguir el siguiente ID y desbloqueo)

  1. bloquear
  2. obtener la última tecla creado a partir de la tabla
  3. incremento y guardar el
  4. desbloqueo

a continuación, utilizar el nuevo valor.

+1

Pero, ¿cómo garantiza una cola que no se creen identificadores duplicados? Lo que puedo entender de http://download.microsoft.com/download/5/2/D/52D36345-BB08-4518-A024-0AA24D47BD12/Windows%20Azure%20Queue%20-%20Dec%202008.docx es que mensaje se agrega a la cola de nuevo si un proceso de trabajo falla al procesar el mensaje de cola. Por lo tanto, necesita hacer que el trabajo en el rol de trabajador sea idempotente. Si el mismo mensaje (es decir, el mismo ID) es utilizado por dos roles de trabajador diferentes, no veo cómo puede hacer ese idempotente. – Yrlec

+2

Si solo tiene 1 woker creando la identificación, entonces las dups se pondrán en la cola. Al sacar los identificadores de la cola, obtenga el mensaje, luego elimine el mensaje antes de usar los contenidos del mensaje (id). Eso debería garantizar que no se utilicen identificadores más de una vez. Parece que en el peor de los casos, es posible que pierda una clave, pero su singularidad aún debería ser buena. –

+0

La segunda oración anterior debería ser: "Si solo tiene 1 woker creando el id, entonces los dups no se pondrán en la cola ..." –

3

Si realmente necesita evitar las guías, ¿ha considerado usar algo basado en la fecha/hora y luego aprovechando las claves de partición para minimizar el riesgo de concurrencia.

Su clave de partición podría ser por usuario, año, mes, día, hora, etc. y la clave de fila podría ser el resto de la fecha y hora en un intervalo de tiempo suficientemente pequeño para controlar la concurrencia.

Por supuesto, tiene que preguntarse, al precio de la fecha en Azure, si evitar un Guid vale realmente todo este esfuerzo adicional (suponiendo que un Guid simplemente funcione).

4

La solución que encontraron que impide que los identificadores duplicados y le permite AutoIncrement que es

  1. lock (lease) a blob y dejar que actúan como una puerta lógica.

  2. A continuación, lea el valor.

  3. Escribir el valor incrementado

  4. Soltar el contrato de arrendamiento

  5. Usar el valor en su aplicación/table

Entonces si su rol de trabajo fueron a estrellarse durante ese proceso, entonces solo tendrías una identificación faltante en tu tienda. En mi humilde opinión, es mejor que los duplicados.

Aquí es una code sample and more information en este enfoque de Steve Marx

10

Para todos los que lo encontrará en la búsqueda, hay una solución mejor. Minimal time for table lock is 15 seconds - eso es horrible. No lo use si desea crear una solución verdaderamente escalable. Use Etag!

Cree una entidad en la tabla para ID (incluso puede nombrarla como ID o lo que sea).

1) Léelo.

2) Incremento.

3) InsertOrUpdate CONETag especificado (de la consulta de lectura).

si la última operación (InsertOrUpdate) tiene éxito, entonces usted tiene una ID nueva, única, autoincrementada. Si falla (excepción con HttpStatusCode == 412), significa que algún otro cliente lo cambió. Por lo tanto, vuelva a repetir 1,2 y 3. El horario habitual para Read+InsertOrUpdate es inferior a 200ms. Mi utilidad de prueba with source on github.

+0

Excelente idea. – PilotBob

+0

¿qué hay de usar EGT para garantizar operaciones atómicas, leer e incrementar? ¿Es esa una forma viable de hacerlo? https://docs.microsoft.com/en-gb/azure/storage/storage-table-design-guide#entity-group-transactions –

Cuestiones relacionadas