Schemaless для Uber.
Несколько лет назад компания Uber отказалась от монолитной базы данных Postgres.
Критически важные данные о поездках были перенесены в собственную базу данных, известную как Schemaless.
По заявлению Uber, Schemaless является масштабируемым и отказоустойчивым хранилищем данных.
Однако Schemaless представляет собой обертку, построенную поверх MySQL.
Но что же делает ее такой удивительной?
Ответ кроется в архитектуре Schemaless.
Schemaless имеет два типа узлов:
✅ Рабочие узлы
✅ узлы хранения данных
Задача рабочих узлов состоит в том, чтобы получать запросы от клиентов, распределять их по узлам хранения и агрегировать результаты.
На узлах хранения хранятся собственно данные.
Сами данные разделены на фиксированное количество шардов.
Вот как выглядит схема на высоком уровне:
“Зачем нужны два отдельных типа узлов?” – спросите вы.
Потому что наличие отдельных узлов позволяет Uber масштабировать каждую часть независимо.
Каждый шард сопоставляется с определенным узлом хранения.
Кроме того, каждый шард реплицируется на некоторое количество узлов хранения.
Их количество (коэффициент репликации) можно регулировать с помощью конфигурации.
Например, типичный коэффициент репликации включает 3 узла – один основной и две реплики.
Узлы-реплики распределяются по нескольким центрам обработки данных для обеспечения избыточности данных в случае сбоя.
См. приведенный ниже пример:
Но что происходит во время запросов на чтение и запись?
✅ Запросы на чтение
Когда к бессхемной БД поступает запрос на чтение, рабочий узел может считывать данные с любого узла хранения.
Клиент может настроить запрос на чтение с основного узла или узла-реплики.
По умолчанию выбирается первичный узел, гарантирующий согласованность чтения после записи.
По сути, это гарантия того, что если клиент произведет какие-то обновления, то он всегда будет видеть свои собственные обновления.
✅ Запросы на запись
Запросы на запись гораздо интереснее.
Падение реплики не влияет на запись.
Это связано с тем, что все записи идут на основной узел.
Но что делать, если основной узел не работает?
Schemaless по-прежнему принимает запросы на запись.
Однако данные сохраняются на диск на другом первичном узле, выбранном случайным образом.
Это обеспечивает доступность базы данных.
Но компромисс заключается в том, что последующие запросы на чтение не могут прочитать те, что были записаны ранее:
- первичный узел снова заработает
- Узел-реплика переводится в разряд основных.
Этот подход также известен как Buffered Writes.