{"id":91090,"date":"2020-08-08T13:42:11","date_gmt":"2020-08-08T11:42:11","guid":{"rendered":"https:\/\/prohoster.info\/blog\/administrirovanie\/arhitektura-s3-3-goda-evolyuczii-mail-ru-cloud-storage"},"modified":"2020-08-08T13:42:11","modified_gmt":"2020-08-08T11:42:11","slug":"arhitektura-s3-3-goda-evolyuczii-mail-ru-cloud-storage","status":"publish","type":"post","link":"https:\/\/prohoster.info\/pt\/blog\/administrirovanie\/arhitektura-s3-3-goda-evolyuczii-mail-ru-cloud-storage","title":{"rendered":"Arquitetura S3: 3 anos de evolu\u00e7\u00e3o do Mail.ru Cloud Storage","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Arquitetura S3: 3 anos de evolu\u00e7\u00e3o do Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/a53775776b3fc969cc15c9d13a64039d.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<em><noindex><a rel=\"nofollow\" href=\"https:\/\/www.deviantart.com\/st-pete\/art\/Storage-Corridor-408874509\">Corredor de Armazenamento<\/a><\/noindex> por St-Pete<\/em><\/p>\n<p><\/p>\n<p>Ol\u00e1 a todos! Sou Mons Anderson, arquiteto de plataforma <noindex><a rel=\"nofollow\" href=\"https:\/\/mcs.mail.ru\/\">Solu\u00e7\u00f5es em Nuvem Mail.ru<\/a><\/noindex>, vou contar como constru\u00edmos nosso armazenamento S3, como ele funciona, quais solu\u00e7\u00f5es se mostraram eficazes e quais mudar\u00edamos se tiv\u00e9ssemos que iniciar esse projeto do zero hoje.<\/p>\n<p><\/p>\n<p>Este artigo foi preparado com base em uma apresenta\u00e7\u00e3o na <noindex><a rel=\"nofollow\" href=\"https:\/\/corp.mail.ru\/ru\/press\/events\/databases-2\/\">@Databases Meetup<\/a><\/noindex> por Mail.ru Cloud Solutions &amp; Tarantool. Neste artigo, vamos falar sobre:<\/p>\n<p><\/p>\n<ul>\n<li>como o armazenamento Mail.ru foi estruturado, em cima do qual constru\u00edmos o armazenamento S3;<\/li>\n<li>o que adicionamos para criar o Mail.ru Cloud Storage;<\/li>\n<li>como funciona o modelo de armazenamento de objetos e quais passos foram dados para a produ\u00e7\u00e3o;<\/li>\n<li>sobre as melhorias do sistema de produ\u00e7\u00e3o: failover e escalabilidade;<\/li>\n<li>como implementamos sharding e resharding;<\/li>\n<li>e tamb\u00e9m sobre o trabalho com certificados SSL.<\/li>\n<\/ul>\n<p><\/p>\n<p>Se voc\u00ea n\u00e3o quiser ler, pode <noindex><a rel=\"nofollow\" href=\"https:\/\/youtu.be\/NEgm1nsv-qg\">ver como<\/a><\/noindex>.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2 id=\"kak-bylo-ustroeno-hranilische-mailru-poverh-kotorogo-my-stroili-s3-hranilische\">Como o armazenamento Mail.ru foi estruturado, em cima do qual constru\u00edmos o armazenamento S3<\/h2>\n<p><\/p>\n<p>O desenvolvimento do nosso S3 come\u00e7ou em cima do armazenamento da Nuvem Mail.ru, ent\u00e3o \u00e9 importante explicar como ele \u00e9 estruturado e o que consegue fazer.<\/p>\n<p><\/p>\n<p>O armazenamento da nuvem Mail.ru consiste em servidores com discos. Em m\u00e9dia, um servidor de storage moderno possui 36 discos de 12 a 14 terabytes. Antes, os discos eram menores, mas em tr\u00eas anos, as capacidades dos discos aumentaram e hoje isso representa quase meio petabyte de dados brutos. <\/p>\n<p><\/p>\n<p>Os discos de diferentes servidores de armazenamento s\u00e3o agrupados em chamadas \"duplas\" (pair). Uma dupla \u00e9 uma unidade \u00fanica de armazenamento de arquivos. Essencialmente, \u00e9 um disco montado em uma determinada parti\u00e7\u00e3o em um caminho espec\u00edfico, onde podem residir arquivos identificados por hashes. <\/p>\n<p><\/p>\n<p>Uma dupla \u00e9 uma denomina\u00e7\u00e3o hist\u00f3rica que se manteve at\u00e9 hoje, embora atualmente em uma dupla n\u00e3o sejam necessariamente apenas dois discos. Podem haver tr\u00eas discos, bem como v\u00e1rias armazenagens h\u00edbridas, como 3\/2. <\/p>\n<p>\n<img decoding=\"async\" alt=\"Arquitetura S3: 3 anos de evolu\u00e7\u00e3o do Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/544ab79846539262e2d4dff6ab95ffff.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><em>Duplas (pair) \u2014 unidades de armazenamento de objetos<\/em><\/p>\n<p><\/p>\n<p>Todas as duplas s\u00e3o armazenadas no PairDB \u2014 um aplicativo baseado em Tarantool. Todos os bancos em nosso armazenamento, desde os primeiros, s\u00e3o Tarantool; n\u00e3o utilizamos outros bancos.<\/p>\n<p><\/p>\n<p>PairDB armazena todas as duplas, seus estados, espa\u00e7o livre, capacidades de falha, \u00faltimos erros. Al\u00e9m disso, pode verificar as duplas, atualizar seu estado, checar se est\u00e3o funcionando ou n\u00e3o. Ou seja, o PairDB fornece uma vis\u00e3o geral do estado de todos os discos do nosso sistema.<\/p>\n<p>\n<img decoding=\"async\" alt=\"Arquitetura S3: 3 anos de evolu\u00e7\u00e3o do Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/d50781b8b51ed5fe126bc84e19c934d1.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><em>Pair DB: banco de dados com o estado das duplas<\/em><\/p>\n<p><\/p>\n<p>Os pares armazenam arquivos e, para saber em qual par est\u00e1 cada arquivo, precisamos de mais um banco de dados \u2014 FileDB. Ele armazena o mapeamento, a defini\u00e7\u00e3o de correspond\u00eancia: esse arquivo est\u00e1 armazenado nesse par, al\u00e9m de um pequeno n\u00famero de atributos necess\u00e1rios.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Arquitetura S3: 3 anos de evolu\u00e7\u00e3o do Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/b1a64737cf7f916bff446c10c1f01d4c.jpeg\" style=\"display:block;margin: 0 auto;\" \/><em>File DB: o lugar onde o arquivo \u00e9 armazenado<\/em><\/p>\n<p>Outro elo importante \u00e9 o servi\u00e7o Nylon, um roteador para trabalhar com bancos de dados. Ele \u00e9 o \u00fanico ponto de entrada e permite trabalhar atrav\u00e9s de uma interface \u00fanica tanto com PairDB quanto com FileDB. \u00c9 um servi\u00e7o sem estado, realiza o balanceamento de requisi\u00e7\u00f5es, entende a qual shard do FileDB deve dirigir-se, sabe quais pares est\u00e3o ativos e quais n\u00e3o est\u00e3o.<\/p>\n<p>\n<img decoding=\"async\" alt=\"Arquitetura S3: 3 anos de evolu\u00e7\u00e3o do Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/3e2225f229c8cfa462d620d2b5fb581e.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><em>Nylon: roteador para trabalhar com bancos de dados<\/em><\/p>\n<p><\/p>\n<p>Al\u00e9m disso, \u00e9 necess\u00e1rio de alguma forma inserir conte\u00fado no armazenamento. Para isso, existe um servi\u00e7o \u2014 Streamer. Ele fornece dois m\u00e9todos HTTP: m\u00e9todo PUT, para enviar conte\u00fado ao armazenamento, e m\u00e9todo GET, para recuper\u00e1-lo. O HTTP \u00e9 um protocolo bastante popular e conveniente para a transfer\u00eancia de dados. <\/p>\n<p><\/p>\n<p>Quando nos dirigimos ao Streamer, ele se conecta ao PairDB atrav\u00e9s do Nylon, verifica em qual par \u00e9 poss\u00edvel carregar o arquivo e, em seguida, transmite os dados via WebDAV para esse par. <\/p>\n<p><\/p>\n<p>Na ess\u00eancia, qualquer servidor de armazenamento \u00e9 composto por nginx mais discos montados em caminhos espec\u00edficos. Podemos usar o Streamer para enviar um arquivo para o armazenamento, delet\u00e1-lo, renome\u00e1-lo ou verificar sua integridade. Ou seja, \u00e9 uma interface conveniente para intera\u00e7\u00e3o de baixo n\u00edvel com o armazenamento. <\/p>\n<p>\n<img decoding=\"async\" alt=\"Arquitetura S3: 3 anos de evolu\u00e7\u00e3o do Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/3722a89ed44cace36e9cb1f8bee4bd1e.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><em>Streamer: ponto de entrada no armazenamento<\/em><\/p>\n<p><\/p>\n<h2 id=\"chto-my-dobavili-chtoby-sdelat-s3-hranilische\">O que adicionamos para criar o armazenamento S3<\/h2>\n<p><\/p>\n<p>Assim, examinamos a estrutura b\u00e1sica do armazenamento no momento em que decidimos lan\u00e7ar o armazenamento S3. Usando o m\u00e9todo PUT, pod\u00edamos inserir qualquer conte\u00fado e receber como identificador desses dados um hash. Com esse identificador, poder\u00edamos posteriormente voltar e recuperar o arquivo original. Mas isso n\u00e3o \u00e9 suficiente para implementar o S3. No protocolo S3, al\u00e9m do pr\u00f3prio armazenamento de objetos, existem:<\/p>\n<p><\/p>\n<ul>\n<li>armazenamento de metadados \u2014 propriedades adicionais dos objetos;<\/li>\n<li>organiza\u00e7\u00e3o de acesso aos objetos via HTTP;<\/li>\n<li>agrupamento de objetos em cole\u00e7\u00f5es \u2014 buckets;<\/li>\n<li>Endpoint HTTP-S3. O S3 organiza os dados em estruturas espec\u00edficas \u2014 buckets, cada um dos quais fornece um ponto de entrada para o armazenamento de arquivos.<\/li>\n<\/ul>\n<p><\/p>\n<p>Para implementar essa l\u00f3gica, foi necess\u00e1rio um servi\u00e7o separado. Tamb\u00e9m quer\u00edamos antecipar a arquitetura para o crescimento futuro do servi\u00e7o com escalabilidade linear.<\/p>\n<p><\/p>\n<h2 id=\"pervye-komponenty\">Os primeiros componentes<\/h2>\n<p><\/p>\n<p>Um daemon que implementa a API S3. Esta \u00e9 a padr\u00e3o API S3 da Amazon, que suporta opera\u00e7\u00f5es em XML para metadados e permite a transfer\u00eancia direta de conte\u00fado. N\u00e3o precis\u00e1vamos reinventar a roda, tudo j\u00e1 est\u00e1 descrito e documentado.<\/p>\n<p><\/p>\n<p>Tamb\u00e9m colocamos o Nginx diante do servi\u00e7o. Usamos para termina\u00e7\u00e3o SSL, balanceamento de carga, al\u00e9m de alguma l\u00f3gica em Lua (m\u00e9tricas, logging e tracing).<\/p>\n<p><\/p>\n<p>Para armazenar metadados S3, tamb\u00e9m escolhemos o Tarantool. Na primeira vers\u00e3o, o daemon S3 acessava essa base para metadados enquanto o conte\u00fado era armazenado em um grande reposit\u00f3rio atrav\u00e9s do Streamer.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Arquitetura S3: 3 anos de evolu\u00e7\u00e3o do Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/03dddec282b5bb41eb63748ccfb6c9a4.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<em>Nginx + API S3 + metadados<\/em><\/p>\n<p><\/p>\n<h2 id=\"obektnaya-model-hraneniya\">Modelo de objeto de armazenamento<\/h2>\n<p><\/p>\n<p>Vamos ver como funciona o S3. O usu\u00e1rio pode criar um bucket \u2014 uma cole\u00e7\u00e3o de objetos. O bucket \u00e9 acessado pelo nome do host e \u00e9 um subdom\u00ednio do servi\u00e7o. Dentro do bucket, o usu\u00e1rio pode criar objetos. O identificador do objeto ser\u00e1 a URL. O conte\u00fado do objeto \u00e9 um blob, um array de dados bin\u00e1rios que vamos armazenar no reposit\u00f3rio. O objeto tamb\u00e9m possui atributos: nome \u2014 a pr\u00f3pria URL, ACL (lista de controle de acesso), outros atributos adicionais ou arbitr\u00e1rios \u2014 tudo isso \u00e9 armazenado nos metadados. <\/p>\n<p><\/p>\n<p>O esquema normalizado desses dados pode parecer assim: existem projetos que possuem buckets, que possuem objetos, e os objetos podem ser compostos. Como uma forma de upload, os objetos podem ser carregados em partes, e h\u00e1 duas tabelas auxiliares para o upload: uploads e chunks. Al\u00e9m disso, os projetos t\u00eam credenciais de acesso e faturamento. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Arquitetura S3: 3 anos de evolu\u00e7\u00e3o do Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/e2bede45ba4044f658b47a9840fd5224.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<em>Esquema de dados<\/em><\/p>\n<p><\/p>\n<p>Como est\u00e1vamos criando um servi\u00e7o B2B com acesso pago, esse esquema precisava de faturamento.<br \/>\nO servi\u00e7o de faturamento tamb\u00e9m foi implementado no Tarantool. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Arquitetura S3: 3 anos de evolu\u00e7\u00e3o do Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/d5b1a63e2273e933c95deecdb054bfe6.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<h2 id=\"dorabotki-s3-hranilischa-shagi-k-prodakshenu\">Desenvolvimentos do armazenamento S3: etapas para produ\u00e7\u00e3o<\/h2>\n<p><\/p>\n<p>J\u00e1 temos um modelo funcional que pode ser usado: os objetos e metadados estavam armazenados, mas para a produ\u00e7\u00e3o faltavam alguns detalhes.<\/p>\n<p><\/p>\n<p>Em primeiro lugar, temos o sistema de rate limiting. Se lan\u00e7armos o servi\u00e7o sem ele, poder\u00edamos sobrecarregar de forma imprevis\u00edvel alguma parte do sistema durante picos de carga. O rate limit deve funcionar da seguinte forma: qualquer requisi\u00e7\u00e3o S3 chega a um host espec\u00edfico, esse host \u00e9 o identificador do bucket, e o bucket pertence a um determinado cliente. Precisamos definir uma fun\u00e7\u00e3o para o bucket que permita calcular o rate limit. <\/p>\n<p><\/p>\n<p>Al\u00e9m disso, o sistema de rate limiting deve ser suficientemente eficiente para suportar a carga que chega ao S3.<\/p>\n<p><\/p>\n<p>Aqui, novamente usamos o Tarantool. Os rate limits s\u00e3o um cluster de 21 inst\u00e2ncias, com as inst\u00e2ncias divididas em grupos, distribu\u00eddas em tr\u00eas n\u00f3s f\u00edsicos e unidas em um grande cluster topol\u00f3gico. As altera\u00e7\u00f5es de configura\u00e7\u00e3o s\u00e3o automaticamente aplicadas por meio dele: rate limits, padr\u00f5es e configura\u00e7\u00f5es s\u00e3o definidos. Cada bucket \u00e9 atendido estritamente por uma \u00fanica inst\u00e2ncia. Quando uma requisi\u00e7\u00e3o para um bucket espec\u00edfico chega, calculamos a inst\u00e2ncia respons\u00e1vel por esse bucket. Dentro desse n\u00f3, \u00e9 feito o c\u00e1lculo da taxa atual de acessos por meio de um algoritmo semelhante ao Token Bucket. Em seguida, o sistema de rate limiting, com base nos indicadores atuais de carga e nas propriedades definidas para o bucket espec\u00edfico, determina se a requisi\u00e7\u00e3o pode ser atendida ou n\u00e3o. A verifica\u00e7\u00e3o dos limites \u00e9 realizada na fase inicial da execu\u00e7\u00e3o da requisi\u00e7\u00e3o S3, protegendo todos os outros elementos do sistema contra sobrecarga. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Arquitetura S3: 3 anos de evolu\u00e7\u00e3o do Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/1b91e5d1fe067c859ba9b36d58827579.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Al\u00e9m disso, sob carga, \u00e9 bastante dif\u00edcil operar sem um cache. No S3, espera-se um acesso repetido aos mesmos objetos, ou seja, \u00e9 um armazenamento quente. Em condi\u00e7\u00f5es normais, o acesso a um \u00fanico arquivo \u00e9 gerenciado por toda a cadeia: Streamer, FileDB, PairDB, Storage. Mas ao acessarmos um arquivo repetidamente, otimizamos o acesso a esse conte\u00fado utilizando um cache local.<\/p>\n<p><\/p>\n<p>O cache \u00e9 em camadas e implementado com o nginx, unidades locais, SSD e discos de RAM. Aqui n\u00e3o usamos o Tarantool, pois \u00e9 mais conveniente servir objetos a partir do sistema de arquivos, permitindo a realiza\u00e7\u00e3o de tiering do cache. Al\u00e9m disso, temos objetos grandes com um tamanho m\u00e1ximo de 32 gigabytes, e no Tarantool apenas objetos pequenos podem ser armazenados em cache.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Arquitetura S3: 3 anos de evolu\u00e7\u00e3o do Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/faa02bd52a1d70642589d775f22c5e75.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Este foi o primeiro sistema com o qual iniciamos, que tinha uma capacidade calculada, suficiente para pesquisa e compreens\u00e3o do produto, para garantir que ele funcionaria. <\/p>\n<p><\/p>\n<h2 id=\"dorabotki-boevoy-sistemy-feylover-i-masshtabirovanie\">Aprimoramentos do sistema em produ\u00e7\u00e3o: failover e escalabilidade<\/h2>\n<p><\/p>\n<p>O sistema j\u00e1 estava em opera\u00e7\u00e3o, e no in\u00edcio n\u00f3s negligenciamos alguns aspectos - era necess\u00e1rio adicionar failover e escalabilidade. <\/p>\n<p><\/p>\n<p>Nosso daemon S3 buscava metadados pelo protocolo Tarantool. Substitu\u00edmos o banco de dados original pelo Tarantool, que atuava como um roteador proxy para as solicita\u00e7\u00f5es de metadados. Do ponto de vista do aplicativo que implementa a API, nada mudou - ele continuou a acessar o banco de dados pelo protocolo Tarantool, mas o roteador p\u00f4de fornecer um failover ativo. Isso nos permitiu verificar a disponibilidade do n\u00f3, gerenciar interrup\u00e7\u00f5es durante as transi\u00e7\u00f5es e falhas, e assim por diante. O aplicativo em si, no entanto, n\u00e3o foi modificado. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Arquitetura S3: 3 anos de evolu\u00e7\u00e3o do Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/978ff8a458f8d48b98672121cf6eca5d.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<h2 id=\"podrobnee-o-tom-kak-my-realizovali-shardirovanie\">Saiba mais sobre como implementamos a fragmenta\u00e7\u00e3o<\/h2>\n<p><\/p>\n<p>A pr\u00f3xima quest\u00e3o que tivemos que considerar foi a fragmenta\u00e7\u00e3o. O sistema cresceu, o n\u00famero de objetos aumentou e era preciso garantir possibilidades para o crescimento futuro.<\/p>\n<p><\/p>\n<p>Voltando ao esquema de dados: temos projetos, buckets, credenciais e faturamento. Estes s\u00e3o objetos que, com alta probabilidade, n\u00e3o ultrapassar\u00e3o os limites de uma \u00fanica inst\u00e2ncia, nem em volume, nem em requisi\u00e7\u00f5es, no futuro pr\u00f3ximo. Portanto, n\u00e3o faz sentido fragment\u00e1-los, e os movemos para uma inst\u00e2ncia separada, que permanecer\u00e1 n\u00e3o fragmentada. Isso permite uma gest\u00e3o mais consistente dos projetos e buckets, j\u00e1 que temos um \u00fanico ponto n\u00e3o fragmentado. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Arquitetura S3: 3 anos de evolu\u00e7\u00e3o do Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/c5a1c1a875e756e3dceb5f885fbda2c8.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Al\u00e9m disso, no esquema existem objetos que crescem linearmente - inicialmente eram centenas de milhares, agora seu n\u00famero chega a bilh\u00f5es. Esses objetos e suas partes precisavam ser movidos para um cluster fragmentado. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Arquitetura S3: 3 anos de evolu\u00e7\u00e3o do Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/00bb418cc61ad2e3e8797caf5d1ab202.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Dividimos o esquema, mas os objetos precisam trabalhar com os buckets: cada objeto sempre pertence a um bucket espec\u00edfico, e o ACL opera nesse bucket. Portanto, para cada shard com objetos, mantemos uma c\u00f3pia sombra de cada bucket. Al\u00e9m disso, durante a modifica\u00e7\u00e3o dos objetos e execu\u00e7\u00e3o das solicita\u00e7\u00f5es, \u00e9 necess\u00e1rio contabilizar o volume para realizar a cobran\u00e7a, ent\u00e3o cada shard possui contadores de faturamento.<\/p>\n<p><\/p>\n<p>Tamb\u00e9m adicionamos mais algumas tabelas e componentes:<\/p>\n<p><\/p>\n<ul>\n<li>lixeira, para eliminar antigos projetos que s\u00e3o exclu\u00eddos ou congelados;<\/li>\n<li>fila para tarefas em segundo plano, ou seja, o armazenamento principal pode executar tarefas em segundo plano que precisam ser feitas no cluster;<\/li>\n<li>suporte ao ciclo de vida \u2014 um mecanismo que permite trabalhar com objetos e gerenciar seu ciclo de vida.<\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Arquitetura S3: 3 anos de evolu\u00e7\u00e3o do Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/933e98dc559eb8e6bac14003215a6836.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Como parte dos dados foi movida para shards, precis\u00e1vamos de um proxy de shard. Poder\u00edamos ter reutilizado o roteador para essa fun\u00e7\u00e3o, mas um proxy de shard separado, respons\u00e1vel apenas pelo shard dos dados, permite que o roteador acesse os dados em geral, sem se preocupar com shard.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Arquitetura S3: 3 anos de evolu\u00e7\u00e3o do Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/4b181ed4629180e15558f25b1e4d5718.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Vou explicar separadamente por que n\u00e3o utilizamos uma solu\u00e7\u00e3o pronta, mas quisemos criar uma fun\u00e7\u00e3o de shard personalizada. <\/p>\n<p><\/p>\n<p>Vamos ver como ela \u00e9 estruturada. Temos 256 shards dispon\u00edveis. Para cada bucket, alocamos um intervalo usando uma fun\u00e7\u00e3o consistente. \u00c9 simples \u2014 assim como voc\u00ea determina a atribui\u00e7\u00e3o a um shard usando uma fun\u00e7\u00e3o consistente, voc\u00ea determina o shard inicial e aloca um intervalo:<\/p>\n<p><\/p>\n<p><code>f(bucket, shards) = subconjunto<\/code><\/p>\n<p><\/p>\n<p>Ou seja, se pegarmos um bucket, podemos dizer que ele e seus dados estar\u00e3o sempre em um subconjunto espec\u00edfico de todos os shards. Isso permite reduzir a influ\u00eancia de alguns buckets sobre outros e simplifica a execu\u00e7\u00e3o de consultas map-reduce, quando \u00e9 necess\u00e1rio, por exemplo, listar objetos de um bucket. Para isso, \u00e9 preciso interrogar todos os shards onde esses objetos est\u00e3o armazenados. Se os objetos estivessem em todos os shards, qualquer listagem afetaria todo o sistema, mas aqui afeta apenas um subconjunto espec\u00edfico.<\/p>\n<p><\/p>\n<p>Al\u00e9m disso, cada objeto pertence a um bucket espec\u00edfico, portanto, quando acessamos um objeto, estamos acessando um objeto pelo nome em um bucket espec\u00edfico. Ou seja, podemos definir uma fun\u00e7\u00e3o para o objeto n\u00e3o a partir de todo o intervalo de shards dispon\u00edveis, mas apenas a partir do subconjunto do seu bucket:<\/p>\n<p><\/p>\n<p><code>f(object, subset) = shard<\/code><\/p>\n<p><\/p>\n<p>Pegamos um objeto espec\u00edfico e, como argumentos da fun\u00e7\u00e3o, passamos n\u00e3o todos os shards, mas o subconjunto do seu bucket \u2014 e obtemos o shard espec\u00edfico. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Arquitetura S3: 3 anos de evolu\u00e7\u00e3o do Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/10480ad2430c228c511ff3cdc5071596.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Assim, o sharding est\u00e1 implementado, existe um proxy de sharding. O que resta \u00e9 que o roteador e o banco de metadados acessem o proxy de sharding. Por exemplo, para criar objetos de c\u00f3pias sombra \u2014 quando criamos um bucket, o armazenamento principal deve criar um representante desse bucket em todos os shards onde ele deve estar presente.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Arquitetura S3: 3 anos de evolu\u00e7\u00e3o do Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/bb34d1f747903a3c2f08f582e4424787.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<h2 id=\"kak-my-realizovali-resharding\">Como implementamos o resharding<\/h2>\n<p><\/p>\n<p>O maior problema do sharding \u00e9 o resharding. Era importante para n\u00f3s faz\u00ea-lo sem downtime, pois o sistema j\u00e1 estava em produ\u00e7\u00e3o. Vou mostrar como resolvemos o problema por meio de uma tarefa semelhante de migra\u00e7\u00e3o de dados ao vivo de um projeto para outro.<\/p>\n<p><\/p>\n<p>Abaixo est\u00e1 o diagrama do nosso cluster, que foi criado ap\u00f3s a implementa\u00e7\u00e3o do sharding. Temos nginx, API S3, roteador, banco de dados prim\u00e1rio com projetos, proxy shard e, diretamente, shards.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Arquitetura S3: 3 anos de evolu\u00e7\u00e3o do Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/0e6bd16c7fc47437b3b7d96b6d9809a4.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Acima, eu deixei de lado o fato de que em um certo momento do projeto havia uma necessidade de produto: \"Lan\u00e7ar mais um armazenamento, Icebox, como Hotbox, mas para dados frios\". Essencialmente, \u00e9 um armazenamento semelhante, mas com URLs diferentes e sem caches.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Arquitetura S3: 3 anos de evolu\u00e7\u00e3o do Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/9ce9085e1d03e9a99b6b8ccc0717c653.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>O Icebox foi utilizado menos do que o Hotbox, ent\u00e3o ele ficou bastante tempo sem qualquer sharding. No final, decidimos descontinu\u00e1-lo e unir Hotbox e Icebox em um \u00fanico servi\u00e7o, apenas dividindo as classes de armazenamento. <\/p>\n<p><\/p>\n<p>Os buckets nos armazenamentos n\u00e3o se sobrepunham, eram facilmente mescl\u00e1veis e transfer\u00edveis, mas os clientes usavam ambos os armazenamentos, o que significava que precis\u00e1vamos resolver o problema de falta de downtime. N\u00e3o pod\u00edamos simplesmente desligar e copiar. Fizemos a migra\u00e7\u00e3o em v\u00e1rias etapas.<\/p>\n<p><\/p>\n<p>Primeiro, sincronizamos os armazenamentos prim\u00e1rios. T\u00ednhamos Tarantool e pod\u00edamos, ao criar um objeto, fazer o seguinte: <\/p>\n<p><\/p>\n<ul>\n<li>um pedido de cria\u00e7\u00e3o de bucket chega ao banco, por exemplo, no Hotbox;<\/li>\n<li>o Tarantool verifica em outro banco (neste caso, no Icebox) se tal bucket n\u00e3o existe;<\/li>\n<li>se o bucket existir, o banco informa que n\u00e3o pode ser criado, e ele se sincronizou como existente.<br \/>\n<img decoding=\"async\" alt=\"Arquitetura S3: 3 anos de evolu\u00e7\u00e3o do Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/6694c9804f09942416c1717b455b9fd3.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<em>Sincroniza\u00e7\u00e3o de buckets<\/em><\/li>\n<\/ul>\n<p><\/p>\n<p>No armazenamento que deveria receber todos os dados, introduzimos para projetos e buckets um sinalizador que indicava onde esse objeto estava armazenado. Ele poderia estar armazenado localmente, ou seja, no Hotbox, no Icebox - neste caso, no novo armazenamento n\u00e3o havia dados para ele, ou poderia estar em estado de migra\u00e7\u00e3o.<\/p>\n<p><\/p>\n<p>Se um projeto ou bucket tinha o sinalizador Migrating, durante a migra\u00e7\u00e3o o pedido era executado primeiro no novo armazenamento, onde os dados deveriam estar, e se n\u00e3o estivessem l\u00e1, os pedidos eram redirecionados para o armazenamento alternativo.<\/p>\n<p><\/p>\n<p>Depois, mudamos o tr\u00e1fego. Como a API poderia atender tanto os pedidos do Icebox quanto os do Hotbox, conseguimos mudar o tr\u00e1fego sem downtime, simplesmente transferindo os hosts e adicionando os registros apropriados no Nginx. <\/p>\n<p><\/p>\n<p>Ap\u00f3s o redirecionamento do tr\u00e1fego, o Nginx e a API da Icebox puderam ser removidos.<br \/>\nEm seguida, removemos o nginx da Icebox e a API S3 \u2014 e tudo funcionou.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Arquitetura S3: 3 anos de evolu\u00e7\u00e3o do Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/62d9f960fc1f11b875a8f8a5aa8e8152.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Depois, iniciamos um processo de migra\u00e7\u00e3o em segundo plano que opera dentro do banco de dados \u2014 percorre todos os projetos e seus buckets, marca-os como Migrating, transfere os dados e, ao concluir a transfer\u00eancia, define o status como Local.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Arquitetura S3: 3 anos de evolu\u00e7\u00e3o do Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/1a3129136f7ccacfdcff260f10cb0605.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ap\u00f3s a transfer\u00eancia de dados, n\u00e3o precisamos mais do armazenamento antigo, e removemos as partes restantes do sistema antigo, assim como removemos do c\u00f3digo o suporte ao status de migra\u00e7\u00e3o.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Arquitetura S3: 3 anos de evolu\u00e7\u00e3o do Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/13b6f11add40c21a3b9afc05dd0dfea9.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Da mesma forma, foi realizada a resharding do armazenamento antigo para o shard:<\/p>\n<p><\/p>\n<ul>\n<li>Marcamos todos os buckets como <code>Non-sharded<\/code>. Todas as solicita\u00e7\u00f5es para esses buckets foram direcionadas ao armazenamento original, n\u00e3o shard.<\/li>\n<li>Novos buckets foram criados imediatamente com o status <code>Sharded<\/code>.<\/li>\n<li>Um a um, peg\u00e1vamos os buckets, marc\u00e1vamos o status como <code>Migrating<\/code> e transfer\u00edamos os dados.<\/li>\n<\/ul>\n<p><\/p>\n<p>As solicita\u00e7\u00f5es foram atendidas da seguinte maneira:<\/p>\n<p><\/p>\n<ul>\n<li>Lemos no novo, depois no antigo.<\/li>\n<li>Criamos apenas no novo.<\/li>\n<li>Atualizamos de forma bif\u00e1sica: se n\u00e3o houver no novo, transferimos do antigo para o novo, depois atualizamos.<\/li>\n<\/ul>\n<p><\/p>\n<h2 id=\"rabota-s-ssl-sertifikatami\">Trabalho com certificados SSL<\/h2>\n<p><\/p>\n<blockquote><p>Na frente, usamos Nginx. Neste caso, n\u00e3o \u00e9 um Nginx comum, mas OpenResty, Nginx com suporte a LuaJIT.<\/p><\/blockquote>\n<p>Mais uma parte do sistema \u2014 trabalho com certificados SSL. No armazenamento S3, voc\u00ea pode definir seu pr\u00f3prio dom\u00ednio para acessar um bucket espec\u00edfico, apenas usando <code>CNAME<\/code>. Mas atualmente n\u00e3o se pode ter HTTPS: um dom\u00ednio pr\u00f3prio implica em um certificado SSL pr\u00f3prio. <\/p>\n<p><\/p>\n<p>Como mencionei, o Nginx \u00e9 respons\u00e1vel pelo balanceamento e pela termina\u00e7\u00e3o SSL. Neste caso, n\u00e3o \u00e9 um Nginx comum, mas OpenResty, Nginx com suporte a LuaJIT.<\/p>\n<p><\/p>\n<p>Isso nos permitiu ensinar nosso Nginx a entregar certificados arbitr\u00e1rios de maneira bastante simples. Al\u00e9m disso, precis\u00e1vamos fornecer certificados de forma din\u00e2mica (sem a necessidade de especific\u00e1-los no arquivo de configura\u00e7\u00e3o). Utilizamos a extens\u00e3o <code>ssl_certificate_by_lua<\/code>, que permite ler o certificado de uma fonte arbitr\u00e1ria durante o handshake TLS. Como reposit\u00f3rio de certificados, tamb\u00e9m utilizamos o Tarantool: isso permite gerenciar os certificados externamente e garante uma entrega extremamente r\u00e1pida.<\/p>\n<p><\/p>\n<p>Tamb\u00e9m foi implementado um daemon separado, cuja tarefa \u00e9 atualizar regularmente os certificados emitidos com o Let\u2019s Encrypt.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Arquitetura S3: 3 anos de evolu\u00e7\u00e3o do Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/8d61c1cb3084d9eb4eb8faa745e212db.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<h2 id=\"chto-by-ya-sohranil-a-chto-sdelal-po-drugomu-esli-razrabatyvat-hranilische-zanovo\">O que eu manteria e o que faria diferente se estivesse desenvolvendo o armazenamento do zero<\/h2>\n<p><\/p>\n<h3 id=\"chto-nuzhno-bylo-ispolzovat-s-samogo-nachala\">O que deveria ter sido usado desde o in\u00edcio<\/h3>\n<p><\/p>\n<p><strong>Sharding desde o in\u00edcio<\/strong>. Fomos confrontados com muitos problemas devido \u00e0 resharding. Ele \u00e9 f\u00e1cil de implementar, mas se voc\u00ea est\u00e1 come\u00e7ando projetos que precisam escalar, \u00e9 melhor usar um cluster shardado desde o in\u00edcio, mesmo que com um n\u00famero m\u00ednimo de n\u00f3s. A implementa\u00e7\u00e3o de sharding no in\u00edcio \u00e9 quase gratuita em compara\u00e7\u00e3o com a implementa\u00e7\u00e3o de sharding em um sistema em produ\u00e7\u00e3o.<\/p>\n<p><\/p>\n<p><strong>Trabalhando com Tarantool atrav\u00e9s de balanceadores<\/strong>. Atualmente, conectamos todas as novas bases de dados ao sistema atrav\u00e9s de balanceadores. Isso permite expandir a funcionalidade e alcan\u00e7ar maior resist\u00eancia a falhas. <\/p>\n<p><\/p>\n<p><strong>Auto-failover<\/strong>. Eu teria instalado todas as ferramentas necess\u00e1rias para o auto-failover, pois as primeiras falhas ap\u00f3s o lan\u00e7amento estavam relacionadas \u00e0 sua aus\u00eancia. Ap\u00f3s a experi\u00eancia com o S3, todos os produtos subsequentes foram lan\u00e7ados levando isso em considera\u00e7\u00e3o.<\/p>\n<p><\/p>\n<p><strong>Recurso S3 \"Versionamento\"<\/strong>. No in\u00edcio pareceu que essa funcionalidade n\u00e3o era muito demandada. Integrar essa possibilidade na arquitetura de um sistema em funcionamento \u00e9 extremamente dif\u00edcil.<\/p>\n<p><\/p>\n<p><strong>Faturamento separado<\/strong>. A forma como integramos o faturamento em nosso sistema se mostrou adequada no in\u00edcio, mas posteriormente se tornou um obst\u00e1culo; teria sido melhor implement\u00e1-lo como um servi\u00e7o completamente separado.<\/p>\n<p><\/p>\n<h3 id=\"chto-bylo-udachnym-resheniem\">O que foi uma decis\u00e3o acertada<\/h3>\n<p><\/p>\n<p><strong>Modelo de dados<\/strong>. A hist\u00f3ria mostrou que, \u00e0 medida que o servi\u00e7o se desenvolvia, est\u00e1vamos bastante alinhados com o modelo de dados da Amazon, permitindo-nos implementar as mesmas funcionalidades que existem l\u00e1.<\/p>\n<p><\/p>\n<p><strong>Esquema de sharding<\/strong>. Eu apoiaria o mesmo tipo de sharding por faixas em buckets, pois isso permite distribuir bem as requisi\u00e7\u00f5es de diferentes buckets por um grande cluster.<\/p>\n<p><\/p>\n<p><strong>Uso de Tarantool<\/strong>. Tarantool ajudou bastante no desenvolvimento e modifica\u00e7\u00e3o do servi\u00e7o; trabalhamos com dados facilmente, transformamos e shardamos o armazenamento sem a necessidade de subir para o n\u00edvel da aplica\u00e7\u00e3o. <\/p>\n<p><\/p>\n<blockquote><p>Esta apresenta\u00e7\u00e3o foi feita pela primeira vez na <noindex><a rel=\"nofollow\" href=\"https:\/\/corp.mail.ru\/ru\/press\/events\/databases-2\/\">@Databases Meetup<\/a><\/noindex> por Mail.ru Cloud Solutions &amp; Tarantool. Veja <noindex><a rel=\"nofollow\" href=\"https:\/\/www.youtube.com\/watch?v=jM4hL2u6JM0&amp;list=PLQzTaxmOHjntyNRPWhaWHqlHp8UN_wgQ3\">v\u00eddeo<\/a><\/noindex> outras apresenta\u00e7\u00f5es e inscreva-se para receber atualiza\u00e7\u00f5es de eventos no Telegram <noindex><a rel=\"nofollow\" href=\"https:\/\/t.me\/k8s_mail\">Em torno do Kubernetes no Mail.ru Group<\/a><\/noindex>.<\/p><\/blockquote>\n<p>Voc\u00ea tamb\u00e9m pode assistir minha antiga apresenta\u00e7\u00e3o sobre S3 ou ler o artigo de um colega sobre armazenamento em bloco.<\/p>\n<p><\/p>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/www.youtube.com\/watch?v=O0iIADHgBVc\">Engenharia reversa da arquitetura do Amazon S3 e como era o armazenamento S3 do MCS h\u00e1 3 anos<\/a><\/noindex>.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/mailru\/blog\/472694\/\">Mais do que Ceph: armazenamento em bloco da nuvem MCS<\/a><\/noindex>.<\/li>\n<\/ul>\n<p>Fonte: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/mailru\/blog\/513356\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>Storage Corridor by St-Pete \u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442! \u042f Mons Anderson, \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u043e\u0440 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b Mail.ru Cloud Solutions, \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443, \u043a\u0430\u043a \u043c\u044b \u043f\u043e\u0441\u0442\u0440\u043e\u0438\u043b\u0438 \u043d\u0430\u0448\u0435 S3-\u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435, \u043a\u0430\u043a \u043e\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u043a\u0430\u043a\u0438\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043e\u043a\u0430\u0437\u0430\u043b\u0438\u0441\u044c \u0443\u0434\u0430\u0447\u043d\u044b\u043c\u0438, \u0430 \u043a\u0430\u043a\u0438\u0435 \u0441\u0442\u043e\u0438\u043b\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c, \u0435\u0441\u043b\u0438 \u0431\u044b \u043c\u044b \u043d\u0430\u0447\u0430\u043b\u0438 \u0442\u0430\u043a\u043e\u0439 \u0436\u0435 \u043f\u0440\u043e\u0435\u043a\u0442 \u0441 \u043d\u0443\u043b\u044f \u0441\u0435\u0439\u0447\u0430\u0441. \u0421\u0442\u0430\u0442\u044c\u044f \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043b\u0435\u043d\u0430 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0434\u043e\u043a\u043b\u0430\u0434\u0430 \u043d\u0430 @Databases Meetup by Mail.ru Cloud Solutions &amp; Tarantool. [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":91091,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-91090","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.3 - aioseo.com -->\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\/pt\/blog\/administrirovanie\/arhitektura-s3-3-goda-evolyuczii-mail-ru-cloud-storage\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.3\" \/>\n\t\t<meta property=\"og:locale\" content=\"pt_PT\" \/>\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 S3: 3 \u0433\u043e\u0434\u0430 \u044d\u0432\u043e\u043b\u044e\u0446\u0438\u0438 Mail.ru Cloud Storage | ProHoster\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/pt\/blog\/administrirovanie\/arhitektura-s3-3-goda-evolyuczii-mail-ru-cloud-storage\" \/>\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-08-08T11:42:11+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-08-08T11:42:11+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\udd47Arquitetura S3: 3 anos de evolu\u00e7\u00e3o do Mail.ru Cloud Storage | ProHoster","description":"","canonical_url":"https:\/\/prohoster.info\/pt\/blog\/administrirovanie\/arhitektura-s3-3-goda-evolyuczii-mail-ru-cloud-storage","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"pt_PT","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 S3: 3 \u0433\u043e\u0434\u0430 \u044d\u0432\u043e\u043b\u044e\u0446\u0438\u0438 Mail.ru Cloud Storage | ProHoster","og:url":"https:\/\/prohoster.info\/pt\/blog\/administrirovanie\/arhitektura-s3-3-goda-evolyuczii-mail-ru-cloud-storage","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-08-08T11:42:11+00:00","article:modified_time":"2020-08-08T11:42:11+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"91090","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":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 12:34:25","updated":"2022-10-02 13:27:50","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/posts\/91090","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/comments?post=91090"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/posts\/91090\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/media\/91091"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/media?parent=91090"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/categories?post=91090"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/tags?post=91090"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}