{"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\/pl\/blog\/administrirovanie\/arhitektura-s3-3-goda-evolyuczii-mail-ru-cloud-storage","title":{"rendered":"Architektura S3: 3 lata ewolucji Mail.ru Cloud Storage","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Architektura S3: 3 lata ewolucji 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\">Korytarz przechowywania<\/a><\/noindex> od St-Petersburga<\/em><\/p>\n<p><\/p>\n<p>Cze\u015b\u0107 wszystkim! Jestem Mons Anderson, architekt platformy <noindex><a rel=\"nofollow\" href=\"https:\/\/mcs.mail.ru\/\">Mail.ru Cloud Solutions<\/a><\/noindex>, opowiem, jak zbudowali\u015bmy nasze przechowywanie S3, jak dzia\u0142a, jakie rozwi\u0105zania okaza\u0142y si\u0119 skuteczne, a kt\u00f3re warto by\u0142oby zmieni\u0107, gdyby\u015bmy zacz\u0119li ten sam projekt od nowa teraz.<\/p>\n<p><\/p>\n<p>Artyku\u0142 przygotowany na podstawie prezentacji na <noindex><a rel=\"nofollow\" href=\"https:\/\/corp.mail.ru\/ru\/press\/events\/databases-2\/\">@Databases Meetup<\/a><\/noindex> od Mail.ru Cloud Solutions &amp; Tarantool. W artykule om\u00f3wimy:<\/p>\n<p><\/p>\n<ul>\n<li>jak by\u0142o zorganizowane przechowywanie Mail.ru, na kt\u00f3rym budowali\u015bmy przechowywanie S3;<\/li>\n<li>co dodali\u015bmy, aby stworzy\u0107 Mail.ru Cloud Storage;<\/li>\n<li>jak dzia\u0142a obiektowy model przechowywania i jakie kroki podj\u0119to, aby przej\u015b\u0107 do produkcji;<\/li>\n<li>o udoskonaleniach systemu produkcyjnego: failover i skalowanie;<\/li>\n<li>jak wdro\u017cyli\u015bmy sharding i resharding;<\/li>\n<li>a tak\u017ce o pracy z certyfikatami SSL.<\/li>\n<\/ul>\n<p><\/p>\n<p>Je\u015bli nie chcesz czyta\u0107, mo\u017cesz <noindex><a rel=\"nofollow\" href=\"https:\/\/youtu.be\/NEgm1nsv-qg\">zobaczy\u0107<\/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\">Jak by\u0142o zorganizowane przechowywanie Mail.ru, na kt\u00f3rym budowali\u015bmy przechowywanie S3<\/h2>\n<p><\/p>\n<p>Rozw\u00f3j naszego S3 rozpocz\u0105\u0142 si\u0119 na bazie przechowywania w Chmurze Mail.ru, dlatego warto najpierw opowiedzie\u0107, jak ono dzia\u0142a i co potrafi.<\/p>\n<p><\/p>\n<p>Przechowywanie chmury Mail.ru sk\u0142ada si\u0119 z serwer\u00f3w z dyskami. \u015arednio, wsp\u00f3\u0142czesny serwer storage to 36 dysk\u00f3w po 12-14 terabajt\u00f3w. Kiedy\u015b dyski by\u0142y mniejsze, ale przez trzy lata pojemno\u015bci dysk\u00f3w wzros\u0142y i dzisiaj to prawie p\u00f3\u0142 petabajta surowych danych. <\/p>\n<p><\/p>\n<p>Dyski z r\u00f3\u017cnych serwer\u00f3w przechowywania s\u0105 \u0142\u0105czone w tzw. \u201epary\u201d (pair). Para to jednostkowy unit przechowywania plik\u00f3w. W istocie jest to dysk zamontowany w okre\u015blonym dziale pod okre\u015blon\u0105 \u015bcie\u017ck\u0105, gdzie mog\u0105 le\u017ce\u0107 pliki identyfikowane przez hashe. <\/p>\n<p><\/p>\n<p>Para to historyczna nazwa, zachowa\u0142a si\u0119 do dzi\u015b, chocia\u017c w parze niekoniecznie musz\u0105 by\u0107 tylko dwa dyski. Mo\u017ce by\u0107 ich trzy, a tak\u017ce mog\u0105 istnie\u0107 r\u00f3\u017cne hybrydowe przechowywania, na przyk\u0142ad 3\/2. <\/p>\n<p>\n<img decoding=\"async\" alt=\"Architektura S3: 3 lata ewolucji Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/544ab79846539262e2d4dff6ab95ffff.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><em>Pary (pair) \u2014 jednostki przechowywania obiekt\u00f3w<\/em><\/p>\n<p><\/p>\n<p>Wszystkie pary s\u0105 przechowywane w PairDB \u2014 to aplikacja w oparciu o Tarantool. Wszystkie bazy w naszym przechowywaniu, pocz\u0105wszy od najwcze\u015bniejszych, to Tarantool, innych baz nie u\u017cywamy.<\/p>\n<p><\/p>\n<p>PairDB przechowuje wszystkie pary, ich stany, wolne miejsce, mo\u017cliwo\u015bci awaryjne, ostatnie b\u0142\u0119dy. Mo\u017ce r\u00f3wnie\u017c sama sprawdza\u0107 pary, aktualizowa\u0107 ich stan, weryfikowa\u0107, czy dzia\u0142aj\u0105, czy nie. Czyli PairDB to og\u00f3lny obraz stanu wszystkich dysk\u00f3w naszego systemu.<\/p>\n<p>\n<img decoding=\"async\" alt=\"Architektura S3: 3 lata ewolucji Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/d50781b8b51ed5fe126bc84e19c934d1.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><em>Pair DB: baza danych z stanem par<\/em><\/p>\n<p><\/p>\n<p>Na parach przechowywane s\u0105 pliki, a aby wiedzie\u0107, na kt\u00f3rej parach jaki plik si\u0119 znajduje, potrzebna jest jeszcze jedna baza \u2014 FileDB. Przechowuje ona mapowanie, okre\u015blenie zgodno\u015bci: plik taki a taki znajduje si\u0119 na parze takiej a takiej, a tak\u017ce niewielk\u0105 liczb\u0119 potrzebnych atrybut\u00f3w.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Architektura S3: 3 lata ewolucji Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/b1a64737cf7f916bff446c10c1f01d4c.jpeg\" style=\"display:block;margin: 0 auto;\" \/><em>File DB: miejsce, w kt\u00f3rym przechowywany jest plik<\/em><\/p>\n<p>Kolejnym istotnym ogniwem jest serwis Nylon, router do pracy z bazami danych. Jest to jednolity punkt dost\u0119pu, pozwala na prac\u0119 przez jeden interfejs zar\u00f3wno z PairDB, jak i z FileDB. Jest to us\u0142uga stateless, wykonuje balansowanie zapyta\u0144, rozumie, na kt\u00f3ry shard FileDB nale\u017cy i\u015b\u0107, wie, kt\u00f3re pary s\u0105 aktywne, a kt\u00f3re nie.<\/p>\n<p>\n<img decoding=\"async\" alt=\"Architektura S3: 3 lata ewolucji Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/3e2225f229c8cfa462d620d2b5fb581e.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><em>Nylon: router do pracy z bazami danych<\/em><\/p>\n<p><\/p>\n<p>W magazynie nale\u017cy jako\u015b umieszcza\u0107 tre\u015bci. W tym celu istnieje serwis \u2014 Streamer. Udost\u0119pnia on dwie metody HTTP: metod\u0119 PUT, aby wprowadzi\u0107 tre\u015b\u0107 do magazynu, oraz metod\u0119 GET, aby j\u0105 stamt\u0105d pobra\u0107. HTTP to do\u015b\u0107 popularny i wygodny protok\u00f3\u0142 do przesy\u0142ania danych. <\/p>\n<p><\/p>\n<p>Gdy zwracamy si\u0119 do Streamer\u2019a, on przez Nylon kontaktuje si\u0119 z PairDB, okre\u015blaj\u0105c, na kt\u00f3r\u0105 par\u0119 mo\u017cna przes\u0142a\u0107 plik, po czym przesy\u0142a dane za pomoc\u0105 WebDAV do tej pary. <\/p>\n<p><\/p>\n<p>W zasadzie ka\u017cdy serwer storage to nginx plus dyski, kt\u00f3re s\u0105 zamontowane na okre\u015blonych \u015bcie\u017ckach. Mo\u017cemy z Streamera wprowadzi\u0107 plik do magazynu, usun\u0105\u0107 go, zmieni\u0107 nazw\u0119 lub sprawdzi\u0107 jego integralno\u015b\u0107. To wygodny interfejs do niskopoziomowej interakcji z magazynem. <\/p>\n<p>\n<img decoding=\"async\" alt=\"Architektura S3: 3 lata ewolucji Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/3722a89ed44cace36e9cb1f8bee4bd1e.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><em>Streamer: punkt dost\u0119pu do magazynu<\/em><\/p>\n<p><\/p>\n<h2 id=\"chto-my-dobavili-chtoby-sdelat-s3-hranilische\">Co dodali\u015bmy, aby zrealizowa\u0107 magazyn S3<\/h2>\n<p><\/p>\n<p>Przeanalizowali\u015bmy podstawow\u0105 struktur\u0119 magazynu w momencie, gdy planowali\u015bmy uruchomi\u0107 magazyn S3. Dzi\u0119ki metodzie PUT mogli\u015bmy umie\u015bci\u0107 tam dowoln\u0105 tre\u015b\u0107 i otrzyma\u0107 jako identyfikator tych danych hasz. Z tym identyfikatorem mo\u017cna by\u0142o p\u00f3\u017aniej przyj\u015b\u0107 i odebra\u0107 oryginalny plik. Jednak to za ma\u0142o, aby zrealizowa\u0107 S3. W protokole S3, opr\u00f3cz samego przechowywania obiekt\u00f3w, znajduj\u0105 si\u0119:<\/p>\n<p><\/p>\n<ul>\n<li>przechowywanie metadanych \u2014 dodatkowych w\u0142a\u015bciwo\u015bci obiekt\u00f3w;<\/li>\n<li>organizowanie dost\u0119pu do obiekt\u00f3w za po\u015brednictwem HTTP;<\/li>\n<li>grupowanie obiekt\u00f3w w kolekcjach \u2014 bucketach;<\/li>\n<li>Endpoint HTTP-S3. S3 organizuje dane w okre\u015blone struktury \u2014 buckety, z kt\u00f3rych ka\u017cdy zapewnia punkt dost\u0119pu do przechowywania plik\u00f3w.<\/li>\n<\/ul>\n<p><\/p>\n<p>A separate service was needed to implement this logic. We also wanted to immediately provide an architecture for further growth of the service with linear scalability.<\/p>\n<p><\/p>\n<h2 id=\"pervye-komponenty\">First components<\/h2>\n<p><\/p>\n<p>A daemon implementing the S3 API. This is the standard S3 API from Amazon, which supports XML operations for metadata and allows content to be transferred directly. We didn't have to invent anything; it's all described and documented.<\/p>\n<p><\/p>\n<p>We also placed Nginx in front of the service. We used it for SSL termination, load balancing, and some logic on Lua (metrics, logging, and tracing).<\/p>\n<p><\/p>\n<p>For storing S3 metadata, we also chose Tarantool. In the first version, the S3 daemon accessed this database for metadata, while the content was stored in a large repository via Streamer.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Architektura S3: 3 lata ewolucji Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/03dddec282b5bb41eb63748ccfb6c9a4.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<em>Nginx + S3 API + metadata<\/em><\/p>\n<p><\/p>\n<h2 id=\"obektnaya-model-hraneniya\">Object storage model<\/h2>\n<p><\/p>\n<p>Let's look at how S3 works. A user can create a bucket\u2014a collection of objects. The bucket is addressed by the host name and serves as a subdomain of the service. Within the bucket, a user can create objects. The object's identifier will be the URL. The content of the object is a blob, an array of binary data that we will store in the repository. The object also has attributes: name\u2014that same URL, ACL (access control list), and other additional or arbitrary attributes\u2014all of this is saved in metadata. <\/p>\n<p><\/p>\n<p>The normalized schema of this data might look like this: there are projects that own buckets, which in turn own objects, and objects can be composite. Since one way to upload an object is in parts, there are two auxiliary tables for uploads: uploads and chunks. Also, projects have credentials for access and billing. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Architektura S3: 3 lata ewolucji Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/e2bede45ba4044f658b47a9840fd5224.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<em>Data schema<\/em><\/p>\n<p><\/p>\n<p>Since we were creating a B2B service with paid access, billing was needed in this scheme.<br \/>\nWe also implemented the billing service on Tarantool. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Architektura S3: 3 lata ewolucji 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\">Improvements to the S3 storage: steps to production<\/h2>\n<p><\/p>\n<p>We have already developed a working model that can be used: objects and metadata were stored, but several aspects were missing for a production rollout.<\/p>\n<p><\/p>\n<p>Po pierwsze, system limit\u00f3w przepustowo\u015bci. Je\u015bli uruchomimy us\u0142ug\u0119 bez niego, w przypadku maksymalnego obci\u0105\u017cenia mo\u017cemy nieprzewidywalnie przeci\u0105\u017cy\u0107 jak\u0105\u015b cz\u0119\u015b\u0107 systemu. Limit przepustowo\u015bci powinien dzia\u0142a\u0107 nast\u0119puj\u0105co: ka\u017cde \u017c\u0105danie S3 trafia na konkretny host, ten host jest identyfikatorem koszyka, a koszyk nale\u017cy do konkretnego klienta. Musimy okre\u015bli\u0107 pewn\u0105 funkcj\u0119 koszyka, kt\u00f3ra pozwoli\u0142aby obliczy\u0107 limit przepustowo\u015bci. <\/p>\n<p><\/p>\n<p>Ponadto system limit\u00f3w przepustowo\u015bci powinien by\u0107 wystarczaj\u0105co wydajny, aby wytrzyma\u0107 obci\u0105\u017cenie, kt\u00f3re przychodzi na S3.<\/p>\n<p><\/p>\n<p>Tutaj ponownie u\u017cyli\u015bmy Tarantoola. Limity przepustowo\u015bci to klaster z\u0142o\u017cony z 21 instancji, instancje s\u0105 podzielone na grupy, rozproszone na trzech fizycznych w\u0119z\u0142ach i po\u0142\u0105czone w du\u017cym klastrze topologicznym. Automatycznie rozprzestrzeniaj\u0105 si\u0119 po nim zmiany konfiguracyjne: ustalane s\u0105 limity przepustowo\u015bci, warto\u015bci domy\u015blne oraz konfiguracja. Ka\u017cdy koszyk obs\u0142ugiwany jest wy\u0142\u0105cznie przez jedn\u0105 instancj\u0119. Gdy konkretne \u017c\u0105danie trafia do danego koszyka, obliczana jest instancja odpowiedzialna za ten koszyk. W ramach tego w\u0119z\u0142a liczony jest bie\u017c\u0105cy wska\u017anik \u017c\u0105da\u0144 za pomoc\u0105 algorytmu podobnego do Token Bucket. Nast\u0119pnie system limit\u00f3w przepustowo\u015bci, na podstawie bie\u017c\u0105cych wska\u017anik\u00f3w obci\u0105\u017cenia i w\u0142a\u015bciwo\u015bci ustalonych dla konkretnego koszyka, decyduje, czy mo\u017cna zrealizowa\u0107 \u017c\u0105danie, czy nie. Sprawdzenie limit\u00f3w wykonywane jest na najwcze\u015bniejszym etapie realizacji \u017c\u0105dania S3, chroni\u0105c wszystkie pozosta\u0142e elementy systemu przed nadmiernym obci\u0105\u017ceniem. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Architektura S3: 3 lata ewolucji Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/1b91e5d1fe067c859ba9b36d58827579.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Pod du\u017cym obci\u0105\u017ceniem do\u015b\u0107 trudno oby\u0107 si\u0119 bez cache. W S3 zak\u0142ada si\u0119 wielokrotne odwo\u0142ania do tych samych obiekt\u00f3w, czyli jest to gor\u0105ce przechowywanie. W normalnym przypadku odwo\u0142anie do pojedynczego pliku obs\u0142ugiwane jest przez pe\u0142ny \u0142a\u0144cuch: Streamer, FileDB, PairDB, Storage. Jednak przy wielokrotnym odwo\u0142aniu do pliku optymalizujemy dost\u0119p do tej tre\u015bci za pomoc\u0105 lokalnej pami\u0119ci podr\u0119cznej.<\/p>\n<p><\/p>\n<p>Cache jest wielowarstwowy i realizowany za pomoc\u0105 nginx, lokalnych dysk\u00f3w SSD i dysk\u00f3w RAM. Nie u\u017cyli\u015bmy tutaj Tarantoola, poniewa\u017c wygodniej jest dostarcza\u0107 obiekty z systemu plik\u00f3w, co pozwala na tworzenie struktury cache. Ponadto mamy du\u017ce obiekty o maksymalnym rozmiarze 32 gigabajty, a w Tarantool mo\u017cna cache'owa\u0107 tylko ma\u0142e obiekty.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Architektura S3: 3 lata ewolucji Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/faa02bd52a1d70642589d775f22c5e75.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ten pierwszy system, z kt\u00f3rym wystartowali\u015bmy, mia\u0142 pewn\u0105 zaplanowan\u0105 pojemno\u015b\u0107, kt\u00f3rej wystarczy\u0142o, aby przeprowadzi\u0107 badania, zrozumie\u0107 produkt oraz sprawdzi\u0107, \u017ce b\u0119dzie dzia\u0142a\u0142. <\/p>\n<p><\/p>\n<h2 id=\"dorabotki-boevoy-sistemy-feylover-i-masshtabirovanie\">Rozw\u00f3j systemu operacyjnego: failover i skalowanie<\/h2>\n<p><\/p>\n<p>System by\u0142 ju\u017c w u\u017cyciu, a na pocz\u0105tku co\u015b przeoczyli\u015bmy \u2014 nale\u017ca\u0142o doda\u0107 failover i skalowanie. <\/p>\n<p><\/p>\n<p>Nasz demon S3 pobiera\u0142 metadane za pomoc\u0105 protoko\u0142u Tarantool. Zamiast pierwotnej bazy umie\u015bcili\u015bmy Tarantool, kt\u00f3ry pe\u0142ni\u0142 rol\u0119 proxy-routera zapyta\u0144 o metadane. Z perspektywy aplikacji realizuj\u0105cej API, nic si\u0119 nie zmieni\u0142o \u2014 wci\u0105\u017c komunikowa\u0142a si\u0119 z baz\u0105 za pomoc\u0105 protoko\u0142u Tarantool, ale router m\u00f3g\u0142 zapewni\u0107 aktywny failover. To znaczy, \u017ce mogli\u015bmy sprawdza\u0107 dost\u0119pno\u015b\u0107 w\u0119z\u0142a, przetrzymywa\u0107 pauzy podczas prze\u0142\u0105cze\u0144 i awarii, i tak dalej. Przy tym nie modyfikowali\u015bmy samej aplikacji. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Architektura S3: 3 lata ewolucji 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\">Wi\u0119cej informacji o tym, jak zrealizowali\u015bmy sharding<\/h2>\n<p><\/p>\n<p>Nast\u0119pne zagadnienie, kt\u00f3re nas zmartwi\u0142o \u2014 to sharding. System r\u00f3s\u0142, liczba obiekt\u00f3w zwi\u0119ksza\u0142a si\u0119 i trzeba by\u0142o zapewni\u0107 mo\u017cliwo\u015bci dalszego wzrostu.<\/p>\n<p><\/p>\n<p>Wracaj\u0105c do schematu danych: s\u0105 projekty, s\u0105 kube\u0142ki, kredyty i billing. To obiekty, kt\u00f3re z du\u017cym prawdopodobie\u0144stwem nie przekrocz\u0105 granic jednego instancji ani pod wzgl\u0119dem obj\u0119to\u015bci, ani pod wzgl\u0119dem zapyta\u0144 w przewidywalnej przysz\u0142o\u015bci. Oznacza to, \u017ce nie ma sensu ich shardowa\u0107, dlatego przenie\u015bli\u015bmy je do osobnej instancji, kt\u00f3ra pozostanie nieshardowana. Umo\u017cliwia to bardziej konsekwentne zarz\u0105dzanie projektami i kube\u0142kami, poniewa\u017c istnieje jedna, nieshardowana jednostka. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Architektura S3: 3 lata ewolucji Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/c5a1c1a875e756e3dceb5f885fbda2c8.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>W schemacie s\u0105 r\u00f3wnie\u017c obiekty, kt\u00f3re rosn\u0105 linearne \u2014 najpierw by\u0142o ich setki tysi\u0119cy, a obecnie ich liczba liczona jest w miliardach. Takie obiekty wraz z ich cz\u0119\u015bciami musia\u0142y by\u0107 przeniesione do klastra shardowanego. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Architektura S3: 3 lata ewolucji Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/00bb418cc61ad2e3e8797caf5d1ab202.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Podzielili\u015bmy schemat, ale obiekty musz\u0105 wsp\u00f3\u0142pracowa\u0107 z kube\u0142kami: obiekt zawsze nale\u017cy do konkretnego kube\u0142ka, a na kube\u0142ku dzia\u0142a ACL. Dlatego dla ka\u017cdego shardu z obiektami przechowujemy kopi\u0119 cieniow\u0105 ka\u017cdego kube\u0142ka. Dodatkowo, podczas modyfikacji obiekt\u00f3w i realizacji zapyta\u0144, trzeba liczy\u0107 obj\u0119to\u015b\u0107 dla realizacji billingu, dlatego na ka\u017cdym shardzie s\u0105 liczniki billingowe.<\/p>\n<p><\/p>\n<p>Dodali\u015bmy r\u00f3wnie\u017c kilka dodatkowych tabel i komponent\u00f3w:<\/p>\n<p><\/p>\n<ul>\n<li>kosz, do usuwania starych projekt\u00f3w, kt\u00f3re s\u0105 usuwane lub zamra\u017cane;<\/li>\n<li>kolejka dla zada\u0144 w tle, co oznacza, \u017ce g\u0142\u00f3wne magazynowanie mo\u017ce obs\u0142ugiwa\u0107 zadania w tle, kt\u00f3re nale\u017cy wykona\u0107 w klastrze;<\/li>\n<li>wsparcie lifecycle \u2014 mechanizmu, kt\u00f3ry pozwala na prac\u0119 z obiektami i zarz\u0105dzanie ich cyklem \u017cycia.<\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Architektura S3: 3 lata ewolucji Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/933e98dc559eb8e6bac14003215a6836.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Poniewa\u017c cz\u0119\u015b\u0107 danych przenie\u015bli\u015bmy na shardy, potrzebny by\u0142 proxy sharduj\u0105cy. Mo\u017cna by by\u0142o wykorzysta\u0107 router do tej roli, ale oddzielny proxy sharduj\u0105cy, odpowiedzialny tylko za shardowanie danych, pozwala na zbieranie danych w ca\u0142o\u015bci z routera, nie my\u015bl\u0105c o shardowaniu.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Architektura S3: 3 lata ewolucji Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/4b181ed4629180e15558f25b1e4d5718.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Osobno opowiem, dlaczego nie skorzystali\u015bmy z gotowego rozwi\u0105zania, a chcieli\u015bmy stworzy\u0107 niestandardow\u0105 funkcj\u0119 shardowania. <\/p>\n<p><\/p>\n<p>Zobaczmy, jak to jest zorganizowane. Mamy 256 dost\u0119pnych shard\u00f3w. Dla ka\u017cdego bucketu przypisujemy zakres za pomoc\u0105 pewnej funkcji konsystentnej. To jest proste \u2014 tak samo, jak za pomoc\u0105 funkcji konsystentnej okre\u015blasz przynale\u017cno\u015b\u0107 do jednego sharda, okre\u015blasz startowy shard i przydzielasz zakres:<\/p>\n<p><\/p>\n<p><code>f(bucket, shards) = subset<\/code><\/p>\n<p><\/p>\n<p>To znaczy, \u017ce je\u015bli we\u017amiesz bucket, mo\u017cesz powiedzie\u0107, \u017ce on i jego dane zawsze b\u0119d\u0105 le\u017ca\u0142y na konkretnym podzbiorze wszystkich shard\u00f3w. To pozwala zredukowa\u0107 wp\u0142yw niekt\u00f3rych bucket\u00f3w na inne i upro\u015bci\u0107 prac\u0119 zapyta\u0144 map-reduce, gdy trzeba na przyk\u0142ad stworzy\u0107 listing obiekt\u00f3w bucketu. W tym celu trzeba zapyta\u0107 wszystkie shardy, na kt\u00f3rych te obiekty s\u0105 przechowywane. Gdyby obiekty le\u017ca\u0142y na wszystkich shardach, ka\u017cdy listing wp\u0142ywa\u0142by na ca\u0142y system, a tutaj wp\u0142ywa tylko na konkretny podzbi\u00f3r.<\/p>\n<p><\/p>\n<p>Dalej \u2014 ka\u017cdy obiekt nale\u017cy do konkretnego bucketu, wi\u0119c gdy zwracamy si\u0119 o obiekt, to pytamy o obiekt po nazwie w konkretnym bucketcie. To znaczy, \u017ce mo\u017cemy okre\u015bli\u0107 funkcj\u0119 dla obiektu nie z ca\u0142ego dost\u0119pnego zakresu shard\u00f3w, a tylko z podzbioru jego bucketu:<\/p>\n<p><\/p>\n<p><code>f(object, subset) = shard<\/code><\/p>\n<p><\/p>\n<p>Bierzemy konkretny obiekt, jako argumenty funkcji przekazujemy tam nie wszystkie shardy, a podzbi\u00f3r jego bucketu \u2014 i otrzymujemy konkretny shard. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Architektura S3: 3 lata ewolucji Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/10480ad2430c228c511ff3cdc5071596.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Zatem shardowanie zosta\u0142o zrealizowane, istnieje proxy sharduj\u0105ce. Nast\u0119pnie zostaje z routera i bazy danych metadanych korzysta\u0107 z proxy sharduj\u0105cego. Na przyk\u0142ad do tworzenia obiekt\u00f3w kopii zapasowych \u2014 gdy tworzymy bucket, g\u0142\u00f3wne magazynowanie musi stworzy\u0107 przedstawiciela tego bucketu na wszystkich shardach, na kt\u00f3rych powinien by\u0107 obecny.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Architektura S3: 3 lata ewolucji 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\">Jak zrealizowali\u015bmy resharding<\/h2>\n<p><\/p>\n<p>Najwi\u0119kszym problemem shardingu jest resharding. Wa\u017cne by\u0142o dla nas, aby zrobi\u0107 to bez przestoj\u00f3w, poniewa\u017c system ju\u017c dzia\u0142a\u0142 w produkcji. Poka\u017c\u0119, jak rozwi\u0105zali\u015bmy ten problem na przyk\u0142adzie podobnego zadania z \u017cyw\u0105 migracj\u0105 danych z jednego projektu do drugiego.<\/p>\n<p><\/p>\n<p>Poni\u017cej znajduje si\u0119 schemat naszego klastra, kt\u00f3ry powsta\u0142 po wdro\u017ceniu shardingu. Mamy nginx, API S3, router, baz\u0119 primary z projektami, proxy sharduj\u0105ce oraz same shardy.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Architektura S3: 3 lata ewolucji Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/0e6bd16c7fc47437b3b7d96b6d9809a4.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Powy\u017cej pomin\u0105\u0142em, \u017ce na pewnym etapie projektu by\u0142 produktowy cel: \u201eUruchomi\u0107 jeszcze jedno repozytorium, Icebox, jako Hotbox, tylko dla zimnych danych\u201d. W zasadzie to takie samo repozytorium, ale pod innymi adresami URL i bez pami\u0119ci podr\u0119cznej.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Architektura S3: 3 lata ewolucji Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/9ce9085e1d03e9a99b6b8ccc0717c653.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Icebox by\u0142 u\u017cywany rzadziej ni\u017c Hotbox, dlatego d\u0142ugo obywa\u0142 si\u0119 bez jakiegokolwiek shardingu. Ostatecznie zdecydowali\u015bmy si\u0119 z niego zrezygnowa\u0107 i po\u0142\u0105czy\u0107 Hotbox i Icebox w jeden serwis, oddzielaj\u0105c jedynie klasy przechowywania. <\/p>\n<p><\/p>\n<p>Koszyki w repozytoriach nie si\u0119 krzy\u017cowa\u0142y, mo\u017cna je by\u0142o \u0142atwo po\u0142\u0105czy\u0107 i przenie\u015b\u0107, ale klienci korzystali zar\u00f3wno z jednego, jak i z drugiego repozytorium, wi\u0119c musieli\u015bmy rozwi\u0105za\u0107 problem braku przestoj\u00f3w. Nie mo\u017cna by\u0142o po prostu wy\u0142\u0105czy\u0107 i skopiowa\u0107. Przeprowadzili\u015bmy migracj\u0119 w kilku etapach.<\/p>\n<p><\/p>\n<p>Na pocz\u0105tek zsynchronizowali\u015bmy primary-repozytoria. Mieli\u015bmy Tarantoola i mogli\u015bmy przy tworzeniu obiekt\u00f3w zrobi\u0107 to w ten spos\u00f3b: <\/p>\n<p><\/p>\n<ul>\n<li>do bazy przychodzi \u017c\u0105danie utworzenia koszyka, na przyk\u0142ad w Hotbox;<\/li>\n<li>Tarantool sprawdza w innej bazie (w tym przypadku w Icebox), \u017ce taki koszyk nie istnieje;<\/li>\n<li>je\u015bli koszyk istnieje, baza informuje, \u017ce nie mo\u017cna go utworzy\u0107, a zosta\u0142 zsynchronizowany jako istniej\u0105cy.<br \/>\n<img decoding=\"async\" alt=\"Architektura S3: 3 lata ewolucji Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/6694c9804f09942416c1717b455b9fd3.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<em>Synchronizacja koszyk\u00f3w<\/em><\/li>\n<\/ul>\n<p><\/p>\n<p>W tym repozytorium, kt\u00f3re mia\u0142o przyj\u0105\u0107 wszystkie dane, wprowadzili\u015bmy oznaczenie dla projekt\u00f3w i koszyk\u00f3w, kt\u00f3re m\u00f3wi\u0142o, gdzie przechowywany jest ten obiekt. M\u00f3g\u0142 on by\u0107 przechowywany lokalnie, to znaczy w Hotbox, w Icebox \u2014 wtedy w nowym repozytorium nie ma \u017cadnych danych, lub m\u00f3g\u0142 by\u0107 w stanie migracji.<\/p>\n<p><\/p>\n<p>Je\u015bli dla projektu lub koszyka ustawiono oznaczenie Migrating, to podczas migracji \u017c\u0105danie wykonywano najpierw w nowym repozytorium, w kt\u00f3rym dane mia\u0142y si\u0119 znajdowa\u0107, a je\u015bli ich tam nie by\u0142o, to \u017c\u0105dania by\u0142y kierowane do alternatywnego repozytorium.<\/p>\n<p><\/p>\n<p>Nast\u0119pnie prze\u0142\u0105czyli\u015bmy ruch. Poniewa\u017c API mog\u0142o obs\u0142ugiwa\u0107 zar\u00f3wno \u017c\u0105dania Icebox, jak i \u017c\u0105dania Hotbox, mogli\u015bmy bez przestoj\u00f3w prze\u0142\u0105czy\u0107 ruch, po prostu przenosz\u0105c hosty i dodaj\u0105c odpowiednie wpisy w Nginx. <\/p>\n<p><\/p>\n<p>Po przekierowaniu ruchu, Nginx i API od Icebox mog\u0142y zosta\u0107 usuni\u0119te.<br \/>\nNast\u0119pnie usun\u0119li\u015bmy Icebox nginx i S3 API \u2014 i wszystko zacz\u0119\u0142o dzia\u0142a\u0107:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Architektura S3: 3 lata ewolucji Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/62d9f960fc1f11b875a8f8a5aa8e8152.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Potem uruchomili\u015bmy proces migracji w tle, kt\u00f3ry dzia\u0142a wewn\u0105trz bazy \u2013 przechodzi przez wszystkie projekty i ich kosze, ustawia dla nich oznaczenie Migrating, przenosi dane, a po zako\u0144czeniu przenoszenia ustawia oznaczenie Local.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Architektura S3: 3 lata ewolucji Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/1a3129136f7ccacfdcff260f10cb0605.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Po przeniesieniu danych nie potrzebujemy ju\u017c starego magazynu, wi\u0119c usuwamy pozosta\u0142e cz\u0119\u015bci starego systemu, a tak\u017ce usuwamy wsparcie statusu migracji z kodu.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Architektura S3: 3 lata ewolucji Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/13b6f11add40c21a3b9afc05dd0dfea9.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>W oparciu o te same zasady wykonali\u015bmy r\u00f3wnie\u017c resharding ze starego magazynu na sharded:<\/p>\n<p><\/p>\n<ul>\n<li>Oznaczyli\u015bmy wszystkie kosze jako <code>Non-sharded<\/code>. Wszystkie zapytania trafia\u0142y do oryginalnego, nieshardowanego magazynu.<\/li>\n<li>Nowe kosze by\u0142y tworzone od razu w statusie <code>Sharded<\/code>.<\/li>\n<li>Jedno po drugim brali\u015bmy kosze, ustalali\u015bmy status <code>Migrating<\/code> i przenosili\u015bmy dane.<\/li>\n<\/ul>\n<p><\/p>\n<p>Zapotrzebowanie by\u0142o obs\u0142ugiwane w nast\u0119puj\u0105cy spos\u00f3b:<\/p>\n<p><\/p>\n<ul>\n<li>Czytamy w nowym, potem w starym.<\/li>\n<li>Tworzymy tylko w nowym.<\/li>\n<li>Aktualizujemy dwuetapowo: je\u015bli w nowym nie ma, przenosimy z starego do nowego, potem aktualizujemy.<\/li>\n<\/ul>\n<p><\/p>\n<h2 id=\"rabota-s-ssl-sertifikatami\">Praca z certyfikatami SSL<\/h2>\n<p><\/p>\n<blockquote><p>Na froncie u\u017cywamy Nginx. W naszym przypadku to nie jest zwyk\u0142y Nginx, lecz OpenResty, Nginx z wsparciem LuaJIT.<\/p><\/blockquote>\n<p>Kolejny element systemu \u2014 praca z certyfikatami SSL. W magazynie S3 mo\u017cesz ustawi\u0107 w\u0142asn\u0105 domen\u0119 do dost\u0119pu do konkretnego kosza, po prostu korzystaj\u0105c z <code>CNAME<\/code>. Jednak, bez HTTPS w dzisiejszych czasach si\u0119 nie da: w\u0142asna domena oznacza w\u0142asny certyfikat SSL. <\/p>\n<p><\/p>\n<p>Jak ju\u017c m\u00f3wi\u0142em, za balansowanie i terminacj\u0119 SSL odpowiada Nginx. W naszym przypadku to nie jest zwyk\u0142y Nginx, lecz OpenResty, Nginx z wsparciem LuaJIT.<\/p>\n<p><\/p>\n<p>To pozwoli\u0142o nam do\u015b\u0107 \u0142atwo nauczy\u0107 nasz Nginx udost\u0119pnia\u0107 dowolne certyfikaty. Co wi\u0119cej, musieli\u015bmy udost\u0119pnia\u0107 certyfikaty dynamicznie (bez potrzeby wpisywania ich w pliku konfiguracyjnym). Skorzystali\u015bmy z rozszerzenia <code>ssl_certificate_by_lua<\/code>, kt\u00f3re umo\u017cliwia odczytanie certyfikatu z dowolnego \u017ar\u00f3d\u0142a bezpo\u015brednio podczas TLS handshake. Jako magazyn certyfikat\u00f3w r\u00f3wnie\u017c wykorzystali\u015bmy Tarantool: pozwala to na zarz\u0105dzanie certyfikatami z zewn\u0105trz i zapewnia niezwykle szybk\u0105 obs\u0142ug\u0119.<\/p>\n<p><\/p>\n<p>Zrealizowano r\u00f3wnie\u017c oddzielny demon, kt\u00f3rego zadaniem jest regularne aktualizowanie certyfikat\u00f3w wydanych przy u\u017cyciu Let's Encrypt.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Architektura S3: 3 lata ewolucji 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\">Co bym zachowa\u0142, a co zrobi\u0142 inaczej, gdybym projektowa\u0142 magazyn od nowa<\/h2>\n<p><\/p>\n<h3 id=\"chto-nuzhno-bylo-ispolzovat-s-samogo-nachala\">Co powinno by\u0107 u\u017cywane od samego pocz\u0105tku<\/h3>\n<p><\/p>\n<p><strong>Shardowanie od razu<\/strong>. Wiele problem\u00f3w sprawi\u0142 resharding. \u0141atwo to zrobi\u0107, jednak w przypadku projekt\u00f3w, kt\u00f3re potrzebuj\u0105 skalowania, lepiej od razu wzi\u0105\u0107 shardowany klaster, nawet na minimalnej liczbie w\u0119z\u0142\u00f3w. Wdro\u017cenie shardingu na starcie jest prawie darmowe w por\u00f3wnaniu do wprowadzenia shardingu w dzia\u0142aj\u0105cym systemie.<\/p>\n<p><\/p>\n<p><strong>Praca z Tarantool przez load balancery<\/strong>. Obecnie wszystkie nowe bazy od razu pod\u0142\u0105czamy do pracy przez load balancery. Umo\u017cliwia to rozszerzenie funkcjonalno\u015bci i osi\u0105gni\u0119cie wy\u017cszej odporno\u015bci na awarie. <\/p>\n<p><\/p>\n<p><strong>Auto failover<\/strong>. Zainstalowa\u0142bym wszystkie narz\u0119dzia potrzebne do auto failover, poniewa\u017c pierwsze niepowodzenia po uruchomieniu by\u0142y zwi\u0105zane z jego brakiem. Po do\u015bwiadczeniach z S3 wszystkie nast\u0119pne produkty by\u0142y uruchamiane z uwzgl\u0119dnieniem tego.<\/p>\n<p><\/p>\n<p><strong>Funkcja S3 \u201eWersjonowanie\u201d<\/strong>. Pocz\u0105tkowo wydawa\u0142o si\u0119, \u017ce to nie jest bardzo potrzebna funkcjonalno\u015b\u0107. Wbudowanie tej mo\u017cliwo\u015bci w architektur\u0119 dzia\u0142aj\u0105cego systemu jest niezwykle trudne.<\/p>\n<p><\/p>\n<p><strong>Osobne billing<\/strong>. To, jak zintegrowali\u015bmy billing z naszym systemem, dobrze sprawdzi\u0142o si\u0119 na pocz\u0105tku, ale p\u00f3\u017aniej zacz\u0119\u0142o przeszkadza\u0107, lepiej by\u0142oby go zainstalowa\u0107 jako ca\u0142kowicie oddzieln\u0105 us\u0142ug\u0119.<\/p>\n<p><\/p>\n<h3 id=\"chto-bylo-udachnym-resheniem\">Co by\u0142o udanym rozwi\u0105zaniem<\/h3>\n<p><\/p>\n<p><strong>Model danych<\/strong>. Historia pokazuje, \u017ce w miar\u0119 rozwoju us\u0142ugi dobrze trafiamy w model danych Amazona, dlatego mo\u017cemy wdra\u017ca\u0107 te funkcje, kt\u00f3re tam si\u0119 znajduj\u0105.<\/p>\n<p><\/p>\n<p><strong>Schemat shardowania<\/strong>. Popar\u0142bym podobne shardowanie w oparciu o kube\u0142ki, poniewa\u017c pozwala to dobrze rozdziela\u0107 zapytania z r\u00f3\u017cnych kube\u0142k\u00f3w po du\u017cym klastrze.<\/p>\n<p><\/p>\n<p><strong>U\u017cycie Tarantool<\/strong>. Tarantool znacznie pom\u00f3g\u0142 w rozwijaniu us\u0142ugi i jej modyfikacji, \u0142atwo pracowali\u015bmy z danymi, transformowali\u015bmy i shardowali\u015bmy magazyn, nie musieli\u015bmy wchodzi\u0107 na poziom aplikacji. <\/p>\n<p><\/p>\n<blockquote><p>Ta prezentacja pierwszy raz zosta\u0142a zaprezentowana na <noindex><a rel=\"nofollow\" href=\"https:\/\/corp.mail.ru\/ru\/press\/events\/databases-2\/\">@Databases Meetup<\/a><\/noindex> by Mail.ru Cloud Solutions&amp;Tarantool. Zobacz <noindex><a rel=\"nofollow\" href=\"https:\/\/www.youtube.com\/watch?v=jM4hL2u6JM0&amp;list=PLQzTaxmOHjntyNRPWhaWHqlHp8UN_wgQ3\">wideo<\/a><\/noindex> inne prezentacje i subskrybuj zapowiedzi wydarze\u0144 w Telegramie <noindex><a rel=\"nofollow\" href=\"https:\/\/t.me\/k8s_mail\">Wok\u00f3\u0142 Kubernetes w Mail.ru Group<\/a><\/noindex>.<\/p><\/blockquote>\n<p>Mo\u017cesz r\u00f3wnie\u017c obejrze\u0107 m\u00f3j stary wyk\u0142ad o S3 lub przeczyta\u0107 artyku\u0142 mojego kolegi na temat magazynu blokowego.<\/p>\n<p><\/p>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/www.youtube.com\/watch?v=O0iIADHgBVc\">In\u017cynieria wsteczna architektury Amazon S3 i to, jak wygl\u0105da\u0142 magazyn S3 MCS 3 lata temu<\/a><\/noindex>.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/mailru\/blog\/472694\/\">Wi\u0119cej ni\u017c Ceph: blokowe przechowywanie w chmurze MCS<\/a><\/noindex>.<\/li>\n<\/ul>\n<p>\u0179r\u00f3d\u0142o: <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.1.1 - 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\/pl\/blog\/administrirovanie\/arhitektura-s3-3-goda-evolyuczii-mail-ru-cloud-storage\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"pl_PL\" \/>\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\/pl\/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\udd47Architektura S3: 3 lata ewolucji Mail.ru Cloud Storage | ProHoster","description":"","canonical_url":"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/arhitektura-s3-3-goda-evolyuczii-mail-ru-cloud-storage","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"pl_PL","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\/pl\/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\/pl\/wp-json\/wp\/v2\/posts\/91090","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/comments?post=91090"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts\/91090\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/media\/91091"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/media?parent=91090"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/categories?post=91090"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/tags?post=91090"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}