13 651
правка
Изменения
Нет описания правки
Доклад сделал мой день, самый интересный доклад первого дня. Ну, для меня. Очень уж хранилки всякие люблю.
Итак. Сначала почта у них хранилась, видимо, в Maildir-ах, ну или в своём аналоге, то есть ящик - ящик — это была папочка на диске, в которой отдельными файлами хранились все письма, плюс индексы. В среднем примерно 3 ТБ вложений на 1 ТБ писем. Горизонтально это масштабировалось норм, а вертикально не норм - предел - норм — предел — 4 ТБ HDD, больше юзать не получалось, т.к. так как iops-ы HDD с объёмом не растут (100-200 100—200 iops). ФС - ФС — очевидный оверхед: директории, иноды...иноды…
Так и масштабировались на 4 ТБ дисках, в итоге домасштабировались до 3000 серверов и стало дорого и неудобно. Захотелось снизить это число раз в 10. Для начала дизагрегировали из писем вложения, по этому поводу был отдельный доклад: [https://www.youtube.com/watch?v=O247Hq3ego4 Как смигрировать 50Пб в 32 без даунтайма? / Альберт Галимов, Андрей Сумин (Mail.ru)] с хайлоада 2016.
Хранилище назвали '''Zepto'''.
Вышло в общем-то очередное [https://www.usenix.org/event/osdi10/tech/full_papers/Beaver.pdf Haystack]/[https://github.com/chrislusf/seaweedfs SeaweedFS]/MDS-подобное хранилище. Примечание: MDS — объектный стородж Яндекса, про который шла речь в докладе Вадима выше и, например, в [https://habr.com/ru/company/yandex/blog/311806/ статьях на хабре], немного дурацкое название, так как в Ceph, Virtuozzo, LizardFS и других MDS называется Metadata Server, а у нас это весь сторадж.
Общие черты:
* Append-only volume-ыс переупаковкой. То есть, объекты хранятся в дописываемых всегда в конец больших файлах -томах вперемешку с заголовками.** Маленькое отличие: в zepto объекты нарезаются на странички , при удалении из тома сразу не удаляются, а только помечаются удалёнными - а потом, когда количество удалённого превышает определённый %, приходит отдельный процесс (называемый по 4 КБ вкусу compaction/defrag/gc/repack) и от каждой странички считается контрольная сумма crc32перезаписывает том целиком, на этот раз действительно удаляя удалённые объекты.** Чуть более интересное отличие Волюмы fallocate- это реализация удалений ятся, чтобы исключить фрагментацию места в zepto - это запись могилки (флага удаления) в конецФС.* Есть "шарды"«шарды», являющие собой группы из N (2, 3 или ещё скольки-то) таких томов на разных машинах, связанных репликацией вместе. То есть, запись идёт в пары или тройки томов.** В zepto, как я понялтерминологии Ceph шард — по сути, PG (placement group). В терминологии zepto - "бакет" (и сам томволюм тоже, видимо, и группа связанных репликацией томов называются называется "бакет" (bucket). Каждый бакет на каждой машине обслуживается отдельным процессом "bucketservice", слушающем на отдельном порту. В терминологии Ceph - аналог OSD.** Размер одного бакета - 2 ТБ. Таким образом, на одной машине живёт примерно до 60*18/2 = 540 bucketservice-ов (60 дисков по 18 ТБ в одной полке). - Клиент хранит ID шарда (бакета) у себя и для чтения объекта обращается к конкретному бакетушарду. Центральный сервер метаданных, знающий, какой объект где лежит, отсутствует.* Запись через page cache. fsync- ов после каждой записи и строгой консистентности формально нет. fsync просто раз в секунду выполняется в отдельном потоке, чтобы стимулировать сброс данных на диск. Но так как бешеные уборщицы не ходят по залу и не дёргают в произвольном порядке целые датацентры из розеток - данные не теряются.* Есть "прокси"«прокси», предоставляющие API доступа к хранилищу. У них они называются zeptoproxy и ставятся прямо на клиентские машины.- * Есть отдельный слой управления кластером и он же отвечает за балансировку записи. У mail.ru он называется statusservice.
Отличительные черты:
* Волюмы/бакеты.
** В zepto нет индексов (почти!). Объект идентифицируется прямо смещением внутри тома.
** А как же удаления, спросите вы, если смещение — это ID? А удаления реализуются через индекс удалений («индекс дырок»), добавляемый при сборке мусора. Видимо, вида «старое смещение → новое смещение». Ну такое… :) если сильно изрубить всё в труху удалениями, всё равно индекс большой получится.
** В zepto объекты нарезаются на странички по 4 КБ и от каждой странички считается контрольная сумма crc32.
** Размер одного бакета — 2 ГБ. Логично, ибо под смещение выделено 32 бита. Плюс ещё 32 бита - ID бакета. Соответственно, общий лимит места в zepto-кластере - 16 ЭБ, чего хватает с головой :)
** Бакеты складываются в 2 ТБ разделы дисков и один раздел (~1000 бакетов) обслуживается 1 процессом "bucketservice". В ноде 72 диска по 18 ТБ, но под Zepto на них обычно выделено только 4-6 ТБ, так что на одной машине живёт примерно 216 bucketservice-ов.
** Процесс-переупаковщик бакетов называется bucketcompactor.
* Распределение объектов - перед каждой записью идём в statusservice и спрашиваем у него, в какой бакет писать. При этом бакет на запись блокируется. При удалении аналогично, тоже блокировка.
* Консистентность удалений - если какой-то bucketservice лежит в момент удаления - другие сохраняют к себе запись типа "foreign delete", т.е. "данный объект был удалён в другом месте" и после его поднятия досылают ему записи удалений.
* Восстановление - тупое, только полным копированием тома на отсутствующие/повреждённые реплики.
<pre>