{"id":55009,"date":"2020-01-10T00:00:00","date_gmt":"2020-01-09T21:00:00","guid":{"rendered":"https:\/\/prohoster.info\/blog\/blog_prohoster\/arhitektura-hraneniya-i-otdachi-fotografij-v-badoo"},"modified":"2020-02-18T14:03:04","modified_gmt":"2020-02-18T11:03:04","slug":"arhitektura-hraneniya-i-otdachi-fotografij-v-badoo","status":"publish","type":"post","link":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/arhitektura-hraneniya-i-otdachi-fotografij-v-badoo","title":{"rendered":"Architettura di memorizzazione e distribuzione delle foto in Badoo","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/04d68ff091d9d271bfd352a6639e2f20.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<h2>Artem Denisov ( <noindex><a rel=\"nofollow\" href=\"https:\/\/habrahabr.ru\/users\/bo0rsh201\/\" class=\"user_link\">bo0rsh201<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/habrahabr.ru\/company\/badoo\/\">Badoo<\/a><\/noindex>)<\/h2>\n<p>\nBadoo \u00e8 il pi\u00f9 grande sito di incontri al mondo. Attualmente abbiamo circa 330 milioni di utenti registrati in tutto il mondo. Ma ci\u00f2 che \u00e8 molto pi\u00f9 importante nel contesto della nostra conversazione di oggi \u00e8 che conserviamo circa 3 petabyte di fotografie degli utenti. Ogni giorno i nostri utenti caricano circa 3,5 milioni di nuove foto, e il carico di lettura si attesta intorno a <b>80.000 richieste al secondo<\/b>. Questo \u00e8 un carico considerevole per il nostro backend, e a volte presentiamo alcune difficolt\u00e0.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/4e4690f9b0d95bd76fbbc1cd6805c26c.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nParler\u00f2 del design di questo sistema, che archivia e restituisce le foto in generale, e dar\u00f2 uno sguardo dal punto di vista dello sviluppatore. Faremo una breve retrospettiva sulla sua evoluzione, dove segner\u00f2 i principali traguardi, ma parler\u00f2 in modo pi\u00f9 dettagliato solo delle soluzioni che utilizziamo attualmente.<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><br \/>\nE ora iniziamo.<\/p>\n<p><center><div class=\"youtube-placeholder\" data-id=\"SU9ETg39FEg\" onclick=\"loadVideo(this)\">\r\n        <img decoding=\"async\" src=\"https:\/\/img.youtube.com\/vi\/SU9ETg39FEg\/hqdefault.jpg\" alt=\"Riproduci video\" loading=\"lazy\" width=\"480\" height=\"360\" style=\"width:100%;height:auto;\">\r\n        <div class=\"play-button\"><\/div>\r\n    <\/div><\/center><br \/>\nCome ho gi\u00e0 detto, questa sar\u00e0 una retrospettiva, e per cominciare prendiamo l'esempio pi\u00f9 banale.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/22b9627cda7ccadd9869b64e9d043d89.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nAbbiamo un compito generale: dobbiamo ricevere, archiviare e restituire le fotografie degli utenti. In questo formato, il compito \u00e8 generale, possiamo utilizzare qualsiasi cosa:<\/p>\n<ul>\n<li>un moderno cloud storage,<\/li>\n<li>una soluzione preconfezionata, ce ne sono molte;<\/li>\n<li>possiamo configurare diverse macchine nel nostro data center e installare grandi dischi rigidi per archiviare le foto l\u00ec.<\/li>\n<\/ul>\n<p>\nBadoo storicamente \u2014 e ora, come allora (ai tempi in cui \u00e8 nato) \u2014 vive sui propri server, all'interno dei nostri data center. Quindi per noi questa opzione era ottimale.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/9434fbabada15670297c551066ad7e71.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nAbbiamo semplicemente preso alcune macchine, le abbiamo chiamate 'photos' e ci siamo creati un cluster che archivia le foto. Ma sembra che ci sia qualcosa che manca. Per far funzionare tutto questo, dobbiamo in qualche modo definire su quale macchina archivieremo quali foto. E qui non c'\u00e8 bisogno di scoprire l'America.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/36258e7107fd8c60f7e9e563a2cb681c.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nAggiungiamo al nostro storage con informazioni sugli utenti un campo. Questo sar\u00e0 la chiave di sharding. Nel nostro caso lo abbiamo chiamato place_id, e questo id indica il luogo in cui sono archiviate le foto degli utenti. Creiamo delle mappe.<\/p>\n<p>Nella prima fase, possiamo farlo anche manualmente: diciamo che la foto di questo utente con tale luogo sar\u00e0 archiviata su tale server. Grazie a questa mappa, sappiamo sempre dove salvare una foto quando un utente la carica e da dove restituirla.<\/p>\n<p>\u00c8 uno schema del tutto banale, ma presenta vantaggi significativi. Primo, \u00e8 semplice, come ho gi\u00e0 detto, e secondo, con questo approccio possiamo facilmente scalare orizzontalmente, semplicemente aggiungendo nuove macchine e inserendole nella mappa. Non serve fare altro.<\/p>\n<p>Cos\u00ec \u00e8 stato per un certo periodo.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/3effb442702f162f7bad9c18ec54392e.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nEra intorno al 2009. Consegnavamo macchine, ne portavamo...<\/p>\n<p>E a un certo punto abbiamo iniziato a notare che questo schema presentava alcuni svantaggi. Quali svantaggi?<\/p>\n<p>Prima di tutto, la capacit\u00e0 limitata. Non possiamo inserire tanti dischi rigidi in un singolo server fisico come vorremmo. E col passare del tempo e l'aumento del dataset \u00e8 diventato un problema.<\/p>\n<p>Secondo. Si tratta di una configurazione non comune delle macchine, poich\u00e9 tali macchine sono difficili da riutilizzare in altri cluster; sono piuttosto specifiche, cio\u00e8 devono avere prestazioni basse, ma allo stesso tempo un grande disco rigido.<\/p>\n<p>Tutto ci\u00f2 risale al 2009, ma in realt\u00e0 queste esigenze sono attuali anche oggi. Abbiamo una retrospettiva, quindi nel 2009 tutto andava male sotto questo aspetto.<\/p>\n<p>E l'ultimo punto \u00e8 il costo.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/e49010eaeab139199d8fe010caa65bf0.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nAll'epoca i costi erano molto alti e dovevamo trovare delle alternative. Dovevamo ottimizzare meglio sia lo spazio nei data center che i server fisici su cui tutto era collocato. I nostri ingegneri di sistema avviarono una grande ricerca, esaminando vari scenari. Guardarono anche ai file system clusterizzati, come PolyCeph e Lustre. L\u00ec c'erano problemi di prestazioni e manutenzione piuttosto gravosa. Decisero di non proseguire. Provarono a montare l'intero dataset tramite NFS su ogni macchina, per cercare di scalare in questo modo. Anche la lettura risult\u00f2 problematica, tentarono diverse soluzioni da vari fornitori.<\/p>\n<p>E alla fine ci decidemmo per l'uso di quello che chiamiamo Storage Area Network.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/e99402fa641f3bd5fc8d57a9f8995642.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nQuesti sono grandi SHD, progettati per gestire grandi volumi di dati. Si tratta di scaffalature con dischi montati su macchine di erogazione finali tramite fibra ottica. Abbiamo quindi un pool di macchine abbastanza ridotto e questi SHD, che sono trasparenti per la nostra logica di erogazione, cio\u00e8 per il nostro nginx o per qualsiasi altro, gestiscono le richieste per queste foto.<\/p>\n<p>Questo sistema presenta vantaggi evidenti. Si tratta di SHD. \u00c8 progettato per memorizzare foto. Risulta pi\u00f9 economico che allestire semplicemente macchine con dischi rigidi.<\/p>\n<p>Un secondo vantaggio. <\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/7fd2e7d629cc239096b14c68be5f76bf.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nLa capacit\u00e0 \u00e8 aumentata notevolmente, cio\u00e8 possiamo collocare un volume di storage molto maggiore in uno spazio molto pi\u00f9 ridotto.<\/p>\n<p>Tuttavia, ci sono stati anche svantaggi che si sono manifestati abbastanza rapidamente. Con l'aumento del numero di utenti e del carico su questo sistema, sono emerse problematiche di performance. E il problema qui \u00e8 piuttosto evidente: qualsiasi SHD, destinato a memorizzare molte foto in uno spazio ridotto, tende a soffrire di letture intense. Questo \u00e8 attuale sia per qualsiasi storage cloud che per qualsiasi altra cosa. Attualmente non esiste uno storage ideale che sia infinitamente scalabile, dove si possa inserire di tutto e che resista bene alle letture, soprattutto a quelle casuali.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/566e836e2fe13a2a3d040ae3fa865d6d.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nCome nel caso delle nostre foto, poich\u00e9 le foto vengono richieste in modo incoerente, ci\u00f2 influisce notevolmente sulle loro performance.<\/p>\n<p>Anche rispetto ai numeri di oggi, se abbiamo un picco superiore a 500 RPS per le foto su una macchina connessa allo storage, gi\u00e0 iniziano i problemi. Questo \u00e8 stato abbastanza problematico per noi, perch\u00e9 il numero di utenti continua a crescere e la situazione non pu\u00f2 che peggiorare. Dobbiamo ottimizzare in qualche modo.<\/p>\n<p>Per ottimizzare, allora, abbiamo deciso di esaminare il profilo di carico \u2014 cosa stava succedendo e cosa dovevamo ottimizzare.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/d67310e6b90c4ee1337065790576c9a0.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nE qui tutto gioca a nostro favore.<\/p>\n<p>Nel primo slide ho gi\u00e0 detto: abbiamo 80.000 richieste al secondo per la lettura, con soli 3,5 milioni di upload al giorno. C'\u00e8 quindi una differenza di tre ordini di grandezza. Ovviamente, dobbiamo ottimizzare la lettura e si capisce praticamente come.<\/p>\n<p>C'\u00e8 anche un altro piccolo dettaglio. La specificit\u00e0 del servizio \u00e8 tale che quando una persona si registra, carica una foto, inizia a guardare attivamente le foto di altre persone, a mettere 'mi piace', e viene mostrata attivamente ad altri. Poi, trova un partner o meno, come va, e per un certo periodo smette di utilizzare il servizio. In quel momento, quando lo utilizza, le sue foto sono molto 'calde' \u2014 sono richieste e vengono visualizzate da molte persone. Appena smette, per\u00f2, rapidamente esce da quelle esposizioni intense ad altre persone, come avveniva prima, e le sue foto praticamente non vengono pi\u00f9 richieste.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/dcc7e306055d8f2b0895f24679bfc3e2.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nQuindi abbiamo un dataset molto ristretto ma con un volume elevato di richieste. Una soluzione ovvia \u00e8 quella di aggiungere una cache.<\/p>\n<p>Una cache con LRU risolver\u00e0 tutti i nostri problemi. Cosa facciamo?<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/2bd0c88a97d928f386db21549fc02500.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nAggiungiamo davanti al nostro grande cluster di storage un altro cluster relativamente piccolo, che chiamiamo fotocache (photoscache). \u00c8, sostanzialmente, un semplice proxy di caching.<\/p>\n<p>Come funziona internamente? Ecco il nostro utente, ecco lo storage. Tutto come prima. Cosa aggiungiamo tra di loro?<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/7b7b5f102f1c012b2aef8f02ec731fac.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n\u00c8 semplicemente una macchina con un disco locale fisico che \u00e8 veloce. Questo \u00e8 un SSD, ad esempio. E su questo disco viene memorizzata qualche cache locale.<\/p>\n<p>Come appare? L'utente invia una richiesta per una foto. NGINX la cerca prima nella cache locale. Se non c'\u00e8, fa semplicemente proxy_pass verso il nostro storage, scarica la foto da l\u00ec e la fornisce all'utente.<\/p>\n<p>Ma \u00e8 molto semplice e poco chiaro cosa succeda all'interno. Funziona pi\u00f9 o meno in questo modo.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/46be24df171d1008e2a9099b7e4c9be6.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nLa cache \u00e8 logicamente separata in tre livelli. Quando parlo di \u00abtre livelli\u00bb, non significa che ci sia un sistema complesso. No, si tratta semplicemente di tre directory nel filesystem:<\/p>\n<ol>\n<li>Questo \u00e8 un buffer, dove finiscono le fotografie appena caricate dal proxy.<\/li>\n<li>Questo \u00e8 il cache caldo, dove sono memorizzate le foto attualmente richieste attivamente.<\/li>\n<li>E il cache freddo, dove le foto vengono lentamente trasferite dal caldo quando ricevono meno richieste.<\/li>\n<\/ol>\n<p>\nAffinch\u00e9 ci\u00f2 funzioni, dobbiamo gestire questa cache in modo da spostare le fotografie al suo interno, ecc. Anche questo \u00e8 un processo molto primitivo.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/9b16fe3e99a5f88f06169f6e5eedf2b9.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nNginx scrive semplicemente su access.log su RAMDisk per ogni richiesta, specificando il percorso dell'immagine che sta servendo attualmente (naturalmente, il percorso relativo) e la sezione da cui \u00e8 stata servita. Cio\u00e8, potrebbe essere scritto \"foto 1\" e poi o buffer, o cache calda, o cache fredda, o proxy.<\/p>\n<p>A seconda di questo, dobbiamo decidere cosa fare con la foto.<\/p>\n<p>Su ogni macchina abbiamo un piccolo demone che legge costantemente questo log e memorizza le statistiche sull'uso delle varie fotografie.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/0dceda5e5ff432d1609520f0c152f152.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nRaccoglie semplicemente le informazioni, mantiene i contatori e periodicamente esegue le seguenti operazioni. Le fotografie che ricevono molte richieste vengono spostate nella cache calda, indipendentemente da dove si trovano.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/941c13ecfea88372f3a7eb62d81b0c4e.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nLe fotografie che vengono richieste raramente e che sono state richieste meno frequentemente vengono gradualmente spostate dalla cache calda a quella fredda.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/a07235246995ad2fa4e6aeccae23a629.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nE quando la nostra cache si riempie, iniziamo semplicemente a rimuovere tutto dalla cache fredda senza fare distinzioni. E questo, tra l'altro, funziona molto bene.<\/p>\n<p>Per garantire che la foto venga salvata immediatamente durante il proxying nel buffer, usiamo la direttiva proxy_store e il buffer \u00e8 anch'esso su RAMDisk, quindi per l'utente funziona molto rapidamente. Questo riguarda l'interno stesso del server di caching.<\/p>\n<p>Rimane la questione di come distribuire le richieste tra questi server.<\/p>\n<p>Supponiamo che ci sia un cluster di venti macchine di storage e tre server di caching (\u00e8 andata cos\u00ec).<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/6bc970b687701f3b6d57e153e3abed18.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nDobbiamo in qualche modo determinare quali richieste sono per quali foto e dove devono andare.<\/p>\n<p>La soluzione pi\u00f9 banale \u00e8 il Round Robin. Oppure farlo in modo casuale?<\/p>\n<p>Questo, ovviamente, presenta diversi svantaggi, perch\u00e9 useremo in modo molto inefficiente la cache in tale situazione. Le richieste verranno indirizzate a macchine casuali: qui \u00e8 stata memorizzata, accanto non c'\u00e8 pi\u00f9. E tutto questo, se funziona, funzioner\u00e0 molto male. Anche con un numero ridotto di macchine nel cluster.<\/p>\n<p>Dobbiamo in qualche modo determinare in modo inequivocabile su quale server inviare quale richiesta.<\/p>\n<p>C'\u00e8 un modo banale. Prendiamo l'hash dell'URL o l'hash della nostra chiave di sharding, che \u00e8 nell'URL, e lo dividiamo interamente per il numero di server. Funzioner\u00e0? Funzioner\u00e0.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/794a82ac1268b651ab936f0225b802a2.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nCio\u00e8, abbiamo una richiesta sicura, ad esempio, per un \"example_url\" che andr\u00e0 sempre sul server con indice \"2\", e la cache sar\u00e0 costantemente utilizata nel modo migliore.<\/p>\n<p>Ma sorge un problema con il resharding in un simile schema. Per resharding intendo il cambiamento del numero di server.<\/p>\n<p>Supponiamo che il nostro cluster di caching non riesca a gestire il carico e decidiamo di aggiungere un'altra macchina.<\/p>\n<p>Aggiungiamo.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/5f2fcba4c4f267c069811c3677bd0213.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nAdesso tutto viene suddiviso non pi\u00f9 su tre, ma su quattro. Di conseguenza, praticamente tutte le chiavi che avevamo, praticamente tutte le URL, ora risiedono su altri server. Tutta la cache viene invalidata istantaneamente. Tutte le richieste si riversano sul nostro cluster di storage, ne soffre, si verificano errori di servizio e utenti insoddisfatti. Non vogliamo che succeda.<\/p>\n<p>Questa opzione non ci va bene.<\/p>\n<p>Quindi, cosa dobbiamo fare? Dobbiamo in qualche modo utilizzare efficacemente la cache, inviare costantemente una richiesta allo stesso server, ma essere anche resilienti al resharding. E esiste una soluzione, non \u00e8 poi cos\u00ec complicata. Si chiama hashing consistente.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/1380758686274df9755a7ebf7d1c8753.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nCome appare?<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/44f97abfac46fa9f361055548819e8a3.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nPrendiamo una certa funzione dalla chiave di sharding e distribuiamo tutti i suoi valori su una circonferenza. Cio\u00e8, nel punto 0 si incontrano i suoi valori minimi e massimi. Poi, sulla stessa circonferenza, posizioniamo tutti i nostri server in modo simile:<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/d470ec615a789913a6baa2726b05acea.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nOgni server \u00e8 identificato da un punto, e il settore che va da esso in senso orario \u00e8 servito da questo host. Quando ci arrivano richieste, vediamo subito che, ad esempio, la richiesta A ha un certo hash e viene servita dal server 2. La richiesta B dal server 3. E cos\u00ec via.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/fcdbd1caa9f1162cf02e8b0a1c79cb74.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nCosa succede in questa situazione durante il resharding?<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/7386cda826e9419d5f8a9a0d6d6703c8.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nNon invalidiamo tutta la cache, come avveniva prima, e non spostiamo tutte le chiavi, ma spostiamo ciascun settore di una piccola distanza in modo che nel posto libero, per cos\u00ec dire, possa rientrare il nostro sesto server, che desideriamo aggiungere, e lo aggiungiamo l\u00ec.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/8680e0cf023ce911b4d162e9102c0545.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nCertamente, in tale situazione anche le chiavi si spostano. Ma si spostano molto meno rispetto a prima. E vediamo che le nostre prime due chiavi rimangono sui loro server, e solo per l'ultima chiave cambia il server di caching. Funziona abbastanza bene, e se aggiungi nuovi host in modo incrementale, non ci sono grandi problemi. Aggiungi un po' alla volta, aspetti che la cache si riempia di nuovo e tutto funziona correttamente.<\/p>\n<p>L'unica domanda che rimane riguarda i guasti. Supponiamo che un nostro server si sia guastato.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/8e3301af782ce8983716c4bc9add79a5.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nE in quel momento non vorremmo davvero rigenerare questa mappa, invalidare parte della cache e cos\u00ec via, se, ad esempio, il server \u00e8 stato riavviato e dobbiamo gestire le richieste. Manteniamo semplicemente un'istanza di backup della cache fotografica in ogni centro, che funge da sostituto per qualsiasi macchina attualmente guasta. Se un server diventa improvvisamente inaccessibile, il traffico viene indirizzato l\u00ec. Naturalmente, non abbiamo alcuna cache, quindi \u00e8 fredda, ma almeno le richieste degli utenti vengono elaborate. Se questo intervallo \u00e8 breve, possiamo affrontarlo tranquillamente. C'\u00e8 solo un carico maggiore sullo storage. Se l'intervallo \u00e8 lungo, possiamo gi\u00e0 decidere di rimuovere quel server dalla mappa o sostituirlo con un altro.<\/p>\n<p>Questo riguarda il sistema di caching. Vediamo i risultati.<\/p>\n<p>A prima vista, non sembra esserci nulla di complesso qui. Ma questo metodo di gestione della cache ci ha dato un tasso di hit di circa il 98%. Ovvero, di queste 80 mila richieste al secondo, solo 1600 arrivano allo storage, e questo \u00e8 un carico perfettamente normale che riescono a sostenere agevolmente, abbiamo sempre una riserva.<\/p>\n<p>Abbiamo collocato questi server in tre dei nostri data center, ottenendo tre punti di presenza: Praga, Miami e Hong Kong.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/64eef492b65a014d8ba3c808b6579b41.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nIn questo modo, sono pi\u00f9 o meno localizzati vicino a ciascuno dei nostri mercati target.<\/p>\n<p>E come piacevole bonus, abbiamo ottenuto questo proxy di caching, il cui CPU in realt\u00e0 rimane inattivo, perch\u00e9 non \u00e8 cos\u00ec necessario per la consegna dei contenuti. E l\u00ec, usando NGINX+Lua, abbiamo implementato molte logiche utilitaristiche.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/b65c609df5e1985240d04ee65a3e4f55.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nAd esempio, possiamo sperimentare con webp o jpeg progressivi (questi sono formati moderni ed efficienti), vedere come influiscono sul traffico, prendere decisioni, attivarli per determinati paesi, e cos\u00ec via; effettuare il ridimensionamento dinamico o il ritaglio delle foto al volo.<\/p>\n<p>Questo \u00e8 un buon caso d'uso, ad esempio, quando avete un'app mobile che mostra foto, e l'app non vuole far utilizzare CPU al client per richiedere una grande foto e ridimensionarla poi a una dimensione per adattarla nella vista. Possiamo semplicemente specificare dinamicamente alcuni parametri nell'URL, e la cache fotografica ridimensioner\u00e0 automaticamente l'immagine. Di solito, sceglie la dimensione che abbiamo fisicamente sul disco, il pi\u00f9 vicino possibile a quella richiesta, e la downscaler\u00e0 nelle coordinate specifiche.<\/p>\n<blockquote><p>A proposito, abbiamo reso disponibili al pubblico le registrazioni video degli ultimi cinque anni delle conferenze degli sviluppatori di sistemi ad alto carico <noindex><a rel=\"nofollow\" href=\"http:\/\/www.highload.ru\/\">HighLoad++<\/a><\/noindex>. Guardate, studiate, condividete e iscrivetevi al <noindex><a rel=\"nofollow\" href=\"https:\/\/www.youtube.com\/user\/profyclub\">canale YouTube<\/a><\/noindex>.<\/p><\/blockquote>\n<p>\nPossiamo anche aggiungere molta logica di prodotto. Ad esempio, possiamo aggiungere diverse filigrane in base ai parametri dell'URL, possiamo sfocare le foto, rendere tutto sfocato o pixelato. Questo quando vogliamo mostrare una foto di una persona, ma non vogliamo mostrare il suo volto, funziona bene, \u00e8 tutto realizzato qui.<\/p>\n<p>Cosa abbiamo ottenuto? Abbiamo ottenuto tre punti di presenza, un buon tasso di hit, e nel contempo il CPU di queste macchine non rimane inattivo. \u00c8 diventato, ovviamente, pi\u00f9 importante di prima. Dobbiamo installare macchine pi\u00f9 potenti, ma ne vale la pena.<\/p>\n<p>Questo riguarda la consegna delle foto. Qui tutto \u00e8 abbastanza chiaro e ovvio. Penso di non aver scoperto l'America, cos\u00ec funziona praticamente qualsiasi CDN.<\/p>\n<p>E, molto probabilmente, l'ascoltatore esperto potrebbe aver avuto la domanda: perch\u00e9 non sostituire tutto con un CDN? Sarebbe pi\u00f9 o meno la stessa cosa, tutti i moderni CDN possono farlo. E ci sono diverse ragioni.<\/p>\n<p>La prima sono le foto.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/592c10eb74d46191bfcedec120f68556.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nQuesto \u00e8 uno dei punti chiave della nostra infrastruttura, e abbiamo bisogno di avere il maggior controllo possibile su di esse. Se si tratta di una soluzione di un fornitore terzo e non si ha alcun potere su di essa, diventa abbastanza difficile viverci quando si ha un grande dataset e un flusso molto elevato di richieste degli utenti.<\/p>\n<p>Facciamo un esempio. Attualmente, sulla nostra infrastruttura, possiamo accedere a una macchina, ad esempio in caso di problemi o rumori sotterranei, per fare debug, per cos\u00ec dire. Possiamo raccogliere delle metriche specifiche di cui abbiamo bisogno, sperimentare in vari modi, osservando come ci\u00f2 influisce sui grafici e cos\u00ec via. Attualmente, stiamo raccogliendo una grande quantit\u00e0 di statistiche da questo cluster di cache. E periodicamente le esaminiamo e analizziamo a lungo alcune anomalie. Se fosse tutto lato CDN, sarebbe molto pi\u00f9 difficile controllarlo. Oppure, ad esempio, se si verifica un incidente, sappiamo cosa \u00e8 successo, sappiamo come gestirlo e superarlo. Questa \u00e8 la prima conclusione.<\/p>\n<p>La seconda conclusione \u00e8 pi\u00f9 di tipo storico, poich\u00e9 il sistema si \u00e8 sviluppato a lungo e ci sono state molte diverse esigenze aziendali in vari momenti, e non sempre queste si adattano al concetto di CDN.<\/p>\n<p>E il punto che ne deriva \u00e8 che<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/007cf3aed2f9cc12185fc3865bf9d196.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nC'\u00e8 molta logica specifica nei nostri foto-cache, che non sempre pu\u00f2 essere aggiunta su richiesta. \u00c8 difficile che un CDN introduca qualcosa di personalizzato per la vostra richiesta. Ad esempio, la crittografia degli URL, se non volete che il cliente possa modificare qualcosa. Volete cambiare l'URL sul server e crittografarlo, per poi restituire qui alcuni parametri dinamici.<\/p>\n<p>Qual \u00e8 la conclusione che si impone? Nel nostro caso, il CDN non \u00e8 un'ottima alternativa.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/cfc2963cca2357cf6b0f63419a4dc436.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nE nel vostro caso, se avete esigenze aziendali specifiche, potete implementare tranquillamente ci\u00f2 che vi ho mostrato. E con un profilo di carico simile, funzioner\u00e0 benissimo.<\/p>\n<p>Ma se avete una soluzione generale e la vostra esigenza non \u00e8 molto specifica, potete tranquillamente usare un CDN. O se per voi \u00e8 molto pi\u00f9 importante il tempo e le risorse, piuttosto che il controllo.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/b76d25404918a5d0d8bf1d6644c8d873.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nE i moderni CDN hanno praticamente tutto ci\u00f2 di cui vi ho parlato ora. Ad eccezione di alcune funzionalit\u00e0 pi\u00f9 o meno.<\/p>\n<p>Questo riguarda la distribuzione delle fotografie.<\/p>\n<p>Ora spostiamoci un po' pi\u00f9 avanti nella nostra retrospettiva e parliamo dell'archiviazione.<\/p>\n<p>L'anno era il 2013.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/f218bfc899512041967842430c02aa9b.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nI server di caching erano stati aggiunti, e i problemi con le performance erano scomparsi. Tutto andava bene. Il dataset cresceva. Nel 2013 avevamo circa 80 server connessi agli storage, e circa 40 server di caching in ogni data center. Parliamo di 560 terabyte di dati per ogni data center, quindi intorno a un petabyte in totale.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/ef741ba4a9164e6940f55e93dfb46ef0.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nE con la crescita del dataset, i costi operativi sono aumentati notevolmente. In cosa consisteva questo?<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/6cf5e489a4e97bc6e26fc6d4d16505b5.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nNello schema disegnato \u2014 con SAN, le macchine collegate e le cache \u2014 ci sono molti punti di guasto. Se prima abbiamo gi\u00e0 affrontato i guasti dei server di caching, dove tutto era relativamente prevedibile e chiaro, sul lato storage era molto peggio.<\/p>\n<p>In primo luogo, il Storage Area Network (SAN) stesso pu\u00f2 guastarsi.<\/p>\n<p>In secondo luogo, \u00e8 collegato tramite fibra ottica alle macchine finali. Possono esserci problemi con le schede ottiche e gli switch.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/6959b79284c5b1244a70a1d64f191893.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nCe ne sono certamente meno rispetto al SAN stesso, ma sono comunque punti di guasto.<\/p>\n<p>In seguito, la macchina stessa, collegata allo storage, pu\u00f2 anche guastarsi.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/1801cb502663a4de14329a5e67dfed79.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nIn totale, abbiamo tre punti di guasto.<\/p>\n<p>Inoltre, al di l\u00e0 dei punti di guasto, c'\u00e8 la manutenzione pesante degli storage stessi.<\/p>\n<p>\u00c8 un sistema complesso e multi-componente, e per gli ingegneri di sistema pu\u00f2 essere difficile gestirlo.<\/p>\n<p>E l'ultimo, e pi\u00f9 importante punto. Se in uno di questi tre punti si verifica un guasto, abbiamo una probabilit\u00e0 non nullo di perdere i dati degli utenti, poich\u00e9 il filesystem potrebbe danneggiarsi.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/4bf8bc1c73a2beef74cb4ee0ee45679b.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nSupponiamo che il filesystem si sia danneggiato. Il suo ripristino richiede tempo \u2014 pu\u00f2 richiedere una settimana con grandi volumi di dati. Inoltre, alla fine, probabilmente otterremo una serie di file incomprensibili da abbinare alle fotografie degli utenti. E rischiamo di perdere dati. Il rischio \u00e8 piuttosto alto. E pi\u00f9 spesso si verificano tali situazioni, e pi\u00f9 problemi sorgono lungo tutta questa catena, maggiore \u00e8 il rischio.<\/p>\n<p>Bisognava fare qualcosa a riguardo. E abbiamo deciso che era necessario semplicemente fare un backup dei dati. \u00c8 davvero una soluzione ovvia e valida. Cosa abbiamo fatto?<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/f80ec2b65003c40bd2fabf88966b3e05.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nEcco com'era il nostro server, collegato allo storage, prima. C'era una partizione principale, un dispositivo a blocchi che rappresenta in realt\u00e0 un mount su uno storage remoto tramite fibra ottica.<\/p>\n<p>Abbiamo semplicemente aggiunto una seconda partizione.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/d3dba75ef477269d92145cd69d587527.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nAbbiamo installato un secondo storage (fortunatamente, \u00e8 relativamente economico), e lo abbiamo chiamato partizione di backup. Anche questo \u00e8 collegato tramite fibra ottica, sulla stessa macchina. Ma dobbiamo in qualche modo sincronizzare i dati tra di loro.<\/p>\n<p>Qui abbiamo semplicemente creato una coda asincrona accanto.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/67bced2b45c589009cfb01a1c21398a5.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nNon \u00e8 molto carica. Sappiamo che abbiamo pochi record. La coda \u00e8 semplicemente una tabella in MySQL, dove si scrivono righe tipo \"devo fare il backup di questa foto\". A ogni modifica o upload copiamo dalla partizione principale al backup in modo asincrono o attraverso qualche background worker.<\/p>\n<p>In questo modo abbiamo sempre due partizioni consistenti. Anche se una parte di questo sistema si guasta, possiamo sempre sostituire la partizione principale con il backup, e tutto continuer\u00e0 a funzionare.<\/p>\n<p>Ma a causa di questo, il carico in lettura aumenta notevolmente, poich\u00e9 oltre ai clienti che leggono dalla partizione principale, perch\u00e9 prima guardano la foto l\u00ec (\u00e8 pi\u00f9 fresca), poi cercano sul backup, se non la trovano (ma questo lo fa semplicemente NGINX), c'\u00e8 anche il nostro sistema di backup che ora legge dalla partizione principale. Non che fosse un collo di bottiglia, ma non volevamo aumentare il carico, fondamentalmente, semplicemente cos\u00ec.<\/p>\n<p>E abbiamo aggiunto un terzo disco, che \u00e8 un piccolo SSD, e l'abbiamo chiamato buffer.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/fd35481822b4170087e5f670bf338dc5.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nEcco come funziona ora.<\/p>\n<p>L'utente carica una foto sul buffer, poi viene generato un evento nella coda che dice che deve essere copiata su entrambe le partizioni. Viene copiata, e la foto vive per un certo periodo (diciamo un giorno) sul buffer, e solo dopo viene purgata. Questo migliora notevolmente l'esperienza utente, perch\u00e9 l'utente carica la foto, e solitamente riceve immediatamente richieste, oppure aggiorna la pagina. Ma tutto dipende dall'applicazione che fa l'upload.<\/p>\n<p>O, per esempio, altre persone a cui inizia a essere mostrata, inviano subito richieste per quella foto. Non \u00e8 ancora nella cache, la prima richiesta avviene molto rapidamente. Fondamentalmente, \u00e8 come con la foto-cache. Lo storage lento non partecipa affatto a questo. E quando dopo un giorno viene purgata, \u00e8 gi\u00e0 stata al 99% cacheata nel nostro layer di caching, oppure probabilmente non serve pi\u00f9 a nessuno. Quindi, l'esperienza utente \u00e8 migliorata notevolmente grazie a queste semplici manovre.<\/p>\n<p>E, soprattutto, abbiamo smesso di perdere dati.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/526f549457dd0c438f32b0adb76df76c.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nPossiamo dire che abbiamo smesso <em>potenziali<\/em> di perdere dati, perch\u00e9 in realt\u00e0 non ne perdevamo molto. Ma c'era un pericolo. Vediamo che questa soluzione \u00e8, ovviamente, buona, ma \u00e8 un po' come attenuare i sintomi del problema, invece di risolverlo completamente. E ci sono rimasti alcuni problemi.<\/p>\n<p>Innanzitutto, c'\u00e8 un punto di guasto rappresentato dal fisico host su cui funziona tutta questa macchina, che non \u00e8 scomparso.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/0eb3d292655a7edf912793ed81e8931c.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nIn secondo luogo, ci sono rimasti problemi con i SAN, il loro pesante maintenance e cos\u00ec via. Non era un fattore critico, ma volevamo provare a vivere senza di essi.<\/p>\n<p>E abbiamo creato la terza versione (in realt\u00e0 la seconda) \u2014 la versione di riserva. Come \u00e8 stata fatta?<\/p>\n<p>Ecco cosa c'era \u2013<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/8b1749b6feed200f8a64529ee2316c1a.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nLe principali problematiche sono legate al fatto che siamo su un host fisico.<\/p>\n<p>Innanzitutto, rimuoviamo i SAN, perch\u00e9 vogliamo sperimentare, vogliamo provare a usare semplicemente dischi rigidi locali.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/fd0f5a8627d9179fcbc7097c1c18505f.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nSiamo gi\u00e0 nel 2014-2015, e in quel periodo la situazione con i dischi e la loro capacit\u00e0 in un host era molto migliorata. Abbiamo deciso, perch\u00e9 non provare.<\/p>\n<p>E poi prendiamo semplicemente la nostra partizione di backup e la trasferiamo fisicamente su una macchina separata.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/456e00bc8557d3340b06efcd1dde8a08.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nIn questo modo otteniamo questo schema. Abbiamo due macchine che memorizzano lo stesso dataset. Si riservano completamente l'un l'altra e sincronizzano i dati attraverso la rete tramite una coda asincrona nello stesso MySQL.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/d44cdb7b440ad4c58cc625123306a8c8.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nPerch\u00e9 questo funziona bene \u2014 perch\u00e9 abbiamo pochi record. Cio\u00e8, se la scrittura fosse comparabile alla lettura, potremmo avere qualche overhead di rete e problemi. Ci sono pochi record, molte letture \u2014 questo metodo funziona bene, quindi copiamo abbastanza raramente foto tra questi due server.<\/p>\n<p>In quale modo funziona, se lo guardiamo un po' pi\u00f9 in dettaglio.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/071c11abb6ee1d7734c53052139ff04b.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nUpload. Il bilanciatore sceglie semplicemente host casuali dalla coppia e fa l\u2019upload su di essi. Naturalmente esegue controlli di salute, assicurandosi che la macchina non sia down. Cio\u00e8, fa upload solo su server attivi, e poi attraverso una coda asincrona tutto viene copiato sul suo vicino. Con l'upload \u00e8 tutto estremamente semplice.<\/p>\n<p>Con il compito \u00e8 un po' pi\u00f9 complesso.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/f494904aec823456e18b987a8c98bf56.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nQui ci ha aiutato Lua, perch\u00e9 su NGINX vaniglia fare una logica del genere pu\u00f2 essere difficile. Iniziamo a fare una richiesta al primo server, vediamo se la foto \u00e8 l\u00ec, perch\u00e9 potenzialmente potrebbe essere stata caricata, per esempio, sul vicino, e qui non \u00e8 ancora arrivata. Se la foto \u00e8 l\u00ec, \u00e8 buono. La diamo subito al cliente e, se possibile, la cache.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/de5f77e997bb049f4cfc1709da0f1788.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nSe non c'\u00e8, facciamo semplicemente una richiesta al vicino e la otteniamo garantita da l\u00ec.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/79aa5592acd28dfbc815261d0276c2e7.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nQuindi, possiamo dire nuovamente che potrebbero esserci problemi di performance, poich\u00e9 i round trip costanti \u2014 abbiamo caricato la foto, ma qui non c'\u00e8, stiamo facendo due richieste invece di una, dovrebbe funzionare lentamente.<\/p>\n<p>Nella nostra situazione non funziona lentamente.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/52ca3902d80990f512201672cd5e6441.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nRaccogliamo molte metriche su questo sistema, e il tasso di hit di questo meccanismo \u00e8 di circa il 95%. Quindi, il ritardo di questo backup \u00e8 molto ridotto e per questo motivo, dopo che la foto \u00e8 stata caricata, la recuperiamo quasi sempre al primo tentativo, senza dover fare due viaggi.<\/p>\n<p>Cos\u00ec, cosa abbiamo ottenuto di interessante?<\/p>\n<p>In precedenza avevamo un'area di backup principale e leggevamo da essa in sequenza. Cio\u00e8, cercavamo sempre prima nel principale e poi nel backup. Questo era un solo passaggio.<\/p>\n<p>Ora utilizziamo la lettura da entrambe le macchine simultaneamente. Distribuiamo le richieste in Round Robin. In una piccola percentuale di casi facciamo due richieste. Ma ora, in generale, abbiamo il doppio della capacit\u00e0 di lettura rispetto a prima. E il carico \u00e8 nettamente diminuito sia sulle macchine di erogazione che direttamente sugli storage che avevamo a quel tempo.<\/p>\n<p>Per quanto riguarda l'affidabilit\u00e0. Fondamentalmente, \u00e8 per questo che abbiamo lottato. Con l'affidabilit\u00e0, qui tutto si \u00e8 rivelato eccellente.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/a030a477e60d6e1f3d0b4e3395013df5.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nUn'unit\u00e0 smette di funzionare.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/42900b24e340c03ea642fd49f5b410ff.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nNessun problema! L'ingegnere di sistema pu\u00f2 anche non svegliarsi di notte, pu\u00f2 aspettare fino al mattino, non ci sar\u00e0 nulla di grave.<\/p>\n<p>Anche se, in caso di guasto di questa macchina, la coda si ferma, non ci sono problemi, i log si accumuleranno prima sulla macchina attiva, e poi si ripristineranno nella coda per essere elaborati dalla macchina che torner\u00e0 operativa dopo un po'.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/ef42eadaaf3e3ecbf70847e9f88c1582.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nLo stesso vale per la manutenzione. Semplicemente spegniamo una delle macchine, la rimuoviamo manualmente da tutti i pool, smette di ricevere traffico, svolgiamo un po' di manutenzione, sistemiamo delle cose e dopo che la rimettiamo in servizio, questo backup si recupera piuttosto rapidamente. Cio\u00e8, in un giorno di inattivit\u00e0 di una macchina, si recupera entro pochi minuti. Questo \u00e8 davvero poco. Con l'affidabilit\u00e0, ripeto, qui tutto \u00e8 fantastico.<\/p>\n<p>Quali conclusioni possiamo trarre da questo schema di riserva?<\/p>\n<p>Abbiamo ottenuto affidabilit\u00e0.<\/p>\n<p>Semplice gestione. Poich\u00e9 le macchine hanno dischi rigidi locali, \u00e8 molto pi\u00f9 comodo per gli ingegneri che ci lavorano.<\/p>\n<p>Abbiamo ottenuto una doppia capacit\u00e0 di lettura.<\/p>\n<p>Questo \u00e8 un ottimo bonus in aggiunta all'affidabilit\u00e0.<\/p>\n<p>Ma ci sono anche problemi. Ora abbiamo uno sviluppo molto pi\u00f9 complesso di alcune funzionalit\u00e0 a causa del fatto che il sistema \u00e8 diventato 100% eventualmente coerente.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/b650276a41730cc303180e8304c5dabb.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nDobbiamo, diciamo, in qualche lavoro in background, pensare costantemente: \u00abSu quale server siamo attualmente in esecuzione?\u00bb, \u00ab\u00c8 sicuro che qui ci sia la foto aggiornata?\u00bb e cos\u00ec via. Questo, naturalmente, \u00e8 tutto incapsulato in wrapper, quindi per il programmatore che scrive la logica di business \u00e8 trasparente. Tuttavia, \u00e8 apparso uno strato complesso. Ma siamo disposti ad accettarlo in cambio dei vantaggi che ne abbiamo ottenuto.<\/p>\n<p>E qui si presenta nuovamente un certo conflitto.<\/p>\n<p>All'inizio ho detto che conservare tutto su dischi rigidi locali \u00e8 sbagliato. E ora dico che ci \u00e8 piaciuto.<\/p>\n<p>S\u00ec, effettivamente, col passare del tempo la situazione \u00e8 cambiata notevolmente, e ora questo approccio ha molti vantaggi. In primo luogo, otteniamo una gestione molto pi\u00f9 semplice.<\/p>\n<p>In secondo luogo, \u00e8 pi\u00f9 performante, poich\u00e9 non abbiamo quei controllori automatici, le connessioni ai rack di dischi.<\/p>\n<p>L\u00ec c'\u00e8 una grande macchina, qui ci sono solo alcuni dischi che sono stati configurati in RAID direttamente sulla macchina.<\/p>\n<p>Ma ci sono anche svantaggi.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/3c090e0801f1a686dc0d5fefce697c56.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nQuesto costa circa 1,5 volte di pi\u00f9 rispetto all'uso dei SAN, anche ai prezzi attuali. Pertanto, abbiamo deciso di non convertire completamente il nostro grande cluster in macchine con dischi rigidi locali e di mantenere una soluzione ibrida.<\/p>\n<p>Una parte delle macchine lavora con dischi rigidi (non la met\u00e0, circa il 30%, probabilmente). E la parte rimanente sono vecchie macchine su cui c'era il primo schema di riserva. Le abbiamo semplicemente rimontate, poich\u00e9 non abbiamo bisogno n\u00e9 di nuovi dati n\u00e9 di altro, abbiamo semplicemente spostato i mount da un host fisico a due.<\/p>\n<p>E abbiamo ottenuto una grande capacit\u00e0 di lettura, e ci siamo espansi. Prima montavamo uno storage su una macchina, ora montiamo quattro storage su una coppia, ad esempio. E questo funziona normalmente.<\/p>\n<p>Facciamo un breve riassunto di cosa abbiamo ottenuto, per cosa abbiamo lottato, e se ci siamo riusciti.<\/p>\n<h3>Risultati<\/h3>\n<p>\nAbbiamo utenti \u2014 ben 33 milioni.<\/p>\n<p>Abbiamo tre punti di presenza \u2014 Praga, Miami, Hong Kong.<\/p>\n<p>In essi si trova uno strato di caching, che consiste in server con dischi locali veloci (SSD), su cui opera una semplice configurazione di NGINX, il suo access.log e demoni scritti in Python che gestiscono tutto ci\u00f2 e controllano la cache.<\/p>\n<p>Se lo desiderate nel vostro progetto, se per voi le immagini non sono cos\u00ec critiche come per noi, o se il trade-off tra controllo e velocit\u00e0 di sviluppo e costi delle risorse pende dalla vostra parte, allora potete tranquillamente sostituirlo con un CDN, che oggi giorno funziona bene.<\/p>\n<p>Successivamente, c'\u00e8 uno strato di archiviazione, dove abbiamo cluster di coppie di server che si riservano l'un l'altro, copiando file in modo asincrono da uno all'altro ad ogni modifica.<\/p>\n<p>Alcuni di questi server lavorano con dischi rigidi locali.<\/p>\n<p>Alcuni di questi server sono collegati a SAN.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/5ddbc4f73d86aa1f83734885d8c9dea0.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nDa un lato, questo \u00e8 pi\u00f9 comodo per la gestione e leggermente pi\u00f9 performante, dall'altro lato, \u00e8 vantaggioso anche in termini di densit\u00e0 di collocazione e costo per gigabyte.<\/p>\n<p>Ecco una breve panoramica dell'architettura di ci\u00f2 che abbiamo realizzato e come si \u00e8 sviluppato.<\/p>\n<p>Alcuni consigli semplici da parte del capoprogetto.<\/p>\n<p>In primo luogo, se mai decidete che sia urgente migliorare la vostra infrastruttura fotografica, misurate innanzitutto, perch\u00e9 forse non \u00e8 necessario alcun miglioramento.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/7770f41d0b190eb78ae0d19f4c8182a6.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nAd esempio, abbiamo un cluster di server che distribuiscono fotografie dagli allegati nelle chat, e l\u00ec funziona ancora un sistema del 2009, e nessuno ha problemi. Tutti sono soddisfatti.<\/p>\n<p>Per misurare, cominciate a collegare una serie di metriche, guardatele e poi decidete cosa vi dispiace e cosa deve essere migliorato. Per misurare, abbiamo uno strumento fantastico chiamato Pinba.<\/p>\n<p>Questo strumento raccoglie statistiche da NGINX in modo molto dettagliato per ogni richiesta e codice di risposta, e distribuzione dei tempi \u2014 qualsiasi cosa. Ha binding per vari sistemi di analisi, e potete poi visualizzarlo in modo elegante.<\/p>\n<p>Misurate prima \u2014 poi migliorate.<\/p>\n<p>Inoltre, ottimizziamo la lettura con la cache, la scrittura con il sharding, ma questo \u00e8 un punto ovvio.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/f53a4777f1a2c7793eba4a72c94263a4.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nSe state appena iniziando a costruire il vostro sistema, \u00e8 molto meglio trattare le fotografie come file immutabili. Poich\u00e9 in questo modo eliminate subito tutta una serie di problemi legati all'invalidazione della cache, a come la logica deve trovare la versione corretta della fotografia, e cos\u00ec via.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/f345c59681275326cda1320b4f188ce9.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nSupponiamo di aver caricato una foto, poi di averla ruotata, fate in modo che sia un file fisicamente diverso. Cio\u00e8, non pensate: adesso risparmier\u00f2 un po' di spazio, scrivo nello stesso file, cambio versione. Questo non funziona mai bene, e poi ci sono molti mal di testa.<\/p>\n<p>Il punto seguente riguarda il resize al volo.<\/p>\n<p>In passato, quando gli utenti caricavano una foto, creavamo immediatamente una serie di dimensioni per ogni evenienza, per diversi clienti, e tutti si trovavano sul disco. Ora ci siamo rinunciati.<\/p>\n<p>Abbiamo mantenuto solo tre dimensioni principali: piccola, media e grande. Tutto il resto lo ridimensioniamo dal formato che ci viene richiesto in Uport, semplicemente adattandolo e restituendolo all'utente.<\/p>\n<p>Il costo del CPU nello strato di caching risulta molto inferiore a se dovessimo continuamente rigenerare queste dimensioni su ogni storage. Supponiamo di voler aggiungere un nuovo formato, ci vorrebbe un mese per eseguire uno script ovunque che faccia tutto questo in modo preciso, senza bloccare il cluster. Cio\u00e8, se c'\u00e8 la possibilit\u00e0 di scegliere, \u00e8 meglio fare il minor numero possibile di formati fisici, ma con una certa variet\u00e0, diciamo tre. E tutto il resto da ridimensionare al volo con moduli pronti. Questo \u00e8 ora molto facile e accessibile.<\/p>\n<p>E il backup incrementale asincrono \u00e8 eccellente.<\/p>\n<p>Come ha dimostrato la nostra esperienza, questo schema funziona bene con la copia ritardata dei file modificati.<\/p>\n<p><img decoding=\"async\" alt=\"Architettura di memorizzazione e distribuzione delle foto in Badoo\" src=\"\/wp-content\/uploads\/2020\/01\/0e550721e838654e61e1fa4d08f9bb93.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nL'ultimo punto \u00e8 anche ovvio. Se nella vostra infrastruttura non ci sono attualmente problemi del genere, ma c'\u00e8 qualcosa che potrebbe rompersi, sicuramente si romper\u00e0 quando ci sar\u00e0 un po' di carico in pi\u00f9. Quindi \u00e8 meglio pensarci in anticipo e non trovarsi a dover affrontare problemi.<\/p>\n<h3>Contatti<\/h3>\n<p>\n\u00bb <noindex><a rel=\"nofollow\" href=\"https:\/\/habrahabr.ru\/users\/bo0rsh201\/\" class=\"user_link\">bo0rsh201<\/a><\/noindex> <br \/>\n\u00bb <noindex><a rel=\"nofollow\" href=\"https:\/\/habrahabr.ru\/company\/badoo\/\">Blog della compagnia Badoo<\/a><\/noindex><\/p>\n<blockquote><p>Questa presentazione \u00e8 la trascrizione di uno dei migliori interventi alla conferenza per sviluppatori di sistemi ad alta scalabilit\u00e0. <noindex><a rel=\"nofollow\" href=\"http:\/\/highload.ru\/?utm_source=habr&amp;utm_medium=media&amp;utm_campaign=past.articles&amp;utm_content=common\">HighLoad++<\/a><\/noindex>Manca meno di un mese alla conferenza HighLoad++ 2017.<\/p>\n<p>Abbiamo gi\u00e0 pronta <noindex><a rel=\"nofollow\" href=\"http:\/\/www.highload.ru\/2017\/abstracts\">Programma della conferenza<\/a><\/noindex>, ora stiamo attivamente formando il programma.<\/p>\n<p>Quest'anno continuiamo a esplorare il tema delle architetture e della scalabilit\u00e0:<\/p>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"http:\/\/www.highload.ru\/2017\/abstracts\/2946.html?utm_source=habr&amp;utm_medium=media&amp;utm_campaign=past.articles&amp;utm_content=common\">Come servire un miliardo di utenti e fornire terabyte di traffico.<\/a><\/noindex> \/ \u0418\u0433\u043e\u0440\u044c \u0412\u0430\u0441\u0438\u043b\u044c\u0435\u0432<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"http:\/\/www.highload.ru\/2017\/abstracts\/3088.html?utm_source=habr&amp;utm_medium=media&amp;utm_campaign=past.articles&amp;utm_content=common\">Come riscrivere da zero il database dei messaggi privati di VKontakte e migrare su di esso senza downtime.<\/a><\/noindex> \/ \u0414\u043c\u0438\u0442\u0440\u0438\u0439 \u0415\u0433\u043e\u0440\u043e\u0432<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"http:\/\/www.highload.ru\/2017\/abstracts\/2843.html?utm_source=habr&amp;utm_medium=media&amp;utm_campaign=past.articles&amp;utm_content=common\">Morti da svendita: come Yandex.Money ha cercato di accelerare verso il Black Friday e resistere<\/a><\/noindex> \/ \u0410\u043d\u0430\u0442\u043e\u043b\u0438\u0439 \u041f\u043b\u0430\u0441\u043a\u043e\u0432\u0441\u043a\u0438\u0439<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"http:\/\/www.highload.ru\/2017\/abstracts\/3003.html?utm_source=habr&amp;utm_medium=media&amp;utm_campaign=past.articles&amp;utm_content=common\">Architettura resistente agli errori del sistema frontale della banca<\/a><\/noindex> \/ \u0420\u043e\u043c\u0430\u043d \u0428\u0435\u0445\u043e\u0432\u0446\u043e\u0432, \u0410\u043b\u0435\u043a\u0441\u0435\u0439 \u0413\u0440\u043e\u043c\u0430\u0442\u0447\u0438\u043a\u043e\u0432<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"http:\/\/www.highload.ru\/2017\/abstracts\/2948.html?utm_source=habr&amp;utm_medium=media&amp;utm_campaign=past.articles&amp;utm_content=common\">Architettura del sistema di pagamento: quasi enterprise<\/a><\/noindex> \/ \u0424\u0438\u043b\u0438\u043f\u043f \u0414\u0435\u043b\u044c\u0433\u044f\u0434\u043e<\/li>\n<\/ul>\n<p>\nAlcuni di questi materiali sono usati anche nel nostro corso online di formazione per lo sviluppo di sistemi ad alto carico <noindex><a rel=\"nofollow\" href=\"http:\/\/highload.guide\/?utm_source=habr&amp;utm_medium=media&amp;utm_campaign=past.articles&amp;utm_content=common\">HighLoad.Guide<\/a><\/noindex> \u00e8 una serie di email, articoli, materiali e video selezionati appositamente. Attualmente il nostro manuale contiene oltre 30 materiali unici. Unisciti a noi!\n<\/p><\/blockquote>\n<p>Fonte: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/oleg-bunin\/blog\/340976\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0410\u0440\u0442\u0435\u043c \u0414\u0435\u043d\u0438\u0441\u043e\u0432 ( bo0rsh201, Badoo) Badoo \u2014 \u044d\u0442\u043e \u043a\u0440\u0443\u043f\u043d\u0435\u0439\u0448\u0438\u0439 \u0432 \u043c\u0438\u0440\u0435 \u0441\u0430\u0439\u0442 \u0437\u043d\u0430\u043a\u043e\u043c\u0441\u0442\u0432. \u041d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0443 \u043d\u0430\u0441 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u043f\u043e\u0440\u044f\u0434\u043a\u0430 330 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u043e\u0432 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u043f\u043e \u0432\u0441\u0435\u043c\u0443 \u043c\u0438\u0440\u0443. \u041d\u043e, \u0447\u0442\u043e \u0433\u043e\u0440\u0430\u0437\u0434\u043e \u0431\u043e\u043b\u0435\u0435 \u0432\u0430\u0436\u043d\u043e \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 \u043d\u0430\u0448\u0435\u0433\u043e \u0441\u0435\u0433\u043e\u0434\u043d\u044f\u0448\u043d\u0435\u0433\u043e \u0440\u0430\u0437\u0433\u043e\u0432\u043e\u0440\u0430, \u2014 \u044d\u0442\u043e \u0442\u043e, \u0447\u0442\u043e \u043c\u044b \u0445\u0440\u0430\u043d\u0438\u043c \u043e\u043a\u043e\u043b\u043e 3 \u043f\u0435\u0442\u0430\u0431\u0430\u0439\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0445 \u0444\u043e\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u0439. \u041a\u0430\u0436\u0434\u044b\u0439 \u0434\u0435\u043d\u044c \u043d\u0430\u0448\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u0437\u0430\u043b\u0438\u0432\u0430\u044e\u0442 \u043f\u043e\u0440\u044f\u0434\u043a\u0430 3,5 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u043e\u0432 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-55009","post","type-post","status-publish","format-standard","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.0.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u0410\u0440\u0442\u0435\u043c \u0414\u0435\u043d\u0438\u0441\u043e\u0432 (\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/arhitektura-hraneniya-i-otdachi-fotografij-v-badoo\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.0.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"it_IT\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0438 \u043e\u0442\u0434\u0430\u0447\u0438 \u0444\u043e\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u0439 \u0432 Badoo | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u0410\u0440\u0442\u0435\u043c \u0414\u0435\u043d\u0438\u0441\u043e\u0432 (\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/arhitektura-hraneniya-i-otdachi-fotografij-v-badoo\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2020-01-09T21:00:00+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-02-18T11:03:04+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Architettura di archiviazione e distribuzione delle foto in Badoo | ProHoster","description":"Artem Denisov (","canonical_url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/arhitektura-hraneniya-i-otdachi-fotografij-v-badoo","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"it_IT","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0438 \u043e\u0442\u0434\u0430\u0447\u0438 \u0444\u043e\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u0439 \u0432 Badoo | ProHoster","og:description":"\u0410\u0440\u0442\u0435\u043c \u0414\u0435\u043d\u0438\u0441\u043e\u0432 (","og:url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/arhitektura-hraneniya-i-otdachi-fotografij-v-badoo","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2020-01-09T21:00:00+00:00","article:modified_time":"2020-02-18T11:03:04+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"55009","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-24 13:30:15","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 19:53:49","updated":"2026-01-24 13:30:15","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/55009","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/comments?post=55009"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/55009\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media?parent=55009"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/categories?post=55009"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/tags?post=55009"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}