Operazioni Strategia della coda di lavoro

2

Sto lavorando su un'applicazione che richiede l'approvazione manuale delle richieste inviate dai clienti. Ora diciamo che ci sono 10 persone coinvolte in questa operazione e ognuna di esse ha una pagina web davanti a loro che serve una richiesta dopo l'altra. Il problema che sto cercando di risolvere è che la stessa richiesta del cliente non dovrebbe essere servita a più persone di operazioni per evitare la duplicazione del lavoro. In questo momento lo risolvo nel modo seguente:

Tabella MySQL:

CREATE TABLE customer_request
(
   id             int PRIMARY KEY AUTO_INCREMENT,
   request_type   tinyint NOT NULL,
   request_body   varchar(100) NOT NULL,
   insert_date    timestamp DEFAULT current_timestamp,
   lock_status    tinyint,
   lock_time      datetime
);

Ogni volta che invio una richiesta a un operatore, imposto la colonna lock_status su 1 e il lock_time su now() . Quando la richiesta è stata elaborata (accettata / rifiutata / escalizzata) il blocco è stato rilasciato.

In secondo luogo c'è un thread in background che cancella qualsiasi blocco più vecchio di x minuti.

Penso che ci dovrebbe essere un modo migliore per gestire questo. Qualsiasi aiuto è molto apprezzato.

    
posta SNAG 20.08.2015 - 08:34
fonte

2 risposte

3

Penso che la soluzione sia valida in generale. È un esempio di blocco pessimistico e inestimabile se si desidera risparmiare risorse o elaborare dati con contesa elevata.

Nel tuo caso, poiché lo scopo di questi operatori è esclusivamente quello di elaborare le richieste dei tuoi clienti, sembra probabile una contesa. Quindi, stai bloccando il record assicurandoti che non venga visualizzato nelle query di altri operatori. Cioè, puoi distinguere i record bloccati e "disponibili" usando il tuo campo lock_status .

IMO manca una cosa. Questo è chiaramente un record memorizzato in un database (ad esempio, non si rimuovono richieste da una coda o alcun bus di messaggi interni, ad esempio JMS, MQ). Pertanto, si desidera assicurarsi che il record bloccato non sia stato bloccato durante il tempo in cui è stato acquisito (problema di aggiornamento perso).

Quindi, raccomanderei un ulteriore campo "lock" che è effettivamente un blocco sul record. Questo per garantire che solo tu abbia bloccato il record in anticipo. Solitamente questo sarebbe chiamato semplicemente sulla falsariga di "lock" o "version" ma per evitare confusione con lock_status lo chiamerò "record_lock".

Quando esegui una query su customer_query , includi record_lock nella query. Quindi, quando esegui l'aggiornamento per aggiornare lock_status e lock_time il tuo aggiornamento dovrebbe includere anche una nuova clausola where where record_lock = /*the value retrieved during your query*/

Questo garantisce che tu sia l'unico operatore che aggiorna quel record e che non è cambiato da quando hai letto. Come sai che non è cambiato? La clausola where stabilisce che record_lock è uguale a quando lo hai interrogato. Cosa lo avrebbe cambiato? Tu! Quando esegui l'aggiornamento di cui sopra, dovresti includere anche un aggiornamento di record_lock in un nuovo valore (sequenza, record-hash, data / ora derivata? Dipende da te).

Per riepilogare, leggi record_lock sulla tua query e assicurati che non sia cambiato quando aggiorni (la clausola where). Includi l'aggiornamento alla record_lock nell'aggiornamento stesso per indicare che l'hai modificato, quindi invalida chiunque altro cerchi di bloccare questo record. Una volta bloccato, dovrebbe essere tuo per lavorare con la fornitura di questi record tutti rispettano il tuo locked_status per interrogare.

Esempio:

select request_id, lock_status, lock_time, record_lock
  from customer_request
  where lock_status = 0;
...
update customer_request
  set lock_status = 1, 
      lock_time = ...,
      record_lock = <somenewvalue>
  where request_id = <requestid>
    and record_lock = <originalrecordlock>;

Implicazioni:

  • Il blocco pessimistico richiede un sovraccarico nella gestione del blocco.
  • Esiste il rischio di deadlock se si richiede l'acquisizione di più blocchi.
  • tre è il rischio che un record non venga elaborato e indirizzato con la soglia di timeout.

Note:

  • Lo chiamerei solo "stato" se si tratta di un vero e proprio campo di stato. Se è solo un binario vero / falso, basta chiamarlo "bloccato", "locked_flag", "is_locked" o qualsiasi altra cosa secondo i tuoi standard.
  • Interessante a parte ... Quando aggiorniamo lock_status, questo aggiornamento utilizza il blocco ottimistico (utilizzando un campo di blocco record). Quando elabori il customer_request, utilizziamo il blocco pessimistico (abbiamo bloccato il record in anticipo).
risposta data 20.08.2015 - 09:31
fonte
2

Quello di cui parli si chiama blocco offline pessimista . Esistono diversi modi per implementarli: il più comune è simile al modo in cui lo si propone, tranne che invece di un'attività in background per cancellare i blocchi scaduti, basta semplicemente cancellarli quando si tenta di bloccarli e sono troppo vecchi.

    
risposta data 20.08.2015 - 09:36
fonte

Leggi altre domande sui tag