Implementa Lucene sullo stack esistente.NET/SQL Server con più server web



sql-server lucene.net (1)

Voglio dare un'occhiata a Lucene per una soluzione di ricerca a testo completo per un sito che attualmente gestisco. Il sito è interamente costruito su tecnologie SQL Server 2008 / C # .NET. I dati che sto cercando di indicizzare sono in realtà abbastanza semplici, con solo un paio di campi per record e solo uno di quei campi è effettivamente ricercabile.

Non mi è chiaro quale sia il set di strumenti migliore che devo usare o quale sia l'architettura che dovrei usare. In particolare:

  1. Dove dovrei inserire l'indice? Ho visto persone consigliare di metterlo sul server web, ma ciò sembrerebbe inutile per un gran numero di server web. Sicuramente la centralizzazione sarebbe meglio qui?

  2. Se l'indice è centralizzato, come lo interrogherei, dato che vive solo sul filesystem? Dovrò effettivamente metterlo su una condivisione di rete che tutti i server web possono vedere?

  3. Esistono strumenti preesistenti che riempiranno in modo incrementale un indice Lucene su una pianificazione, estraendo i dati da un database SQL Server? Farei meglio a fare il mio servizio qui?

  4. Quando chiedo l'indice, dovrei cercare di recuperare un gruppo di ID dei record che poi torno al DB per il record attuale, o dovrei mirare a ottenere tutto ciò di cui ho bisogno per la ricerca direttamente dall'indice ?

  5. Vale la pena provare a implementare qualcosa come Solr in questo ambiente di sapori? Se è così, probabilmente gli darei il proprio * nix VM ed eseguirlo su Tomcat. Ma non sono sicuro di cosa Solr mi comprerebbe in questo caso.

https://src-bin.com


Answer #1

Risponderò un po 'in base a come abbiamo scelto di implementare Lucene.Net qui su e alcune lezioni che ho imparato lungo il percorso:

Dove dovrei inserire l'indice? Ho visto persone consigliare di metterlo sul server web, ma ciò sembrerebbe inutile per un gran numero di server web. Sicuramente la centralizzazione sarebbe meglio qui?

  • Dipende dai tuoi obiettivi qui, abbiamo avuto un livello web severamente sottoutilizzato (circa il 10% della CPU) e un database sovraccarico che esegue la ricerca FullText (circa il 60% della CPU, lo volevamo più basso). Caricando lo stesso indice su ogni livello Web, utilizziamo queste macchine e abbiamo una tonnellata di ridondanza , possiamo comunque perdere 9 server Web su 10 e mantenere attiva la rete di Stack Exchange se necessario. C'è uno svantaggio in questo, è molto IO (leggi) intensivo per noi, e il livello web non è stato acquistato con questo in mente (questo è spesso il caso nella maggior parte delle aziende). Sebbene funzioni correttamente, continueremo ad aggiornare il nostro livello Web agli SSD e ad implementare altri bit lasciati fuori dalla porta .Net per compensare questa carenza di hardware (ad esempio, NIOFSDirectory ).
  • L'altro lato negativo se indicizziamo tutti i nostri database n volte per il livello Web, ma per fortuna non siamo affamati di larghezza di banda della rete e il caching dei server SQL memorizza i risultati rendendo ogni volta un'operazione di indicizzazione delta molto rapida. Con un gran numero di server web, solo questo potrebbe eliminare questa opzione.

Se l'indice è centralizzato, come lo interrogherei, dato che vive solo sul filesystem? Dovrò effettivamente metterlo su una condivisione di rete che tutti i server web possono vedere?

  • Puoi eseguire una query su una condivisione file in entrambi i casi, ma assicurati che solo uno sia indicizzato alla volta ( write.lock , il meccanismo di blocco della directory lo garantirà ed errore quando proverai più IndexWriter in una volta).
  • Tieni a mente le mie note sopra, questo è un intento di IO quando molti lettori stanno volando in giro, quindi hai bisogno di un'ampia larghezza di banda per il tuo negozio, a meno di almeno iSCSI o fibra SAN, sarei cauto con questo approccio su uso elevato (centinaia di migliaia di ricerche al giorno).
  • Un'altra considerazione riguarda il modo in cui si aggiornano / avvisano i server Web (o qualsiasi livello lo stia interrogando). Quando IndexReader una pass di indicizzazione, devi riaprire i tuoi IndexReader per ottenere l'indice aggiornato con nuovi documenti. Utilizziamo un canale di messaggistica redis per avvisare chiunque si interessi che l'indice sia aggiornato ... qualsiasi meccanismo di messaggistica funzionerebbe qui.

Esistono strumenti preesistenti che riempiranno in modo incrementale un indice Lucene su una pianificazione, estraendo i dati da un database SQL Server? Farei meglio a fare il mio servizio qui?

  • Sfortunatamente non ci sono nessuno che io conosca, ma posso condividere con voi come mi sono avvicinato a questo.
  • Durante l'indicizzazione di una tabella specifica (simile a un documento in Lucene), abbiamo aggiunto una rowversion a quella tabella. Quando indichiamo selezioniamo in base all'ultima rowversion (un datatype rowversion , ritirato come bigint ). Ho scelto di memorizzare l'ultima data di indice e l'ultima rowversion indicizzata sul file system tramite un semplice file .txt per una ragione: tutto il resto in Lucene è memorizzato lì. Questo significa che se c'è un problema di grandi dimensioni, puoi semplicemente eliminare la cartella contenente l'indice e la prossima passata di indicizzazione si ripristinerà e avrà un indice aggiornato, basta aggiungere un codice per gestire il fatto che non c'è niente che significa "indicizza tutto" .

Quando chiedo l'indice, dovrei cercare di recuperare un gruppo di ID dei record che poi torno al DB per il record attuale, o dovrei mirare a ottenere tutto ciò di cui ho bisogno per la ricerca direttamente dall'indice ?

  • Questo dipende molto dai tuoi dati, per noi non è davvero fattibile memorizzare tutto nell'indice (non è raccomandato). Quello che suggerisco è di memorizzare i campi per i risultati della ricerca nell'indice, e con ciò intendo ciò che è necessario per presentare i risultati della ricerca in un elenco, prima che l'utente clicchi per andare al pieno [inserire tipo qui].
  • Un'altra considerazione è la frequenza con cui i tuoi dati stanno cambiando. Se molti campi su cui non si sta effettuando la ricerca cambiano rapidamente, è necessario indicizzare nuovamente tali righe (documenti) per aggiornare l'indice, non solo quando il campo in cui si sta effettuando la ricerca cambia.

Vale la pena provare a implementare qualcosa come Solr in questo ambiente di sapori? Se è così, probabilmente gli darei il proprio * nix VM ed eseguirlo su Tomcat. Ma non sono sicuro di cosa Solr mi comprerebbe in questo caso.

  • Certo che c'è, è la ricerca centralizzata di cui parli (con un numero elevato di ricerche potresti ancora raggiungere un limite con una configurazione VM, tieni d'occhio questo). Non lo abbiamo fatto perché ha introdotto molta (riteniamo) complessità ingiustificata nel nostro stack tecnologico e nel processo di creazione, ma per un numero maggiore di server Web ha molto più senso.
  • Cosa ti compra? principalmente le prestazioni e un server di indicizzazione dedicato. Invece di n server che eseguono la scansione di una condivisione di rete (in competizione anche per l'I / O), possono colpire un singolo server che gestisce solo richieste e risultati sulla rete, non eseguendo la scansione dell'indice, ovvero molti più dati che vanno avanti e indietro ... questo sarebbe locale sui server Solr. Inoltre, non stai colpendo il tuo server SQL tanto più che un numero inferiore di server sta indicizzando.
  • Quello che non ti compra è la stessa ridondanza, ma dipende da te quanto sia importante questo. Se riesci a operare bene con la ricerca degradata o senza di essa, fallo semplicemente gestire dall'app. Se non è possibile , un server Solr di backup o più può anche essere una soluzione valida ... ed è possibile conservare un altro stack software.




lucene.net