concurrency primary-key azure-storage auto-increment identity-column

concurrency - Incremento automático en el almacenamiento de tablas de Azure



primary-key azure-storage (5)

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.

Por lo tanto, estoy buscando una manera de usar un entero auto-incrementado, 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).

Ha habido algunas discusiones sobre el tema, por ejemplo, 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 realmente difíciles de depurar y detectar, me siento un poco incómodo con la implementación de esto por mi cuenta. Mi pregunta es, por lo tanto, si hay una improbación bien probada de esto?


La solución que encontré que evita las identificaciones duplicadas y le permite autoincrementarla es

  1. bloquear (arrendar) un blob y dejar que actúe como una puerta lógica.

  2. Luego lee el valor.

  3. Escribe el valor incrementado

  4. Liberar el contrato de arrendamiento

  5. Usa el valor en tu app / tabla

Luego, si su rol de trabajador se bloqueara durante ese proceso, entonces solo tendría una identificación faltante en su tienda. En mi humilde opinión que es mejor que los duplicados.

Aquí hay un ejemplo de código y más información sobre este enfoque de Steve Marx.


No lo he implementado todavía, pero estoy trabajando en ello ...

Podría sembrar una cola con sus siguientes ID para usar, luego simplemente eliminarlos 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 los números enteros, puede hacer que un trabajador se despierte de vez en cuando y se asegure de que la cola todavía tenga números enteros. También puede tener una cola int utilizada que el trabajador pueda verificar para vigilar su uso.

También puede conectar a ese trabajador, de modo que si la cola estuviera vacía cuando su código necesitara una identificación (por casualidad) podría interrumpir la siesta del trabajador para crear más claves lo antes posible.

Si esa llamada falla, necesitaría una forma de (decirle al trabajador que va a hacer el trabajo por ellos (bloquear), luego hacer el trabajo de los trabajadores para obtener la próxima ID y desbloquear)

  1. bloquear
  2. obtener la última clave creada de la tabla
  3. incrementar y guardar
  4. desbloquear

luego usa el nuevo valor.


Si realmente necesita evitar las guías, ¿ha considerado usar algo basado en la fecha / hora y luego aprovechar 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 período de tiempo suficientemente pequeño para controlar la concurrencia.

Por supuesto, debe preguntarse a sí mismo, al precio de la fecha en Azure, si realmente vale la pena el esfuerzo extra por evitar un Guid (suponiendo que un Guid solo funcionará).



Para todos los que lo encuentren en la búsqueda, hay una mejor solución. El tiempo mínimo para el bloqueo de la mesa es de 15 segundos , eso es horrible. No lo use si desea crear una solución verdaderamente escalable. Utilice 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 WITH ETag especificado (de la consulta de lectura).

Si la última operación ( InsertOrUpdate ) tiene éxito, entonces tiene una ID nueva, única y auto-incrementada. Si falla (excepción con HttpStatusCode == 412), significa que algún otro cliente lo cambió. Por lo tanto, repita 1,2 y 3. El tiempo habitual para Read+InsertOrUpdate es menos de 200 ms . Mi utilidad de prueba con fuente en github .