2010-03-13 4 views
5

(me doy cuenta de que mi título es pobre. Si después de leer la pregunta tiene una mejora en mente, edítela o dígame y la cambiaré)¿Hay un patrón estándar para escanear una tabla de trabajos ejecutando algunas acciones?

Tengo el escenario relativamente común de un tabla de trabajo que tiene 1 fila para algo que necesita hacerse. Por ejemplo, podría ser una lista de correos electrónicos para enviar. La tabla es como la siguiente:

ID Completed TimeCompleted anything else... 
---- --------- ------------- ---------------- 
1  No       blabla 
2  No       blabla 
3  Yes   01:04:22 
... 

estoy buscando ya sea para una práctica/patrón estándar (o código - C#/SQL Server preferido) de forma periódica "de barrido" (utilizo el término "escaneo" de manera muy informal) esta tabla, encontrar los ítems no completados, realizar la acción y luego marcarlos completados una vez que se hayan realizado correctamente.

Además del proceso básico para llevar a cabo lo anterior, estoy considerando los siguientes requisitos:

  • me gustaría algún medio de "escalamiento lineal", por ejemplo, ejecutar múltiples "procesos de trabajo" simultáneamente o enhebrar o lo que sea. (Es sólo una idea específica técnica -. Estoy asumiendo que como resultado de este requisito, necesito algún método de marcar un elemento como "en curso" para evitar la acción de intentar varias veces)
  • Cada elemento de la tabla debe solo se ejecutará una vez.

Algunos otros pensamientos:

  • no estoy particularmente preocupado por la aplicación que se realiza en la base de datos (por ejemplo, en T-SQL o código PL/SQL) frente a un cierto código programa externo (por ejemplo, un ejecutable independiente o alguna acción provocada por una página web) que se ejecuta contra la base de datos
  • ya sea el "hacer la acción" se hace parte sincrónica o asincrónica no es algo que estoy considerando como parte de esta pregunta.
+0

suena como una cola de proceso ... –

+0

a veces llamada cola de productor/consumidor ... –

Respuesta

1

Si está dispuesto a considerar tecnologías que no son de base de datos, la mejor (aunque no la única) solución es message queuing (a menudo junto con una base de datos que contiene los detalles de cada trabajo). Las colas de mensajes proporcionan una gran cantidad de funcionalidad, pero el flujo de trabajo básico es simple:

1) Un proceso pone un 'anuncio de trabajo' (tal vez sólo un id) en una cola.

2) Otro proceso mantiene un ojo en la cola. Realiza un sondeo de la cola de trabajos y extrae trabajos que encuentra fuera de la cola, uno a la vez, en el orden en que se recibieron. Los elementos que ha retirado de la cola se marcan como 'en progreso': ya no están disponibles para otros procesos.

3) Para flujos de trabajo críticos, puede realizar una lectura transaccional; en el caso de una falla del sistema, la transacción se retrotrae y el mensaje aún está en la cola. Si hay algún otro tipo de excepción (como un tiempo de espera durante una lectura de base de datos), puede simplemente reenviar el mensaje a una cola de error especial.

La manera más simple de escalar esto es hacer que su proceso de lectura distribuya múltiples hilos para manejar los trabajos que saca de la cola. Alternativamente, puede escalar usando múltiples procesos de lectura, que pueden estar en servidores separados.

. La compatibilidad con .NET incluye Microsoft Message Queue y Windows Communication Foundation o las clases en el espacio de nombres System.Messaging. Requiere cierta configuración y configuración (debe crear las colas y configurar los permisos), pero vale la pena.

+0

+1 para recomendar una cola específica. No lo hice porque soy un programador de Java y no creo que una recomendación de JMS sea muy apreciada en una pregunta etiquetada 'C#'. :) –

+0

@Jeff - Sin embargo, con respecto al # 2, creo que es lo mismo que estoy preguntando en la pregunta. En otras palabras, la lógica de sondear y seleccionar un artículo, mientras apoyo la concurrencia, es el problema que estoy tratando de resolver, sin tener muchos problemas de contención y/o bloqueo, etc. Con respecto a su afirmación, " Alternativamente, puede escalar usando múltiples procesos de lectura, que pueden estar en servidores separados ". Supongo que volveré a cómo lo haría evitando. Por lo tanto, es más el "cómo" implementaría estas opciones al tiempo que evitaría los problemas anteriores. – Howiecamp

+0

¡Lo siento, mi respuesta no fue clara al respecto! Las colas de mensajes admiten la concurrencia en este sentido: sincronizan el acceso al contenido de la cola: solo un proceso puede leer un mensaje dado a la vez. Es una de las características definitorias de las colas de mensajes y una de las principales razones para usarlas en lugar de escribir código para extraer trabajos de una tabla de base de datos. –

1

Para escalar, es posible que desee considerar buscar trabajos que estén listos y luego agregarlos a una cola de mensajes. De esta forma, múltiples consumidores pueden leer trabajos listos fuera de la cola. Marcado de puestos de trabajo como "en curso" podría ser tan simple como poner ese valor en la columna completado, o se puede añadir una columna TimeStarted y tienen un período de tiempo de espera predeterminado antes de un trabajo se pondrá a cero y ser elegible para otro subproceso de trabajo para el proceso . (Este último enfoque supone el procesamiento fallado si el tiempo especificado sin el trabajo de completar. A falta después de una cierta cantidad de intentos deberían dar lugar a la inspección manual de ese trabajo.) El mismo proceso demonio que explora la base de datos de puestos de trabajo listo para agregar a la cola puede busca trabajos que han expirado.

+0

@Bill - ¿Cómo puedo determinar qué registros lee un consumidor determinado? Si quiero apoyar a varios consumidores, probablemente no me gustaría que cada uno de ellos obtenga * todos * registros no completados, ya que esto esencialmente limitaría la situación a un solo consumidor. En otras palabras, si un consumidor determinado hizo una "IDENTIFICACIÓN SELECCIONADA de la tabla WHERE Completed = No" y luego inmediatamente establece esos registros en "en progreso", no habría registros para que otro consumidor los agarre. – Howiecamp

+0

@Bill - ¿Tal vez solo quisiera que el consumidor elija un número "razonable" de registros por ejecución? – Howiecamp

+0

Desde el punto de vista de la cola, el hilo daemon sería un productor. Su trabajo sería verificar periódicamente la base de datos para ver si hay trabajos listos y agregarlos a la cola. Luego tiene múltiples consumidores que revisan la cola y cada uno toma un trabajo a la vez para procesar. –

1

Si está utilizando SQL 2005+, es posible que desee investigar Service Broker. Está bastante diseñado para esto.

Cuestiones relacionadas