Elasticsearch In Production - Best practice per l'implementazione

Elasticsearch è un motore di ricerca altamente ottimizzato per la moderna analisi dei dati.

Elasticsearch è un fantastico motore di ricerca e analisi in tempo reale. È costruito su Apache Lucene. È distribuito, RESTful, facile da usare e altamente disponibile. I casi d'uso di Elasticsearch comprendono il potenziamento della ricerca, il monitoraggio delle transazioni e il rilevamento degli errori, la scoperta dei contenuti, l'analisi dei log, la ricerca fuzzy, l'aggregazione dei dati degli eventi, la visualizzazione dei dati. Elasticsearch e il resto dello Stack Elastico si sono dimostrati estremamente versatili e, come puoi vedere sopra i casi d'uso, esistono diversi modi per integrare Elasticsearch in ciò che il tuo prodotto sta offrendo oggi e aggiungere ulteriori informazioni ad esso.

Lo usiamo pesantemente per la ricerca e l'analisi in Botmetric, indicizziamo circa un miliardo di documenti al giorno e utilizziamo aggregazioni molto complesse per la visualizzazione dei dati in tempo reale.

Detto questo, l'avvio di un'applicazione rispetto all'esecuzione nella produzione e nella manutenzione sono totalmente diversi. Questo articolo copre molti di questi fattori dalle esperienze della vita reale e sono gli elementi comuni di base che dovresti considerare per eseguire Elasticsearch nella produzione.

Memoria:

Elasticsearch e Lucene sono scritti in Java, il che significa che devi cercare lo spazio heap e le statistiche JVM. Maggiore è l'heap disponibile per Elasticsearch, maggiore è la memoria che può utilizzare per il filtro e altre cache per aumentare le prestazioni delle query. Ma nota che troppo heap può sottoporti a lunghe pause per la raccolta dei rifiuti. Non impostare Xmx al di sopra del valore limite che la JVM utilizza per i puntatori di oggetti compressi (oops compressi); il taglio esatto varia ma è vicino a 32 GB.

Un problema comune è la configurazione di un heap troppo grande. Hai una macchina da 64 GB - e, a malincuore, vuoi dare a Elasticsearch tutti i 64 GB di memoria. Più "è meglio! Heap è sicuramente importante per Elasticsearch. È utilizzato da molte strutture di dati in memoria per garantire un funzionamento rapido. Detto questo, c'è un altro grande utente di memoria che è fuori dall'heap: cache dei file del sistema operativo.

Lucene è progettato per sfruttare il sistema operativo sottostante per la memorizzazione nella cache delle strutture di dati in memoria. I segmenti Lucene sono memorizzati in singoli file. Poiché i segmenti sono immutabili, questi file non cambiano mai. Ciò li rende molto compatibili con la cache e il sistema operativo sottostante manterrà felicemente i segmenti attivi residenti in memoria per un accesso più rapido. Questi segmenti includono sia l'indice invertito (per la ricerca full-text) sia i valori doc (per le aggregazioni). Le prestazioni di Lucene si basano su questa interazione con il sistema operativo. Ma se dai tutta la memoria disponibile all'heap di Elasticsearch, non rimarrà alcun residuo per la cache dei file del sistema operativo. Ciò può influire seriamente sulle prestazioni. La raccomandazione standard è di dare il 50% della memoria disponibile all'heap di Elasticsearch, lasciando l'altro 50% libero. Non rimarrà inutilizzato; Lucene consumerà felicemente tutto ciò che resta della cache dei file. L'heap di Elasticsearch può essere configurato seguendo le modalità,

export ES_HEAP_SIZE = 10g

o

ES_JAVA_OPTS = "- Xms10g -Xmx10g" ./bin/elasticsearch

PROCESSORE:

Elasticsearch supporta aggregazioni e query filtrate. L'esecuzione di query filtrate complesse, indicizzazione intensiva, percolazione e query rispetto agli indici richiede una CPU pesante, quindi è fondamentale raccogliere quella giusta. È necessario comprendere le specifiche della CPU e come si comportano con Java durante l'esecuzione delle query su JVM.

Ogni pool esegue un numero di thread, che può essere configurato e ha una coda. La modifica di questo non è consigliata a meno che tu non abbia requisiti molto specifici in quanto Elasticsearch esegue l'allocazione dinamica dei core.

Tipi di pool di thread:

Elasticsearch ha 3 tipi di pool di thread.

  1. Memorizzato nella cache: il pool di thread nella cache è un pool di thread senza limiti che genererà un thread se ci sono richieste in sospeso. Questo pool di thread viene utilizzato per impedire il blocco o il rifiuto delle richieste inviate a questo pool. I thread non utilizzati in questo pool di thread verranno chiusi dopo la scadenza di un keep-alive (il valore predefinito è cinque minuti). Il pool di thread nella cache è riservato per il pool di thread generico.
  2. Risolto: il pool di thread fisso contiene una dimensione fissa di thread per gestire le richieste con una coda (facoltativamente limitata) per le richieste in sospeso che non hanno thread per servirle. Il parametro size controlla il numero di thread e il valore predefinito è il numero di core 5 volte.
  3. Ridimensionamento: il pool di thread di ridimensionamento contiene un numero dinamico di thread. Questo numero è proporzionale al carico di lavoro e varia tra 1 e il valore del parametro size.

Elasticsearch divide l'uso della CPU in pool di thread di vari tipi:

  • generico: per operazioni standard come il rilevamento e il tipo di pool di thread viene memorizzato nella cache.
  • indice: per operazioni di indice / cancellazione. Il tipo di pool di thread è fisso.
  • ricerca: per operazioni di conteggio / ricerca. Il tipo di pool di thread è fisso.
  • get: per operazioni get. Il tipo di pool di thread è fisso.
  • bulk: per operazioni bulk come l'indicizzazione bulk. Il tipo di pool di thread è fisso. La migliore configurazione di documenti in blocco dipende dalla configurazione del cluster, questo può essere identificato provando più valori.
  • percolato: per percolazione. Il tipo di pool di thread è fisso.
  • Aggiorna: per le operazioni di aggiornamento. Il tipo di pool di thread è in scala.

La modifica di un pool di thread specifico può essere effettuata impostando i parametri specifici del tipo.

Maggiori informazioni https://www.elastic.co/guide/en/elasticsearch/reference/2.2/modules-threadpool.html#types

Dimensione del coccio:

Il frammento è l'unità in cui Elasticsearch distribuisce i dati all'interno del cluster. La velocità con cui Elasticsearch può spostare i frammenti durante il riequilibrio dei dati, ad es. in seguito a un errore, dipenderà dalla dimensione e dal numero di frammenti, nonché dalle prestazioni della rete e del disco.

In Elasticsearch, ogni query viene eseguita in un singolo thread per frammento. È possibile tuttavia elaborare più frammenti in parallelo, così come più query e aggregazioni sullo stesso frammento.

Ciò significa che la latenza minima della query, quando non è prevista la memorizzazione nella cache, dipenderà dai dati, dal tipo di query e dalle dimensioni del frammento. L'interrogazione di molti piccoli frammenti renderà più veloce l'elaborazione per frammento, ma poiché molte più attività devono essere messe in coda ed elaborate in sequenza, non sarà necessariamente più veloce che interrogare un numero inferiore di frammenti più grandi. Avere un sacco di piccoli frammenti può anche ridurre il throughput delle query se ci sono più query simultanee.

Ogni frammento ha dati che devono essere conservati in memoria e utilizza lo spazio dell'heap. Ciò include le strutture di dati che contengono informazioni a livello di frammento e anche a livello di segmento al fine di definire dove risiedono i dati sul disco. La dimensione di queste strutture dati non è fissa e varia in base al caso d'uso. Una caratteristica importante dell'overhead relativo al segmento è tuttavia che non è strettamente proporzionale alla dimensione del segmento. Ciò significa che segmenti più grandi hanno un sovraccarico minore per volume di dati rispetto ai segmenti più piccoli. La differenza può essere sostanziale. La scelta del giusto numero di frammenti è complicata perché non sai mai quanti documenti otterrai prima di iniziare. Avere un sacco di frammenti può essere sia buono che terribile per un cluster. La gestione di indici e frammenti può sovraccaricare il nodo principale, che potrebbe non rispondere, portando a comportamenti strani e cattivi. Allocare ai nodi master risorse sufficienti per far fronte alle dimensioni del cluster.

La cosa brutta è che il numero di frammenti è immutabile e viene definito quando si crea l'indice. Una volta creato l'indice, l'unico modo per modificare il numero di frammenti è eliminare gli indici, crearli di nuovo e reindicizzare.

replicazione

Elasticsearch supporta la replica, i dati vengono replicati tra i nodi di dati in modo che una perdita di nodo non porterebbe alla perdita di dati. Il fattore di replica predefinito è 1, ma a seconda delle esigenze del prodotto può essere aumentato. Più repliche, più i dati saranno resistenti ai disastri. Un altro vantaggio di avere più repliche è che ogni nodo contiene un frammento di replica, il che migliora le prestazioni della query poiché anche le repliche vengono utilizzate per la query.

La formula di replica utilizzata da Elasticsearch per coerenza è,

(primario + numero_di_replicas) / 2 + 1

Ottimizzazione dell'allocazione

In base ai requisiti dei dati di prodotto, possiamo classificare i dati in caldo e freddo. Agli indici a cui si accede più frequentemente di altri, possono essere allocati più nodi di dati mentre agli indici a cui si accede meno frequentemente possono essere allocate meno risorse. Questa strategia è particolarmente utile per l'archiviazione di dati di serie temporali come i registri delle applicazioni (ad es. ELK).

Ciò può essere ottenuto eseguendo un cronjob che sposta gli indici su nodi diversi a intervalli regolari.

Il nodo attivo è un tipo di nodo dati che esegue tutta l'indicizzazione all'interno del cluster. Detengono anche gli indici più recenti poiché questi tendono generalmente a essere interrogati più frequentemente. Poiché l'indicizzazione è un'operazione intensiva per CPU e I / O, questi server devono essere potenti e supportati dall'archiviazione SSD collegata. Si consiglia di eseguire un minimo di 3 nodi attivi per l'alta disponibilità. Tuttavia, a seconda della quantità di dati recenti che desideri raccogliere e richiedere, potresti dover aumentare questo numero per raggiungere i tuoi obiettivi di rendimento.

Il nodo warm è un tipo di nodo dati progettato per gestire una grande quantità di indici di sola lettura che non hanno la stessa probabilità di essere interrogati frequentemente. Poiché questi indici sono di sola lettura, il nodo caldo tende a utilizzare dischi collegati di grandi dimensioni (in genere dischi rotanti) anziché SSD. Come per il nodo attivo, si consiglia un minimo di 3 nodi caldi per l'alta disponibilità. E come in precedenza, con l'avvertenza che grandi quantità di dati potrebbero richiedere nodi aggiuntivi per soddisfare i requisiti di prestazione. Si noti inoltre che le configurazioni della CPU e della memoria dovranno spesso rispecchiare quelle dei nodi attivi. Questo può essere determinato solo testando query simili a quelle che potresti sperimentare in una situazione di produzione.

Per maggiori dettagli sul nodo caldo e caldo consultare qui.

Un'altra strategia che è possibile adattare è l'archiviazione degli indici su s3 e il ripristino quando sono necessari dati da tali indici. Puoi leggere di più al riguardo da qui.

Topologia del nodo:

I nodi Elasticsearch possono essere suddivisi in tre categorie nodo principale, nodo dati, nodo client.

  1. Nodo principale: il nodo principale può essere piccolo se non è un nodo dati in quanto non memorizza alcun indice / frammento. È responsabile dello stato dettagliato del cluster e di aiutare i dati e altri nodi nella ricerca dei metadati di indici / frammenti. Elasticsearch dovrebbe avere più nodi master per evitare problemi al cervello diviso.
  2. Nodo dati: il nodo dati è responsabile della memorizzazione / query dei dati di indice effettivi.
  3. Nodo client: il nodo client viene utilizzato come proxy per l'indicizzazione e la ricerca. Questo è altamente raccomandato se le aggregazioni sono usate pesantemente. Si tratta di nodi ElasticSearch speciali che non sono né dati né master idonei. I nodi client sono a conoscenza del cluster e pertanto possono fungere da bilanciatori di carico intelligenti. È possibile inviare le query ai nodi client che possono quindi assumere il costoso compito di raccogliere risposte ai risultati della query da ciascuno dei nodi di dati.

aggiungere queste impostazioni al file elasticsearch.yml per i rispettivi nodi.

Nodo principale: node.master: true node.data:false
Nodo dati: node.master: false node.data:true
Nodo client: node.master: false node.data:false

Suggerimenti per la risoluzione dei problemi:

Le prestazioni di Elasticsearch dipendono fortemente dalla macchina su cui è installata. CPU, utilizzo della memoria e I / O del disco sono metriche di base del sistema operativo per ciascun nodo Elasticsearch. Si consiglia di esaminare le metriche JVM (Java Virtual Machine) quando si verificano picchi di utilizzo della CPU. Nell'esempio seguente, il motivo dello spike era la maggiore attività di raccolta dei rifiuti.

  1. Pressione dell'heap: la pressione della memoria elevata agisce contro le prestazioni del cluster in due modi: man mano che la pressione della memoria sale al 75% e oltre, rimane meno memoria disponibile e il cluster ora deve anche impiegare alcune risorse della CPU per recuperare la memoria attraverso la garbage collection. Questi cicli della CPU non sono disponibili per la gestione delle richieste dell'utente mentre la garbage collection è attiva. Di conseguenza, i tempi di risposta per le richieste degli utenti aumentano man mano che il sistema diventa sempre più limitato dalle risorse. Se la pressione della memoria continua a salire e raggiunge quasi il 100%, viene utilizzata una forma molto più aggressiva di raccolta dei rifiuti, che a sua volta influirà notevolmente sui tempi di risposta del cluster. La metrica dei tempi di risposta dell'indice mostra che un'elevata pressione della memoria porta a un impatto significativo sulle prestazioni.
  2. Crescita nella memoria non heap della JVM, eliminando la memoria destinata alla cache della pagina e probabilmente causando la raccolta OOM a livello di kernel.
  3. Evita il problema del cervello diviso. Split brain è uno scenario in cui il cluster si divide. Ad esempio, hai un cluster a 6 nodi. 2 nodi si disconnettono dal cluster, ma sono comunque in grado di vedersi. Questi 2 nodi creano quindi un altro cluster. Eleggeranno persino un nuovo maestro tra loro. Ora abbiamo due cluster con lo stesso nome, uno con 4 nodi e l'altro con 2 nodi. Ognuno ha anche un nodo principale. Questo è ciò che viene chiamato problema split-brain con i cluster ES. Per evitare ciò, impostare il parametro ES discovery.zen.minimum_master_nodes sulla metà del numero di nodi + 1.
  4. Poiché Elasticsearch utilizza i dispositivi di archiviazione pesantemente, il monitoraggio dell'I / O del disco garantisce che questa esigenza di base venga soddisfatta. Ci sono molte ragioni per ridurre l'I / O del disco, è considerata una metrica chiave per prevedere molti tipi di problemi. È una buona metrica per verificare l'efficacia dell'indicizzazione e delle prestazioni della query. L'analisi delle operazioni di lettura e scrittura indica direttamente ciò di cui il sistema ha più bisogno nel caso d'uso specifico. Le impostazioni del sistema operativo per l'I / O del disco sono una base per tutte le altre ottimizzazioni, ottimizzando l'I / O del disco può evitare potenziali problemi. Se l'I / O del disco non è ancora sufficiente, le contromisure come l'ottimizzazione del numero di frammenti e delle loro dimensioni, la limitazione delle fusioni, la sostituzione di dischi lenti, lo spostamento su SSD o l'aggiunta di più nodi devono essere valutate in base alle circostanze che causano l'I / O i colli di bottiglia.
  5. Per le applicazioni che si basano sulla ricerca, l'esperienza dell'utente è fortemente correlata alla latenza delle richieste di ricerca. Esistono molte cose che possono influire sulle prestazioni della query, come query costruite, cluster Elasticsearch configurato in modo errato, problemi di memoria JVM e garbage collection, I / O del disco e così via. La latenza delle query è la metrica che influisce direttamente sugli utenti, quindi assicurati di inserire alcuni avvisi.
  6. La maggior parte dei filtri in Elasticsearch sono memorizzati nella cache per impostazione predefinita. Ciò significa che durante la prima esecuzione di una query filtrata, Elasticsearch troverà i documenti corrispondenti al filtro e costruirà una struttura chiamata "bitset" utilizzando tali informazioni. I dati memorizzati nel set di bit contengono un identificativo del documento e se un determinato documento corrisponde al filtro. Le successive esecuzioni di query con lo stesso filtro riutilizzeranno le informazioni memorizzate nel bitset, rendendo più rapida l'esecuzione delle query salvando le operazioni di I / O e i cicli della CPU. Si consiglia di utilizzare il filtro nella query. Per maggiori dettagli consultare qui.
  7. Il tempo di aggiornamento e il tempo di unione sono strettamente correlati alle prestazioni di indicizzazione, oltre a influire sulle prestazioni complessive del cluster. Il tempo di aggiornamento aumenta con il numero di operazioni sui file per l'indice Lucene (shard).
  8. L'abilitazione della registrazione delle query lenta aiuterà a identificare quali query sono lente e cosa si può fare per migliorarle, particolarmente utile per le query con caratteri jolly.
  9. Aumenta le dimensioni di ulimit per consentire il numero massimo di file.
  10. Le prestazioni di ElasticSearch possono risentirne quando il sistema operativo decide di sostituire la memoria dell'applicazione non utilizzata. Disabilita lo scambio configurando le impostazioni a livello di sistema operativo o imposta quanto segue nella configurazione di ElasticSearch bootstrap.mlockall: true
  11. Disabilita l'eliminazione di tutti gli indici tramite query con caratteri jolly. Per assicurarsi che qualcuno non esegua un'operazione DELETE su tutti gli indici (* o _all) impostare action.destructive_requires_name su true.

Prima di concludere, ecco l'elenco degli URL utili per la visualizzazione delle metriche.

  • / _cluster / health? pretty: per l'indicatore di integrità del cluster.
  • / _status? pretty: per tutte le informazioni su tutti gli indici.
  • / _nodes? pretty: per tutte le informazioni sui nodi.
  • / _cat / master? pretty: per nodo principale.
  • / _stats? pretty: per l'allocazione dei frammenti, statistiche sugli indici.
  • / _nodes / stats? pretty: per le statistiche dei singoli nodi, questo include statistiche jvm, http, io per il nodo.

L'aggregazione metrica di Elasticsearch è supportata dalla maggior parte degli strumenti di monitoraggio del sistema come Datadog, TICK. Si consiglia l'utilizzo di tali strumenti e la creazione di un imbuto è fortemente consigliata per il monitoraggio continuo di Elasticsearch.

Conclusione:

Elasticsearch è un motore di ricerca e analisi full-text distribuito, che consente a più tenant di effettuare ricerche nell'intero set di dati, indipendentemente dalle dimensioni, a velocità senza precedenti. Oltre alle funzionalità di ricerca full-text, ElasticSearch funge anche da sistema di analisi e database distribuito. Per iniziare, ElasticSearch ha ottime impostazioni predefinite. Ma una volta superata la fase iniziale di sperimentazione, devi dedicare un po 'di tempo a modificare le impostazioni in base alle tue esigenze. Si consiglia di rivedere la configurazione in un secondo momento, insieme alla documentazione ufficiale, per assicurarsi che il cluster sia configurato per soddisfare le proprie esigenze.