10

Oye. Uso retrayed_job para el procesamiento en segundo plano. Tengo 8 CPU del servidor, MySQL y empiezo 7 delayed_job procesaRieles con múltiples retardos_trabajos: tablas de bloqueo

RAILS_ENV=production script/delayed_job -n 7 start 

P1: Me pregunto ¿es posible que 2 o más procesos delayed_job comenzar a procesar el mismo proceso (el mismo registro en fila la base de datos retrayed_jobs). Comprobé el código del complemento de retraso de trabajo pero no puedo encontrar la directiva de bloqueo de una manera que debería ser (sin bloqueo de tabla o SELECCIONAR ... PARA ACTUALIZAR).

Creo que cada proceso debe bloquear la tabla de la base de datos antes de ejecutar una ACTUALIZACIÓN en la columna lock_by. Bloquean el registro simplemente actualizando el campo locked_by (UPDATE demoyed_jobs SET locked_by ...). ¿Es eso realmente suficiente? No se necesita bloqueo? ¿Por qué? Sé que UPDATE tiene mayor prioridad que SELECT, pero creo que esto no tiene el efecto en este caso.

Mi comprensión de la situación del multy-roscado es:

Process1: Get waiting job X. [OK] 
Process2: Get waiting jobs X. [OK] 
Process1: Update locked_by field. [OK] 
Process2: Update locked_by field. [OK] 
Process1: Get waiting job X. [Already processed] 
Process2: Get waiting jobs X. [Already processed] 

creo que en algunos casos más puestos de trabajo pueden obtener la misma información y pueden comenzar a procesar el mismo proceso.

Q2: ¿Hay 7 números demorados en un buen número para el servidor 8CPU? Por qué sí/no

Thx 10x!

Respuesta

11

Creo que la respuesta a su pregunta es en la línea 168 de 'lib/delayed_job/job.rb':

self.class.update_all(["locked_at = ?, locked_by = ?", now, worker], ["id = ? and (locked_at is null or locked_at < ?)", id, (now - max_run_time.to_i)]) 

Aquí la actualización de la fila sólo se realiza, si no hay otro trabajador ya ha bloqueado el trabajo y esto se verifica si la tabla se actualiza. No es necesario un bloqueo de tabla o similar (que, por cierto, reduciría de forma masiva el rendimiento de su aplicación), ya que su DBMS garantiza que la ejecución de una única consulta quede aislada de los efectos de otras consultas. En su ejemplo, Process2 no puede obtener el bloqueo para el trabajo X, ya que actualiza la tabla de trabajos si y solo si no se bloqueó antes.

A su segunda pregunta: Depende. En un servidor de 8 CPU. que está dedicado para este trabajo, 8 trabajadores son un buen punto de partida, dado que los trabajadores tienen un solo hilo, debe ejecutar uno por cada núcleo. Dependiendo de su configuración, más o menos trabajadores son mejores. Depende mucho de tus trabajos. Aproveche su trabajo ventaja de núcleos mutiple? ¿O su trabajo espera la mayor parte del tiempo para obtener recursos externos? Tienes experimentar con diferentes configuraciones y echar un vistazo a todos los recursos involucrados.

+0

¿Entonces usted está diciendo que cada proceso es de estilo atómico y es seguro? – xpepermint

+0

Lo que creo que falta aquí es SELECCIONAR ... PARA ACTUALIZAR. ? – xpepermint

+0

La consulta es atómica. Por lo tanto, si ejecuta la consulta 'UPDATE jobs SET locked_at = '..', locked_by = 1 WHERE id = 12 y (locked_at es nulo o locked_at <'..')', entonces locked_at y locked_by solo se actualizan si no hay otro bloqueo válido El DBMS primero verifica la condición where y luego ejecuta la actualización y asegura que la fila no se modifique en el medio. Por lo tanto, no puede sobreescribir un bloqueo existente. – gregor

Cuestiones relacionadas