Una completa introduzione ai sistemi distribuiti

Che cos'è un sistema distribuito e perché è così complicato?

Un orso che contempla sistemi distribuiti

Sommario

introduzione

  1. Che cos'è un sistema distribuito?
  2. Perché distribuire un sistema?
  3. Esempio di ridimensionamento del database
  4. Decentrato vs distribuito

Categorie di sistema distribuite

  1. Archivi di dati distribuiti
  2. Calcolo distribuito
  3. File system distribuito
  4. Messaggistica distribuita
  5. Applicazioni distribuite
  6. Registri distribuiti

Sommario

introduzione

Con la sempre crescente espansione tecnologica del mondo, i sistemi distribuiti stanno diventando sempre più diffusi. Sono un vasto e complesso campo di studio in informatica.

Questo articolo ha lo scopo di farvi conoscere i sistemi distribuiti in modo basilare, mostrandovi un assaggio delle diverse categorie di tali sistemi senza immergervi in ​​profondità nei dettagli.

Che cos'è un sistema distribuito?

Un sistema distribuito nella sua definizione più semplice è un gruppo di computer che lavorano insieme per apparire all'utente finale come un singolo computer.

Queste macchine hanno uno stato condiviso, funzionano contemporaneamente e possono fallire indipendentemente senza influire sul tempo di attività dell'intero sistema.

Propongo di lavorare in modo incrementale attraverso un esempio di distribuzione di un sistema in modo che tu possa avere un'idea migliore di tutto:

Una pila tradizionale

Andiamo con un database! I database tradizionali vengono archiviati nel filesystem di una singola macchina, ogni volta che si desidera recuperare / inserire informazioni al suo interno - si parla direttamente con quella macchina.

Per poter distribuire questo sistema di database, dovremmo avere questo database eseguito su più macchine contemporaneamente. L'utente deve essere in grado di parlare con qualunque macchina scelga e non dovrebbe essere in grado di dire che non sta parlando con una singola macchina - se inserisce un record nel nodo # 1, il nodo # 3 deve essere in grado di restituire quel record.

Un'architettura che può essere considerata distribuita

Perché distribuire un sistema?

I sistemi sono sempre distribuiti per necessità. La verità è che la gestione dei sistemi distribuiti è un argomento complesso pieno zeppo di insidie ​​e mine antiuomo. È un mal di testa distribuire, mantenere e eseguire il debug di sistemi distribuiti, quindi perché andarci?

Ciò che un sistema distribuito ti consente di fare è ridimensionare orizzontalmente. Tornando al nostro precedente esempio del singolo server di database, l'unico modo per gestire più traffico sarebbe aggiornare l'hardware su cui è in esecuzione il database. Questo si chiama ridimensionamento verticale.

Il ridimensionamento verticale è tutto a posto, ma dopo un certo punto vedrai che anche l'hardware migliore non è sufficiente per un traffico sufficiente, per non parlare di poco pratico da ospitare.

Il ridimensionamento orizzontale significa semplicemente aggiungere più computer anziché aggiornare l'hardware di un singolo.

Il ridimensionamento orizzontale diventa molto più economico dopo una certa soglia

È significativamente più economico del ridimensionamento verticale dopo una certa soglia, ma non è questo il caso principale di preferenza.

Il ridimensionamento verticale può solo aumentare le prestazioni fino alle funzionalità hardware più recenti. Queste capacità si rivelano insufficienti per le aziende tecnologiche con carichi di lavoro da moderati a grandi.

La cosa migliore del ridimensionamento orizzontale è che non hai limiti su quanto puoi ridimensionare: ogni volta che le prestazioni diminuiscono, aggiungi semplicemente un'altra macchina, potenzialmente fino all'infinito.

Il facile ridimensionamento non è l'unico vantaggio che si ottiene dai sistemi distribuiti. Anche la tolleranza ai guasti e la bassa latenza sono altrettanto importanti.

Tolleranza agli errori: un cluster di dieci macchine su due data center è intrinsecamente più tollerante agli errori di una singola macchina. Anche se un data center prende fuoco, l'applicazione funzionerebbe comunque.

Bassa latenza: il tempo per un pacchetto di rete di viaggiare per il mondo è fisicamente limitato dalla velocità della luce. Ad esempio, il tempo più breve possibile per il tempo di andata e ritorno di una richiesta (ovvero andare avanti e indietro) in un cavo in fibra ottica tra New York e Sydney è di 160 ms. I sistemi distribuiti ti consentono di avere un nodo in entrambe le città, consentendo al traffico di colpire il nodo più vicino ad esso.

Perché un sistema distribuito funzioni, tuttavia, è necessario che il software in esecuzione su tali macchine sia progettato in modo specifico per l'esecuzione su più computer contemporaneamente e per la gestione dei problemi che ne derivano. Questa non è un'impresa facile.

Ridimensionare il nostro database

Immagina che la nostra applicazione web sia diventata follemente popolare. Immagina anche che il nostro database abbia iniziato a ricevere il doppio delle query al secondo che è in grado di gestire. La tua applicazione inizierebbe immediatamente a peggiorare le prestazioni e questo verrebbe notato dagli utenti.

Lavoriamo insieme e facciamo scalare il nostro database per soddisfare le nostre elevate esigenze.

In una tipica applicazione Web di solito leggi le informazioni molto più frequentemente di quanto non inserisci nuove informazioni o modifichi quelle vecchie.

C'è un modo per aumentare le prestazioni di lettura e quello è attraverso la cosiddetta strategia di replica Master-Slave. Qui, crei due nuovi server di database che si sincronizzano con quello principale. Il trucco è che puoi leggere solo da queste nuove istanze.

Ogni volta che inserisci o modifichi informazioni, parli con il database principale. A sua volta, informa in modo asincrono gli schiavi del cambiamento e anche loro lo salvano.

Congratulazioni, ora puoi eseguire 3 volte più query di lettura! Non è fantastico?

trappola

Gotcha! Abbiamo immediatamente perso la C nelle garanzie ACID del nostro database relazionale, che significa Coerenza.

Vedete, esiste ora una possibilità in cui inseriamo un nuovo record nel database, immediatamente dopo emettiamo una query di lettura per esso e non otteniamo nulla in cambio, come se non esistesse!

La propagazione delle nuove informazioni dal master allo slave non avviene istantaneamente. Esiste effettivamente una finestra temporale in cui è possibile recuperare informazioni non aggiornate. Se così non fosse, le prestazioni di scrittura ne risentirebbero, in quanto dovrebbero attendere in modo sincrono la propagazione dei dati.

I sistemi distribuiti presentano una manciata di compromessi. Questo particolare problema è uno con cui dovrai convivere se vuoi ridimensionare adeguatamente.

Continuando a ridimensionare

Utilizzando l'approccio del database slave, possiamo ridimensionare orizzontalmente il nostro traffico di lettura fino a un certo punto. È fantastico, ma abbiamo superato un muro per quanto riguarda il nostro traffico di scrittura: è ancora tutto in un server!

Non ci sono molte opzioni qui. Dobbiamo semplicemente dividere il nostro traffico di scrittura in più server poiché non è possibile gestirlo.

Un modo è seguire una strategia di replica multi-master. Lì, invece degli slave da cui puoi solo leggere, hai più nodi master che supportano le letture e le scritture. Sfortunatamente, questo diventa complicato molto rapidamente poiché ora hai la possibilità di creare conflitti (ad esempio, inserisci due record con lo stesso ID).

Andiamo con un'altra tecnica chiamata sharding (anche chiamata partizionamento).

Con lo sharding puoi dividere il tuo server in più server più piccoli, chiamati shard. Questi frammenti contengono tutti record diversi: crei una regola su quale tipo di record va inserito in quale frammento. È molto importante creare la regola in modo che i dati vengano diffusi in modo uniforme.

Un possibile approccio a questo è definire intervalli in base ad alcune informazioni su un record (ad esempio utenti con nome A-D).

Questa chiave di sharding dovrebbe essere scelta con molta attenzione, poiché il carico non è sempre uguale sulla base di colonne arbitrarie. (ad es. più persone hanno un nome che inizia con C anziché con Z). Un singolo frammento che riceve più richieste di altri viene chiamato hot spot e deve essere evitato. Una volta divisi, i dati di ri-sharding diventano incredibilmente costosi e possono causare tempi di inattività significativi, come nel caso della famigerata interruzione di 11 ore di FourSquare.

Per semplificare il nostro esempio, supponiamo che il nostro client (l'app Rails) sappia quale database utilizzare per ogni record. Vale anche la pena notare che ci sono molte strategie per lo sharding e questo è un semplice esempio per illustrare il concetto.

Abbiamo vinto parecchio in questo momento - possiamo aumentare il nostro traffico di scrittura N volte dove N è il numero di frammenti. Questo non ci dà praticamente alcun limite: immagina quanto possiamo ottenere con questo partizionamento.

trappola

Tutto in Ingegneria del Software è più o meno un compromesso e questa non fa eccezione. Sharding non è un'impresa semplice ed è meglio evitarlo fino a quando non è veramente necessario.

Ora abbiamo fatto query con chiavi diverse dalla chiave partizionata incredibilmente inefficiente (devono passare attraverso tutti i frammenti). Le query SQL JOIN sono persino peggiori e quelle complesse diventano praticamente inutilizzabili.

Decentrato vs distribuito

Prima di andare oltre, vorrei fare una distinzione tra i due termini.

Anche se le parole sembrano simili e si può concludere che significano la stessa logica, la loro differenza ha un impatto tecnologico e politico significativo.

Il decentralizzato è ancora distribuito in senso tecnico, ma l'intero sistema decentralizzato non è di proprietà di un attore. Nessuna azienda può possedere un sistema decentralizzato, altrimenti non sarebbe più decentralizzato.

Ciò significa che la maggior parte dei sistemi che esamineremo oggi possono essere pensati come sistemi centralizzati distribuiti - ed è quello che sono fatti per essere.

Se ci pensate, è più difficile creare un sistema decentralizzato perché è necessario gestire il caso in cui alcuni dei partecipanti sono dannosi. Questo non è il caso dei normali sistemi distribuiti, poiché sai di possedere tutti i nodi.

Nota: questa definizione è stata molto dibattuta e può essere confusa con altri (peer-to-peer, federati). Nella letteratura antica, è stato definito anche in modo diverso. Indipendentemente da ciò, ciò che ti ho dato come definizione è quello che ritengo sia il più ampiamente usato ora che blockchain e criptovalute hanno reso popolare il termine.

Categorie di sistema distribuite

Ora esamineremo un paio di categorie di sistemi distribuiti ed elencheremo il loro più grande utilizzo di produzione noto pubblicamente. Tieni presente che la maggior parte di questi numeri mostrati sono obsoleti e molto probabilmente molto più grandi dal momento in cui stai leggendo questo.

Archivi di dati distribuiti

Gli archivi dati distribuiti sono ampiamente utilizzati e riconosciuti come database distribuiti. La maggior parte dei database distribuiti sono database non relazionali NoSQL, limitati alla semantica dei valori-chiave. Offrono prestazioni e scalabilità incredibili a costo di coerenza o disponibilità.

Scala nota - Apple è nota per l'utilizzo di 75.000 nodi Apache Cassandra che memorizzano oltre 10 petabyte di dati, nel 2015

Non possiamo discutere di archivi di dati distribuiti senza prima introdurre il teorema della PAC.

Teorema della PAC

Provato nel lontano 2002, il teorema della CAP afferma che un archivio di dati distribuiti non può essere simultaneamente coerente, disponibile e tollerante alle partizioni.

Scegli 2 su 3 (ma non coerenza e disponibilità)

Alcune definizioni rapide:

  • Coerenza: ciò che leggi e scrivi in ​​sequenza è ciò che ti aspetti (ricordi il gotcha con la replica del database qualche paragrafo fa?)
  • Disponibilità - l'intero sistema non muore - ogni nodo non difettoso restituisce sempre una risposta.
  • Tolleranza alle partizioni - Il sistema continua a funzionare e mantiene le sue garanzie di coerenza / disponibilità nonostante le partizioni di rete

In realtà, la tolleranza della partizione deve essere data per qualsiasi archivio di dati distribuito. Come accennato in molti luoghi, uno dei quali questo fantastico articolo, non puoi avere coerenza e disponibilità senza tolleranza di partizione.

Pensaci: se hai due nodi che accettano le informazioni e la loro connessione si interrompe, come saranno entrambe disponibili e allo stesso tempo ti daranno coerenza? Non hanno modo di sapere cosa sta facendo l'altro nodo e come tali possono diventare offline (non disponibili) o lavorare con informazioni non aggiornate (incoerenti).

Cosa facciamo?

Alla fine ti resta da scegliere se desideri che il tuo sistema sia fortemente coerente o altamente disponibile in una partizione di rete.

La pratica dimostra che la maggior parte delle applicazioni apprezza maggiormente la disponibilità. Non è sempre necessaria una forte coerenza. Anche in questo caso, questo compromesso non viene necessariamente effettuato perché è necessaria la garanzia di disponibilità al 100%, ma piuttosto perché la latenza della rete può essere un problema quando si devono sincronizzare le macchine per ottenere una forte coerenza. Questi e altri fattori rendono le applicazioni in genere optare per soluzioni che offrono elevata disponibilità.

Tali database si sistemano con il modello di coerenza più debole - eventuale coerenza (spiegazione di coerenza forte vs eventuale). Questo modello garantisce che se non vengono apportati nuovi aggiornamenti a un determinato articolo, alla fine tutti gli accessi a quell'elemento restituiranno l'ultimo valore aggiornato.

Tali sistemi forniscono proprietà BASE (al contrario dell'ACID dei database tradizionali)

  • Fondamentalmente disponibile: il sistema restituisce sempre una risposta
  • Stato morbido - Il sistema potrebbe cambiare nel tempo, anche durante i periodi di inattività (a causa di un'eventuale coerenza)
  • Eventuale coerenza - In assenza di input, i dati si diffonderanno prima o poi su tutti i nodi - diventando così coerenti

Esempi di tali database distribuiti disponibili: Cassandra, Riak, Voldemort

Naturalmente, ci sono altri archivi di dati che preferiscono una maggiore coerenza: HBase, Couchbase, Redis, Zookeeper

Il teorema di CAP è degno di più articoli per conto suo - alcuni su come puoi modificare le proprietà di CAP di un sistema a seconda di come si comporta il client e altri su come non è compreso correttamente.

cassandra

Cassandra, come menzionato sopra, è un database distribuito No-SQL che preferisce le proprietà AP al di fuori del CAP, risolvendosi con eventuale coerenza. Devo ammettere che questo potrebbe essere un po 'fuorviante, dato che Cassandra è altamente configurabile: puoi renderlo molto coerente a spese della disponibilità, ma non è il suo caso d'uso comune.

Cassandra utilizza un hash coerente per determinare quali nodi del cluster devono gestire i dati in transito. È possibile impostare un fattore di replica, che sostanzialmente indica a quanti nodi si desidera replicare i dati.

Esempio di scrittura

Durante la lettura, leggerai solo da quei nodi.

Cassandra è enormemente scalabile, offrendo una capacità di scrittura assurdamente alta.

Diagramma possibilmente distorto, che mostra benchmark di scrittura al secondo. Tratto da qui.

Anche se questo diagramma potrebbe essere distorto e sembra che confronta Cassandra con i database impostati per fornire una forte coerenza (altrimenti non riesco a capire perché MongoDB riduca le prestazioni se aggiornato da 4 a 8 nodi), questo dovrebbe comunque mostrare che cosa è impostato correttamente il cluster Cassandra è in grado di farlo.

Indipendentemente da ciò, nel trade-off dei sistemi distribuiti che consente il ridimensionamento orizzontale e un throughput incredibilmente elevato, Cassandra non fornisce alcune caratteristiche fondamentali dei database ACID - vale a dire le transazioni.

Consenso

Le transazioni del database sono difficili da implementare nei sistemi distribuiti in quanto richiedono che ciascun nodo sia d'accordo sull'azione giusta da intraprendere (interrompere o eseguire il commit). Questo è noto come consenso ed è un problema fondamentale nei sistemi distribuiti.

Raggiungere il tipo di accordo necessario per il problema del "commit delle transazioni" è semplice se i processi partecipanti e la rete sono completamente affidabili. Tuttavia, i sistemi reali sono soggetti a una serie di possibili guasti, come arresti anomali del processo, partizionamento della rete e messaggi persi, distorti o duplicati.

Ciò pone un problema: è stato dimostrato impossibile garantire il raggiungimento di un consenso corretto entro un periodo di tempo limitato su una rete non affidabile.

In pratica, tuttavia, esistono algoritmi che raggiungono il consenso su una rete non affidabile abbastanza rapidamente. Cassandra in realtà fornisce transazioni leggere attraverso l'uso dell'algoritmo Paxos per il consenso distribuito.

Calcolo distribuito

Il calcolo distribuito è la chiave per l'afflusso dell'elaborazione dei Big Data che abbiamo visto negli ultimi anni. È la tecnica di suddividere un compito enorme (ad es. Aggregare 100 miliardi di record), di cui nessun singolo computer è in grado di eseguire praticamente da solo, in molti compiti più piccoli, ognuno dei quali può adattarsi a una singola macchina di merci. Hai diviso il tuo enorme compito in molti più piccoli, li hai eseguiti su molte macchine in parallelo, aggregando i dati in modo appropriato e hai risolto il problema iniziale. Questo approccio consente di ridimensionare orizzontalmente: quando si ha un'attività più grande, è sufficiente includere più nodi nel calcolo.

Scala nota - Folding @ Home aveva 160k macchine attive nel 2012

Un primo innovatore in questo spazio era Google, che per necessità delle loro grandi quantità di dati ha dovuto inventare un nuovo paradigma per il calcolo distribuito - MapReduce. Hanno pubblicato un articolo su di esso nel 2004 e la comunità open source ha successivamente creato Apache Hadoop basato su di esso.

Riduci mappa

MapReduce può essere semplicemente definito in due passaggi: mappare i dati e ridurli a qualcosa di significativo.

Proviamo di nuovo con un esempio:

Supponiamo che siamo medi e che abbiamo archiviato le nostre enormi informazioni in un database distribuito secondario per scopi di deposito. Vogliamo recuperare i dati che rappresentano il numero di applausi emessi ogni giorno durante aprile 2017 (un anno fa).

Questo esempio è il più breve, chiaro e semplice possibile, ma immagina di lavorare con un sacco di dati (ad esempio analizzando miliardi di battiti di mani). Ovviamente non memorizzeremo tutte queste informazioni su una macchina e non analizzeremo tutte queste informazioni con una sola macchina. Inoltre, non eseguiremo query sul database di produzione, ma piuttosto su un database di "magazzino" creato appositamente per lavori offline a bassa priorità.

Ogni processo Mappa è un nodo separato che trasforma il maggior numero di dati possibile. Ogni lavoro attraversa tutti i dati nel nodo di archiviazione specificato e li mappa su una semplice tupla di data e numero uno. Quindi, vengono eseguiti tre passaggi intermedi (di cui nessuno parla): Shuffle, Sort e Partition. Fondamentalmente organizzano ulteriormente i dati e li eliminano nel processo di riduzione appropriato. Dato che abbiamo a che fare con i big data, ogni processo Riduci è separato per funzionare in un'unica data.

Questo è un buon paradigma e sorprendentemente ti consente di fare molto con esso, ad esempio puoi concatenare più lavori MapReduce.

Tecniche migliori

MapReduce è in qualche modo ereditato al giorno d'oggi e comporta alcuni problemi. Poiché funziona in batch (lavori), sorge un problema a causa del quale se il lavoro fallisce, è necessario riavviare il tutto. Un fallimento di un lavoro di 2 ore può davvero rallentare l'intera pipeline di elaborazione dei dati e non lo vuoi minimamente, specialmente nelle ore di punta.

Un altro problema è il tempo che aspetti prima di ricevere i risultati. Nei sistemi analitici in tempo reale (che hanno tutti i big data e quindi utilizzano il calcolo distribuito) è importante che i tuoi ultimi dati sgranati siano il più aggiornati possibile e certamente non da poche ore fa.

Come tale, sono emerse altre architetture che affrontano questi problemi. Vale a dire Lambda Architecture (mix di elaborazione batch ed elaborazione stream) e Kappa Architecture (solo elaborazione stream). Questi progressi nel campo hanno portato nuovi strumenti che li abilitano: Kafka Streams, Apache Spark, Apache Storm, Apache Samza.

File system distribuito

I file system distribuiti possono essere considerati archivi di dati distribuiti. Sono la stessa cosa di un concetto: archiviare e accedere a una grande quantità di dati attraverso un cluster di macchine che appaiono tutte come una. Di solito vanno di pari passo con il calcolo distribuito.

Scala nota: Yahoo è nota per l'esecuzione di HDFS su oltre 42.000 nodi per l'archiviazione di 600 petabyte di dati, già nel 2011

Wikipedia definisce la differenza che i file system distribuiti consentono l'accesso ai file utilizzando le stesse interfacce e semantiche dei file locali, non attraverso un'API personalizzata come Cassandra Query Language (CQL).

HDFS

Hadoop Distributed File System (HDFS) è il file system distribuito utilizzato per l'elaborazione distribuita tramite il framework Hadoop. Vantando un'adozione diffusa, viene utilizzato per archiviare e replicare file di grandi dimensioni (dimensioni GB o TB) su molte macchine.

La sua architettura è costituita principalmente da NameNodes e DataNodes. I NameNodes sono responsabili della conservazione dei metadati sul cluster, ad esempio quale nodo contiene quali blocchi di file. Agiscono come coordinatori per la rete, scoprendo dove archiviare e replicare meglio i file, monitorando lo stato del sistema. DataNodes semplicemente memorizza i file ed esegue comandi come replicare un file, scriverne uno nuovo e altri.

Non sorprende che HDFS sia meglio utilizzato con Hadoop per il calcolo in quanto fornisce consapevolezza dei dati ai lavori di calcolo. Detti lavori vengono quindi eseguiti sui nodi in cui sono memorizzati i dati. Ciò sfrutta la localizzazione dei dati: ottimizza i calcoli e riduce la quantità di traffico sulla rete.

IPFS

Interplanetary File System (IPFS) è un nuovo entusiasmante protocollo / rete peer-to-peer per un file system distribuito. Sfruttando la tecnologia Blockchain, vanta un'architettura completamente decentralizzata senza proprietario singolo né punto di errore.

IPFS offre un sistema di denominazione (simile al DNS) chiamato IPNS e consente agli utenti di accedere facilmente alle informazioni. Memorizza i file tramite il controllo delle versioni storico, in modo simile a come fa Git. Ciò consente di accedere a tutti gli stati precedenti di un file.

È ancora in fase di forte sviluppo (v0.4 al momento della stesura) ma ha già visto progetti interessati a costruirlo (FileCoin).

Messaggistica distribuita

I sistemi di messaggistica forniscono un posto centrale per l'archiviazione e la propagazione di messaggi / eventi all'interno del sistema generale. Consentono di disaccoppiare la logica dell'applicazione dalla conversazione diretta con gli altri sistemi.

Scala nota: il cluster Kafka di LinkedIn ha elaborato 1 trilione di messaggi al giorno con picchi di 4,5 milioni di messaggi al secondo.

In poche parole, una piattaforma di messaggistica funziona nel modo seguente:

Un messaggio viene trasmesso dall'applicazione che potenzialmente lo crea (chiamato produttore), entra nella piattaforma e viene letto da applicazioni potenzialmente multiple che sono interessate ad esso (chiamate consumatori).

Se è necessario salvare un determinato evento in alcuni luoghi (ad es. Creazione di utenti nel database, magazzino, servizio di invio e-mail e qualsiasi altra cosa si possa inventare), una piattaforma di messaggistica è il modo più chiaro per diffondere quel messaggio.

I consumatori possono estrarre informazioni dai broker (modello pull) o fare in modo che i broker inseriscano le informazioni direttamente nei consumatori (modello push).

Esistono un paio di piattaforme di messaggistica di alto livello popolari:

RabbitMQ - Broker di messaggi che consente un controllo più preciso delle traiettorie dei messaggi tramite regole di routing e altre impostazioni facilmente configurabili. Può essere chiamato un broker intelligente, poiché ha molta logica e tiene traccia dei messaggi che lo attraversano. Fornisce impostazioni per AP e CP da CAP. Utilizza un modello push per la notifica ai consumatori.

Kafka - Message broker (e tutta la piattaforma fuori) che è un po 'più basso livello, in quanto non tiene traccia di quali messaggi sono stati letti e non consente complesse logiche di routing. Ciò consente di ottenere prestazioni straordinarie. Secondo me, questa è la più grande prospettiva in questo spazio con uno sviluppo attivo da parte della comunità open source e il supporto del team Confluent. Kafka ha probabilmente l'uso più diffuso da parte delle migliori aziende tecnologiche. Ho scritto un'introduzione completa a questo, dove vado nel dettaglio di tutta la sua bontà.

Apache ActiveMQ - Il più vecchio del gruppo, risalente al 2004. Utilizza l'API JMS, il che significa che è orientato verso le applicazioni Java EE. È stato riscritto come ActiveMQ Artemis, che offre prestazioni eccezionali alla pari di Kafka.

Amazon SQS - Un servizio di messaggistica fornito da AWS. Ti consente di integrarlo rapidamente con le applicazioni esistenti ed elimina la necessità di gestire la tua infrastruttura, il che potrebbe essere un grande vantaggio, poiché i sistemi come Kafka sono notoriamente difficili da configurare. Amazon offre anche due servizi simili: SNS e MQ, l'ultimo dei quali è fondamentalmente ActiveMQ ma gestito da Amazon.

Applicazioni distribuite

Se si arrotolano i server 5 Rails dietro un unico bilanciamento del carico tutti collegati a un database, è possibile chiamare un'applicazione distribuita? Richiama la mia definizione dall'alto:

Un sistema distribuito è un gruppo di computer che lavorano insieme per apparire all'utente finale come un singolo computer. Queste macchine hanno uno stato condiviso, funzionano contemporaneamente e possono fallire indipendentemente senza influire sul tempo di attività dell'intero sistema.

Se si considera il database come uno stato condiviso, si potrebbe sostenere che questo può essere classificato come un sistema distribuito, ma si sbaglierebbe, poiché si è persa la parte "lavorare insieme" della definizione.

Un sistema viene distribuito solo se i nodi comunicano tra loro per coordinare le loro azioni.

Pertanto, qualcosa come un'applicazione che esegue il suo codice back-end su una rete peer-to-peer può essere meglio classificato come un'applicazione distribuita. Indipendentemente da ciò, questa è tutta una classificazione inutile che non serve a nulla, ma illustra quanto siamo pignoli nel raggruppare le cose.

Scala nota - Sciame di BitTorrent di 193.000 nodi per un episodio di Game of Thrones, aprile 2014

Macchina virtuale Erlang

Erlang è un linguaggio funzionale che ha una grande semantica per la concorrenza, la distribuzione e la tolleranza agli errori. La stessa macchina virtuale Erlang gestisce la distribuzione di un'applicazione Erlang.

Il suo modello funziona avendo molti processi leggeri isolati tutti con la capacità di parlare tra loro attraverso un sistema integrato di passaggio dei messaggi. Questo si chiama Actor Model e le librerie OTP di Erlang possono essere pensate come un framework di attori distribuito (sulla falsariga di Akka per la JVM).

Il modello è ciò che lo aiuta a raggiungere una grande concorrenza piuttosto semplicemente: i processi sono distribuiti tra i core disponibili del sistema che li esegue. Poiché ciò non è distinguibile da un'impostazione di rete (a parte la possibilità di eliminare i messaggi), la VM di Erlang può connettersi ad altre VM Erlang in esecuzione nello stesso data center o anche in un altro continente. Questo sciame di macchine virtuali esegue una singola applicazione e gestisce i guasti della macchina tramite acquisizione (un altro nodo viene pianificato per l'esecuzione).

In effetti, è stato aggiunto lo strato distribuito della lingua per fornire tolleranza d'errore. Il software in esecuzione su un singolo computer è sempre a rischio di morire quel singolo computer e portare offline l'applicazione. Il software in esecuzione su molti nodi consente una più facile gestione degli errori hardware, a condizione che l'applicazione sia stata creata tenendo presente questo aspetto.

BitTorrent

BitTorrent è uno dei protocolli più utilizzati per il trasferimento di file di grandi dimensioni sul Web tramite torrent. L'idea principale è quella di facilitare il trasferimento di file tra diversi peer nella rete senza dover passare attraverso un server principale.

Utilizzando un client BitTorrent, ti connetti a più computer in tutto il mondo per scaricare un file. Quando apri un file .torrent, ti colleghi a un cosiddetto tracker, che è una macchina che funge da coordinatore. Aiuta con il peer discovery, mostrandoti i nodi nella rete che hanno il file desiderato.

una rete di esempio

Hai le nozioni di due tipi di utenti, un leecher e una seminatrice. Un leecher è l'utente che sta scaricando un file e una seminatrice è l'utente che sta caricando tale file.

La cosa divertente delle reti peer-to-peer è che tu, come utente normale, hai la possibilità di unirti e contribuire alla rete.

BitTorrent e i suoi precursori (Gnutella, Napster) ti consentono di ospitare volontariamente file e caricarli su altri utenti che li desiderano. Il motivo per cui BitTorrent è così popolare è che è stato il primo nel suo genere a fornire incentivi per contribuire alla rete. Il freeride, in cui un utente scaricava solo i file, era un problema con i precedenti protocolli di condivisione dei file.

BitTorrent ha risolto il freeride in una certa misura facendo caricare di più i seeder a coloro che offrono le migliori velocità di download. Funziona incentivando il caricamento durante il download di un file. Sfortunatamente, dopo aver terminato, nulla ti rende attivo nella rete. Ciò causa la mancanza di seeders nella rete che dispongono del file completo e poiché il protocollo si basa fortemente su tali utenti, soluzioni come i tracker privati ​​sono state realizzate. I tracker privati ​​richiedono di essere membri di una comunità (spesso solo su invito) per poter partecipare alla rete distribuita.

Dopo i progressi nel campo, sono stati inventati torrent trackerless. Questo è stato un aggiornamento del protocollo BitTorrent che non si basava su tracker centralizzati per la raccolta di metadati e la ricerca di peer, ma utilizzava invece nuovi algoritmi. Uno di questi esempi è Kademlia (Mainline DHT), una tabella hash distribuita (DHT) che consente di trovare peer attraverso altri peer. In effetti, ogni utente svolge i compiti di un tracker.

Registri distribuiti

Un libro mastro distribuito può essere pensato come un database immutabile, di sola aggiunta, replicato, sincronizzato e condiviso su tutti i nodi della rete distribuita.

Scala nota: Ethereum Network ha registrato un picco di 1,3 milioni di transazioni al giorno il 4 gennaio 2018.

Sfruttano il modello di approvvigionamento di eventi, consentendoti di ricostruire lo stato del libro mastro in qualsiasi momento della sua storia.

Blockchain

Blockchain è l'attuale tecnologia di base utilizzata per i registri distribuiti e in effetti ha segnato il loro inizio. Questa ultima e più grande innovazione nello spazio distribuito ha consentito la creazione del primo protocollo di pagamento realmente distribuito: Bitcoin.

Blockchain è un libro mastro distribuito che trasporta un elenco ordinato di tutte le transazioni che sono mai avvenute nella sua rete. Le transazioni sono raggruppate e memorizzate in blocchi. L'intera blockchain è essenzialmente una lista collegata di blocchi (da cui il nome). Detti blocchi sono computazionalmente costosi da creare e sono strettamente collegati tra loro attraverso la crittografia.

Detto semplicemente, ogni blocco contiene un hash speciale (che inizia con una quantità X di zero) del contenuto del blocco corrente (sotto forma di un albero di merkle) più l'hash del blocco precedente. Questo hash richiede molta potenza della CPU per essere prodotto perché l'unico modo per crearlo è attraverso la forza bruta.

Blockchain semplificata

I minatori sono i nodi che provano a calcolare l'hash (tramite bruteforce). Tutti i minatori competono tra loro per chi può inventare una stringa casuale (chiamata nonce) che, quando combinata con il contenuto, produce il suddetto hash. Una volta che qualcuno trova il nonce corretto, lo trasmette a tutta la rete. Detta stringa viene quindi verificata da ciascun nodo da sola e accettata nella loro catena.

Questo si traduce in un sistema in cui è assurdamente costoso modificare la blockchain e assurdamente facile verificare che non sia manomesso.

È costoso modificare i contenuti di un blocco perché ciò produrrebbe un hash diverso. Ricorda che l'hash di ogni blocco successivo dipende da esso. Se dovessi modificare una transazione nel primo blocco dell'immagine sopra, cambieresti la radice di Merkle. Questo a sua volta cambierebbe l'hash del blocco (molto probabilmente senza gli zeri iniziali necessari) - cambierebbe l'hash del blocco # 2 e così via e così via. Ciò significa che dovresti forzare un nuovo nonce per ogni blocco dopo quello appena modificato.

La rete si fida sempre e replica la catena valida più lunga. Per ingannare il sistema ed eventualmente produrre una catena più lunga, avrai bisogno di oltre il 50% della potenza totale della CPU utilizzata da tutti i nodi.

Blockchain può essere pensato come un meccanismo distribuito per il consenso emergente. Il consenso non viene raggiunto esplicitamente: non vi sono elezioni o momenti fissi in cui si verifica il consenso. Invece, il consenso è un prodotto emergente dell'interazione asincrona di migliaia di nodi indipendenti, tutti seguendo le regole del protocollo.

Questa innovazione senza precedenti è recentemente diventata un boom nello spazio tecnologico con le persone che prevedono che segnerà la creazione del Web 3.0. È sicuramente lo spazio più eccitante nel mondo dell'ingegneria del software in questo momento, pieno di problemi estremamente impegnativi e interessanti in attesa di essere risolti.

Bitcoin

Ciò che mancava ai precedenti protocolli di pagamento distribuito era un modo per prevenire praticamente il problema della doppia spesa in tempo reale, in modo distribuito. La ricerca ha prodotto interessanti proposte [1] ma Bitcoin è stato il primo a implementare una soluzione pratica con chiari vantaggi rispetto ad altri.

Il doppio problema di spesa afferma che un attore (ad esempio Bob) non può spendere la sua singola risorsa in due posti. Se Bob ha $ 1, non dovrebbe essere in grado di darlo sia ad Alice che a Zack - è solo una risorsa, non può essere duplicata. Si scopre che è davvero difficile ottenere veramente questa garanzia in un sistema distribuito. Esistono alcuni approcci di mitigazione interessanti che precedono la blockchain, ma non risolvono completamente il problema in modo pratico.

La doppia spesa viene risolta facilmente da Bitcoin, poiché alla catena viene aggiunto solo un blocco alla volta. La doppia spesa è impossibile in un singolo blocco, quindi anche se vengono creati due blocchi contemporaneamente - solo uno verrà a trovarsi sulla catena più lunga.

Bitcoin si basa sulla difficoltà di accumulare potenza della CPU.

Mentre in un sistema di voto un utente malintenzionato deve solo aggiungere nodi alla rete (il che è facile, poiché l'accesso gratuito alla rete è un obiettivo di progettazione), in uno schema basato sulla potenza della CPU un utente malintenzionato deve affrontare una limitazione fisica: ottenere l'accesso a sempre di più hardware potente.

Questo è anche il motivo per cui gruppi di nodi dannosi devono controllare oltre il 50% della potenza computazionale della rete per trasportare effettivamente qualsiasi attacco riuscito. Meno di questo, e il resto della rete creerà una blockchain più lunga più velocemente.

Ethereum

Ethereum può essere pensato come una piattaforma software programmabile basata su blockchain. Ha la sua criptovaluta (Ether) che alimenta la distribuzione di contratti intelligenti sulla sua blockchain.

I contratti intelligenti sono un pezzo di codice archiviato come singola transazione nella blockchain di Ethereum. Per eseguire il codice, tutto ciò che devi fare è emettere una transazione con un contratto intelligente come destinazione. Questo a sua volta fa sì che i nodi miner eseguano il codice e qualsiasi modifica subisca. Il codice viene eseguito all'interno della macchina virtuale Ethereum.

Solidità, il linguaggio di programmazione nativo di Ethereum, è ciò che viene utilizzato per scrivere contratti intelligenti. È un linguaggio di programmazione completo che si interfaccia direttamente con la blockchain di Ethereum, permettendoti di interrogare stati come saldi o altri risultati di contratti intelligenti. Per evitare loop infiniti, l'esecuzione del codice richiede una certa quantità di Ether.

Dato che la blockchain può essere interpretata come una serie di cambiamenti di stato, molte applicazioni distribuite (DApps) sono state costruite su Ethereum e piattaforme simili.

Ulteriori usi di registri distribuiti

Prova dell'esistenza - Un servizio per archiviare in modo anonimo e sicuro la prova dell'esistenza di un determinato documento digitale in un determinato momento. Utile per garantire l'integrità, la proprietà e il timestamp del documento.

Organizzazioni autonome decentralizzate (DAO): organizzazioni che utilizzano la blockchain come mezzo per raggiungere il consenso sulle proposte di miglioramento dell'organizzazione. Esempi sono il sistema di governance di Dash, il progetto SmartCash

Autenticazione decentralizzata: archivia la tua identità sulla blockchain, consentendoti di utilizzare Single Sign-On (SSO) ovunque. Sovrin, Civic

E molti altri ancora. La tecnologia di contabilità distribuita ha davvero aperto infinite possibilità. Alcuni sono probabilmente inventati mentre parliamo!

Sommario

Nel breve periodo di questo articolo, siamo riusciti a definire cos'è un sistema distribuito, perché dovresti usarne uno e andare oltre ogni categoria un po '. Alcune cose importanti da ricordare sono:

  • I sistemi distribuiti sono complessi
  • Sono scelti per necessità di scala e prezzo
  • Sono più difficili da lavorare
  • Teorema della PAC - Coerenza / disponibilità
  • Hanno 6 categorie: archivi dati, informatica, file system, sistemi di messaggistica, registri, applicazioni

Ad essere sinceri, abbiamo appena toccato la superficie su sistemi distribuiti. Non ho avuto la possibilità di affrontare e spiegare a fondo problemi fondamentali come consenso, strategie di replica, ordinazione e tempo degli eventi, tolleranza ai guasti, trasmissione di un messaggio attraverso la rete e altri.

Attenzione

Lascia che ti lasci un avvertimento di separazione:

Devi allontanarti il ​​più possibile dai sistemi distribuiti. La complessità ambientale che incorrono con se stessi non vale la pena se riesci ad evitare il problema risolvendolo in un modo diverso o con qualche altra soluzione pronta all'uso.

[1]
Lotta contro la doppia spesa utilizzando i sistemi cooperativi P2P, 25-27 giugno 2007 - una soluzione proposta in cui ogni "moneta" può scadere e le viene assegnato un testimone (validatore).

Bitgold, dicembre 2005 - Una panoramica di alto livello di un protocollo estremamente simile a quello di Bitcoin. Si dice che questo sia il precursore di Bitcoin.

Ulteriore lettura di sistemi distribuiti:

Progettando applicazioni ad alta intensità di dati, Martin Kleppmann - Un grande libro che ripercorre tutto nei sistemi distribuiti e altro ancora.

Cloud Computing Specialization, University of Illinois, Coursera - Una lunga serie di corsi (6) che analizzano concetti di sistema distribuito, applicazioni

Jepsen - Blog che spiega molte tecnologie distribuite (ElasticSearch, Redis, MongoDB, ecc.)

Grazie per aver dedicato del tempo a leggere questo lungo articolo (~ 5600 parole)!

Se, per caso, hai trovato questo informativo o hai pensato che ti fornisse valore, assicurati di dargli il maggior numero di applausi che ritieni meriti e considera la condivisione con un amico che potrebbe usare un'introduzione a questo meraviglioso campo di studio.

~ Stanislav Kozlovski

Aggiornare

Attualmente lavoro in Confluent. Confluent è una società di Big Data fondata dai creatori di Apache Kafka stessi! Sono immensamente grato per l'opportunità che mi hanno dato - attualmente lavoro su Kafka stesso, il che è fantastico! Confluent contribuisce a modellare l'intero ecosistema Kafka open source, inclusa una nuova offerta cloud gestita come servizio Kafka.

Stiamo assumendo molte posizioni (in particolare SRE / Software Engineers) in Europa e negli Stati Uniti! Se sei interessato a lavorare su Kafka stesso, alla ricerca di nuove opportunità o semplicemente curioso, assicurati di inviarmi un messaggio su Twitter e condividerò tutti i grandi vantaggi che derivano dal lavorare in un'azienda della baia.