Introduzione a Big Queue

1. Panoramica

In questo tutorial, daremo una rapida occhiata a Big Queue, un'implementazione Java di una coda persistente.

Parleremo un po 'della sua architettura e poi impareremo come usarla attraverso esempi rapidi e pratici.

2. Utilizzo

Dovremo aggiungere la dipendenza bigqueue al nostro progetto:

 com.leansoft bigqueue 0.7.0 

Abbiamo anche bisogno di aggiungere il suo repository:

 github.release.repo //raw.github.com/bulldog2011/bulldog-repo/master/repo/releases/ 

Se siamo abituati a lavorare con le code di base, sarà un gioco da ragazzi adattarsi a Big Queue poiché la sua API è abbastanza simile.

2.1. Inizializzazione

Possiamo inizializzare la nostra coda semplicemente chiamando il suo costruttore:

@Before public void setup() { String queueDir = System.getProperty("user.home"); String queueName = "baeldung-queue"; bigQueue = new BigQueueImpl(queueDir, queueName); }

Il primo argomento è la directory home per la nostra coda.

Il secondo argomento rappresenta il nome della nostra coda. Creerà una cartella all'interno della home directory della nostra coda in cui possiamo salvare i dati.

Dovremmo ricordarci di chiudere la nostra coda quando abbiamo finito per evitare perdite di memoria:

bigQueue.close();

2.2. Inserimento

Possiamo aggiungere elementi alla coda semplicemente chiamando il metodo enqueue :

@Test public void whenAddingRecords_ThenTheSizeIsCorrect() { for (int i = 1; i <= 100; i++) { bigQueue.enqueue(String.valueOf(i).getBytes()); } assertEquals(100, bigQueue.size()); }

Dobbiamo notare che Big Queue supporta solo il tipo di dati byte [] , quindi siamo responsabili della serializzazione dei nostri record durante l'inserimento.

2.3. Lettura

Come ci saremmo potuti aspettare, leggere i dati è altrettanto facile utilizzando il metodo dequeue :

@Test public void whenAddingRecords_ThenTheyCanBeRetrieved() { bigQueue.enqueue(String.valueOf("new_record").getBytes()); String record = new String(bigQueue.dequeue()); assertEquals("new_record", record); }

Dobbiamo anche fare attenzione a deserializzare correttamente i nostri dati durante la lettura.

La lettura da una coda vuota genera un'eccezione NullPointerException .

Dovremmo verificare che ci siano valori nella nostra coda utilizzando il metodo isEmpty :

if(!bigQueue.isEmpty()){ // read }

Per svuotare la nostra coda senza dover passare attraverso ogni record, possiamo utilizzare il metodo removeAll :

bigQueue.removeAll();

2.4. Sbirciando

Quando sbirciamo, leggiamo semplicemente un record senza consumarlo:

@Test public void whenPeekingRecords_ThenSizeDoesntChange() { for (int i = 1; i <= 100; i++) { bigQueue.enqueue(String.valueOf(i).getBytes()); } String firstRecord = new String(bigQueue.peek()); assertEquals("1", firstRecord); assertEquals(100, bigQueue.size()); }

2.5. Eliminazione dei record consumati

Quando chiamiamo il metodo dequeue , i record vengono rimossi dalla nostra coda, ma rimangono persistenti su disco.

Questo potrebbe potenzialmente riempire il nostro disco con dati non necessari.

Fortunatamente, possiamo eliminare i record consumati utilizzando il metodo gc :

bigQueue.gc();

Proprio come il garbage collector in Java pulisce gli oggetti non referenziati dall'heap, gc pulisce i record consumati dal nostro disco.

3. Architettura e caratteristiche

La cosa interessante di Big Queue è il fatto che la sua base di codice è estremamente piccola: solo 12 file sorgente che occupano circa 20 KB di spazio su disco.

Ad alto livello, è solo una coda persistente che eccelle nella gestione di grandi quantità di dati.

3.1. Gestione di grandi quantità di dati

La dimensione della coda è limitata solo dallo spazio su disco totale disponibile. Ogni record all'interno della nostra coda viene conservato su disco, in modo da essere resistente ai crash.

Il nostro collo di bottiglia sarà l'I / O del disco, il che significa che un SSD migliorerà significativamente il throughput medio su un HDD.

3.2. Accesso ai dati estremamente veloce

Se diamo uno sguardo al suo codice sorgente, noteremo che la coda è supportata da un file mappato in memoria. La parte accessibile della nostra coda (la testina) è conservata nella RAM, quindi l'accesso ai record sarà estremamente veloce.

Anche se la nostra coda diventasse estremamente grande e occupasse terabyte di spazio su disco, saremmo comunque in grado di leggere i dati con una complessità temporale O (1).

Se abbiamo bisogno di leggere molti messaggi e la velocità è una preoccupazione fondamentale, dovremmo considerare l'utilizzo di un SSD su un HDD, poiché lo spostamento dei dati dal disco alla memoria sarebbe molto più veloce.

3.3. Vantaggi

Un grande vantaggio è la sua capacità di crescere di dimensioni molto grandi. Possiamo ridimensionarlo all'infinito teorico semplicemente aggiungendo più spazio di archiviazione, da cui il nome "Big".

In un ambiente simultaneo, Big Queue può produrre e consumare circa 166 MBps di dati su una macchina comune.

Se la dimensione media dei nostri messaggi è di 1 KB, può elaborare 166.000 messaggi al secondo.

Può arrivare fino a 333k messaggi al secondo in un ambiente a thread singolo - piuttosto impressionante!

3.4. Svantaggi

I nostri messaggi rimangono persistenti su disco, anche dopo che li abbiamo consumati, quindi dobbiamo occuparci della raccolta dei rifiuti quando non ne abbiamo più bisogno.

Siamo anche responsabili della serializzazione e deserializzazione dei nostri messaggi.

4. Conclusione

In questo breve tutorial, abbiamo imparato a conoscere Big Queue e come possiamo usarlo come coda scalabile e persistente.

Come sempre, il codice è disponibile su Github.