Strategia per aggiornare l'indice di ricerca dopo aver corretto la generazione dell'indice

0

Descrizione della situazione

Sto lavorando a un'applicazione (basata su Spring Framework) utilizzando un indice di ricerca (lucene se ciò è importante) per rendere ricercabile il contenuto di tale applicazione. I documenti vengono aggiunti / aggiornati in quell'indice ogni volta che il contenuto dell'applicazione viene modificato e cancellato ogni volta che viene eliminato il contenuto corrispondente.

Abbiamo riscontrato un bug in cui il trigger per l'aggiornamento di un documento sulle modifiche del contenuto non funzionava in alcuni casi. Pertanto alcuni dei documenti contengono valori non validi (scaduti). Questo problema è stato risolto, quindi le modifiche future verranno scritte correttamente nell'indice.

Tuttavia, voglio correggere i documenti non validi nell'indice e vorrei sapere quale sarebbe la migliore strategia per farlo. Le condizioni importanti sono:

  • Il ricalcolo dell'indice completo richiede più ore e l'applicazione viene ridistribuita regolarmente come parte della distribuzione continua. Pertanto, è necessario che l'applicazione venga chiusa tra il processo di aggiornamento.
  • La maggior parte dei documenti non è valida.
  • Non sono in grado di riconoscere documenti non validi basati solo sull'indice. Ciò richiederebbe molte informazioni da un database.
  • I valori non validi dei documenti non sono particolarmente importanti. Il campo più pertinente (il nome) non è stato influenzato dal bug. Pertanto, anche i documenti con valori non validi funzionano correttamente nella maggior parte dei casi d'uso.
  • Vorrei una soluzione che funzionasse anche per problemi futuri.

Penso che un caso simile si verifichi se estendiamo l'indice nelle versioni future, ad es. aggiungi un campo. Ciò richiederebbe l'aggiornamento di tutti i documenti per aggiungere il campo, mentre il caso d'uso principale dell'indice funzionerà anche senza quel campo.

Possibile soluzione

La mia idea è di aggiungere un campo versione ai documenti. Quindi aggiungerei un processo che esegue tutti i pochi minuti, recupera un batch di documenti con una versione precedente (o senza alcuna versione per l'esecuzione iniziale), ricalcola i campi richiesti, imposta il campo versione sulla versione corrente e aggiorna il documento in l'indice.

Professionisti di questa soluzione:

  • Se l'aggiornamento viene interrotto, l'applicazione riconosce quali documenti sono già stati corretti e quali no.
  • Questa informazione è memorizzata all'interno dell'indice, quindi dove appartiene (avevo alcune idee prima di dove avrei archiviato le informazioni nel database).

Con di questa soluzione:

  • Dovrà aggiornare ogni documento, anche se non ha valori non validi.

La mia domanda

Questa è una soluzione ragionevole per il problema? Ci sono approcci migliori per fare questo? Non sono riuscito a trovare nulla su come risolvere questo problema e nessuna informazione sul fatto che sia una buona idea aggiungere una versione ai tuoi documenti.

Forse sto anche pensando troppo alla situazione e una soluzione molto più semplice è possibile?

    
posta lucash 04.08.2017 - 15:14
fonte

3 risposte

2

TL; DR: Puoi fare le cose più velocemente.

Ho avuto un problema simile. Risulta, con Lucene, ricostruire l'intero indice usando il codice ottimizzato per esso, partendo da zero, usando una query SELECT field1, field2 FROM table senza clausola where, era abbastanza veloce. Il motivo per il rapido tempo di esecuzione era probabilmente che il codice di interfacciamento di Lucene non aveva bisogno di preoccuparsi delle query di Lucene parallele e l'istruzione SQL poteva usare una scansione sequenziale.

Per questo motivo abbiamo avuto i metodi indexOne e indexAll , scritti separatamente.

Non sono sicuro che sia abbastanza veloce per il tuo caso, ma dovresti dare un'occhiata alle API di Lucene, vedere che tipo di caratteristiche che migliorano le prestazioni: non sincronizzare per ogni singolo elemento? Non ti importa delle query parallele? Ricostruisci l'indice da zero? Non ricordo quali caratteristiche dell'API di Lucene abbiamo utilizzato per ottenere le ottime prestazioni perché erano 8 anni fa, ma ricordo che le prestazioni di indexAll erano molto meglio di indexOne .

Naturalmente, questo tipo di approccio richiede alcuni tempi di inattività. Ma con un'ottimizzazione abbastanza buona, forse puoi spingere il tempo di fermo a un livello accettabile, da ore a minuti minuti.

Se non riesci a ridurre il tempo di inattività a un livello accettabile, la tua unica soluzione è un indicizzatore in background. Avevamo una tabella denominata indexqueue nel database e conteneva identificatori di oggetto. L'indicizzatore in background preleva regolarmente le righe da questa tabella e reindicizza solo le righe recuperate. Quindi inserisci semplicemente ogni identificatore di oggetto nella tabella indexqueue e attendi che tutto venga reindicizzato.

Per quanto riguarda il numero di record, abbiamo avuto milioni di record. Il tuo problema di centinaia di migliaia di record, con il leggero progresso delle prestazioni del computer in 8 anni e il grande progresso nella quantità di memoria del computer, è minuscolo in confronto ai milioni di record di problemi che abbiamo avuto. In passato utilizzavamo dischi rigidi e oggi i server utilizzano SSD!

Sono abbastanza sicuro che puoi reindicizzare migliaia di righe al secondo, se fai le cose in modo ottimale, a meno che, naturalmente, ogni riga non abbia una sorta di corpo di testo di 1000 pagine di testo. Questo rende centinaia di migliaia di righe al minuto.

    
risposta data 02.01.2018 - 14:56
fonte
1

Anche se introduci qualcosa come il tuo campo di versione nei documenti, non puoi sapere in anticipo quale tipo di bug ci sarà in futuro. Ce n'è sempre uno che rende necessario ricostruire l'intero indice. Quindi dovresti cercare una strategia che lo renda possibile.

Hai scritto

Recalculating the complete index requires multiple hours and the application is redeployed regularly as part of continuous deployment. Therefore it must be expected that the application is shut down in between the updating process.

e questo è in realtà il problema ed è la soluzione: non appena si disaccoppia l'applicazione principale (e le sue distribuzioni) dal processo / programma che ricalcola l'indice, il problema viene risolto. Quindi è possibile arrestare e ridistribuire l'applicazione senza arrestare il processo di ricalcolo.

Naturalmente, probabilmente dovrai prendere alcune misure aggiuntive come

  • progettare il ricalcolo in modo che non interferisca con la funzione di ricerca dell'applicazione principale. Ad esempio, è possibile innanzitutto eseguire un processo di lunga durata che calcoli le modifiche necessarie all'indice senza applicarle e applicare le modifiche in seguito (che richiede probabilmente solo una frazione del tempo totale, se interessano solo una piccola parte del tempo voci di indice)

  • registra se il ricalcolo è stato applicato con successo, quindi non viene applicato una seconda volta

  • e, se necessario: prendere in considerazione l'implementazione di una strategia per riavviare il ricalcolo dell'indice in caso di interruzione nel punto in cui è stata interrotta.

risposta data 02.01.2018 - 07:40
fonte
0

Ecco un paio di soluzioni alternative al tuo problema:

  1. Potresti utilizzare la strategia distribuzione blu-verde con il tuo indice di ricerca. Fondamentalmente si dovrebbe creare periodicamente l'indice fresco nella distribuzione in standby. Quando l'indice ha finito di costruire, cambieresti per utilizzare lo standby in produzione e il tuo indice live in precedenza diventerebbe il nuovo standby.
  2. Puoi utilizzare l'indice di ricerca solo per la ricerca e cercare i documenti e gli attributi effettivi dal tuo database. Quindi i tuoi risultati di ricerca restituirebbero l'ID dell'articolo e tu invierai le copie aggiornate per l'attributo di ciascun articolo.
risposta data 05.08.2017 - 01:38
fonte

Leggi altre domande sui tag