Come elaborare miliardi di eventi al secondo senza uccidere la latenza
Immagina questo: devi verificare le transazioni bancarie per frodi in tempo reale durante il processo di pagamento. Hai solo pochi millisecondi per prendere una decisione. Apache Kafka sta trasmettendo eventi senza sosta, ma per ciascuno devi recuperare lo storico del cliente dal database. Se esegui una query su un PostgreSQL o MySQL tradizionale per ogni messaggio, il sistema crollerà immediatamente sotto il carico.
Questo è un vicolo cieco comune che gli ingegneri incontrano quando progettano sistemi ad alta intensità di carico. Una cache normale come Redis aiuta ad accelerare le letture di singole chiavi, ma quando si tratta di costruire logiche di business complesse e analisi sopra uno stream di dati, le sue capacità iniziano a essere insufficienti. Sei costretto a legare insieme cache, broker di messaggi e motori di elaborazione di terze parti. A questo punto, ha senso dare un'occhiata a Hazelcast.
Hazelcast combina l'archiviazione distribuita in memoria e un motore di elaborazione stream in un unico sistema. Invece di assemblare un costrutto da tre servizi diversi, ottieni una piattaforma unificata capace di acquisire, arricchire e analizzare i dati al volo.
Cosa succede all'interno della piattaforma
Il cuore della piattaforma è il motore Jet. È responsabile della costruzione delle pipeline di elaborazione dati. Jet può lavorare ugualmente bene con stream continui e set di dati statici, come bucket in Amazon S3 o tabelle in un database relazionale.
Le metriche di performance qui sono interessanti. Un singolo nodo Hazelcast può aggregare 10 milioni di eventi al secondo mantenendo la latenza entro 10 millisecondi. Se clust erizzi i server insieme, il throughput scala fino a un miliardo di eventi al secondo.
Per scrivere query contro gli stream di dati, non devi immergerti nelle API Java di basso livello. La piattaforma supporta SQL standard. Puoi scrivere una familiare SELECT contro lo stream di dati in entrata, unirla con una tabella in memoria, e instradare immediatamente il risultato al servizio target.
Ecco come appare la connessione di fonti esterne. Out of the box, ottieni un set di connettori:
- Apache Kafka e JMS per lavorare con le code
- Hadoop e Amazon S3 per accedere allo storage file
- Database relazionali tramite JDBC standard
- Modelli Python per eseguire machine learning direttamente all'interno della pipeline
Memoria distribuita e coordinamento
Se rimuovi l'analisi degli stream dall'equazione, Hazelcast rimane un archivio chiave-valore distribuito. I dati sono distribuiti attraverso i nodi del cluster come partizioni. Gli sviluppatori hanno accesso a strutture Java familiari (IMap, IQueue, ITopic), con l'unica differenza che sono distribuite attraverso la rete. Le ricerche puntuali per chiave richiedono microsecondi.
Per le operazioni di database, sono supportati i pattern di caching classici: read-through, write-through e write-behind. Quando si usa write-behind, l'applicazione salva i dati esclusivamente nella RAM di Hazelcast, e la piattaforma li scarica in modo asincrono su disco e sul database principale. Se il DBMS relazionale va temporaneamente giù, l'applicazione continuerà ad accettare richieste senza interruzioni.
Una funzionalità separata è il coordinamento dei microservizi. Hazelcast può gestire lock distribuiti, generare sequenze di ID univoci e mantenere contatori condivisi. Questo elimina la necessità di distribuire e gestire un cluster Apache ZooKeeper separato per compiti banali di sincronizzazione.
Come costruire ed eseguire il progetto
Il codice sorgente del progetto è scritto in Java. Per compilare da sorgente è richiesto JDK 17 o versione successiva. Il modo più semplice per compilare il progetto è usare lo script Maven Wrapper:
git pull origin master
./mvnw clean package -DskipTests
Il build completo con tutti i controlli può richiedere un po'. Se hai solo bisogno di verificare rapidamente modifiche locali, passa il flag -Dquick:
./mvnw clean package -DskipTests -Dquick
Questo parametro disabilita la generazione di Javadoc, i controlli Checkstyle e i build dei moduli secondari.
La situazione dei test è interessante. Il repository contiene migliaia di test divisi in tre profili:
- Il profilo standard
./mvnw testesegue test di integrazione veloci. - Il profilo nightly
./mvnw test -P nightly-buildinclude test lenti che non possono essere eseguiti in parallelo. - Il profilo full
./mvnw test -P all-testsesegue sequenzialmente tutti i controlli usando la rete.
Alcuni test dipendono da Docker. Se Docker non è installato sulla tua macchina, quei test falliranno. Per disabilitarli, usa il parametro -Dhazelcast.disable.docker.tests. Quando crei una Pull Request, il CI server del progetto esegue la suite completa, quindi localmente è sufficiente eseguire i test solo per il tuo modulo.
Puoi scrivere client non solo in Java. La community e l'azienda mantengono librerie ufficiali per Python, Node.js, .NET, C++ e Go.
Licenza e un paio di sfumature pratiche
Il codice nel repository è diviso in due parti. Il core è distribuito sotto la permissiva licenza Apache 2.0. Tuttavia, alcune funzionalità enterprise e moduli sono protetti dalla Hazelcast Community License. Questa vieta di usare il codice per creare servizi managed a pagamento (Cloud Service Provider) che competono con il prodotto cloud originale dell'azienda.
Il secondo punto sono i requisiti di risorse. Poiché tutti i dati caldi risiedono in RAM, dovrai acquistare una quantità sostanziale di memoria per lavorare con grandi volumi. Inoltre, in un ambiente Java, dovresti prestare molta attenzione alle impostazioni del Garbage Collector per evitare pause durante la pulizia di gigabyte di memoria. Tuttavia, gli ingegneri di Hazelcast mitigano questo problema con lo storage off-heap, spostando i dati fuori dall'heap Java.
Chi dovrebbe dare un'occhiata a Hazelcast
La piattaforma funziona bene dove la risposta agli eventi in tempo reale è importante:
- Prevenzione delle frodi e scoring nel fintech
- Elaborazione di telemetria e segnali IoT ad alta frequenza
- Calcolo di prezzi e sconti nell'e-commerce proprio nel momento del click del cliente
- Sincronizzazione dei dati tra data center distribuiti (replica WAN)
Se hai solo bisogno di una semplice cache per un paio di endpoint, Hazelcast sarebbe eccessivo: un Redis più semplice gestirebbe quel compito senza problemi. Ma se il tuo progetto è cresciuto fino a raggiungere una scala in cui l'analisi degli stream deve intersecarsi con la memoria distribuita senza viaggi costanti verso lo storage su disco, Hazelcast ti farà risparmiare mesi di sviluppo.
Progetti correlati