etcd в сравнении с другими хранилищами ключей и значений
Название «etcd» образовано из двух идей: каталога Unix «/etc» и распределённых («d»istributed) систем. В «/etc» хранятся данные конфигурации одной системы, тогда как etcd хранит конфигурацию крупных распределённых систем. Поэтому распределённый («d»istributed) «/etc» называется «etcd».
etcd задуман как универсальная основа крупных распределённых систем. Такие системы не допускают split-brain и готовы ради этого пожертвовать доступностью. etcd хранит метаданные согласованно и отказоустойчиво. Кластер etcd предоставляет хранилище ключей и значений с высокой стабильностью, надёжностью, масштабируемостью и производительностью.
Распределённые системы используют etcd как согласованное хранилище ключей и значений для управления конфигурацией, обнаружения служб и координации работы. Многие организации строят на etcd производственные системы: планировщики контейнеров, службы обнаружения и распределённые хранилища данных. Распространённые шаблоны включают выбор лидера , распределённые блокировки и контроль работоспособности машин.
Сценарии использования
- Container Linux от CoreOS: приложения в Container Linux автоматически получают обновления ядра Linux без простоя. Container Linux координирует обновления через locksmith , реализующий распределённый семафор на etcd, чтобы одновременно перезагружалась только часть кластера.
- Kubernetes хранит в etcd конфигурацию для обнаружения служб и управления кластером; согласованность etcd критична для правильного планирования и работы служб. Сервер API Kubernetes сохраняет состояние кластера в etcd и использует API наблюдения для мониторинга и применения важных изменений.
Сравнительная таблица
Возможно, etcd уже кажется подходящим, но любое технологическое решение требует осторожности. Документацию написала команда etcd. Хотя сравнение должно быть беспристрастным, опыт и предпочтения авторов неизбежно склоняются в пользу etcd.
Таблица позволяет быстро сравнить etcd с популярными альтернативами. Подробности по каждому столбцу приведены в следующих разделах.
| etcd | ZooKeeper | Consul | NewSQL (Cloud Spanner, CockroachDB, TiDB) | |
|---|---|---|---|---|
| Примитивы конкурентности | RPC блокировок , RPC выборов , блокировки командной строки , выборы командной строки , рецепты на Go | Внешние рецепты curator на Java | Встроенный API блокировок | Редко , если вообще есть |
| Линеаризуемое чтение | Да | Нет | Да | Иногда |
| Многоверсионное управление конкурентностью | Да | Нет | Нет | Иногда |
| Транзакции | Сравнение полей, чтение, запись | Проверка версии, запись | Сравнение поля, блокировка, чтение, запись | В стиле SQL |
| Уведомления об изменениях | Исторические и текущие интервалы ключей | Текущие ключи и каталоги | Текущие ключи и префиксы | Триггеры (иногда) |
| Права пользователей | На основе ролей | ACL | ACL | Различаются (табличный GRANT , роли базы данных ) |
| API HTTP/JSON | Да | Нет | Да | Редко |
| Изменение состава | Да | >3.5.0 | Да | Да |
| Максимальный надёжный размер базы | Несколько гигабайт | Сотни мегабайт (иногда несколько гигабайт) | Сотни MB | Терабайты+ |
| Минимальная задержка линеаризации чтения | Сетевой RTT | Без линеаризации чтения | RTT + fsync | Барьеры часов (атомарные, NTP) |
ZooKeeper
ZooKeeper решает ту же задачу, что и etcd: координацию распределённых систем и хранение метаданных. Но при создании etcd учитывался инженерный и эксплуатационный опыт проектирования ZooKeeper. Эти уроки помогли etcd поддерживать крупные системы, такие как Kubernetes. Улучшения относительно ZooKeeper включают:
- динамическое изменение состава кластера;
- стабильное чтение и запись под высокой нагрузкой;
- модель многоверсионного управления конкурентностью;
- надёжное наблюдение за ключами без скрытой потери событий;
- примитивы аренды, отделяющие соединения от сеансов;
- API безопасных распределённых совместных блокировок.
Кроме того, etcd изначально поддерживает множество языков и фреймворков.
ZooKeeper использует собственный уникальный протокол Jute RPC, ограничивающий
языковые привязки
, тогда как клиентский протокол etcd основан на
gRPC
с привязками для Go, C++, Java и других языков. gRPC можно
сериализовать в JSON поверх HTTP, поэтому с etcd работают даже утилиты вроде
curl. Системы строятся на etcd с естественными инструментами выбранного стека.
Новым приложениям, которым нужно согласованное хранилище ключей и значений, с учётом возможностей, поддержки и стабильности лучше выбрать etcd вместо ZooKeeper.
Consul
Consul — комплексная среда обнаружения служб со встроенными проверками состояния, обнаружением отказов и DNS. Она также предоставляет хранилище ключей и значений через RESTful API HTTP. В Consul 1.0 операции с ключами масштабировались хуже etcd и ZooKeeper: миллионы ключей приводили к высоким задержкам и давлению на память. В API отсутствуют многоверсионные ключи, условные транзакции и надёжные потоковые наблюдения.
etcd и Consul решают разные задачи. Для распределённого согласованного хранилища лучше etcd. Для комплексного обнаружения служб кластера возможностей etcd недостаточно; выберите Kubernetes, Consul или SmartStack.
NewSQL (Cloud Spanner, CockroachDB, TiDB)
И etcd, и базы NewSQL, например Cockroach , TiDB и Google Spanner , обеспечивают строгую согласованность при высокой доступности. Но различия архитектуры приводят к разным клиентским API и характеристикам.
Базы NewSQL горизонтально масштабируются между центрами обработки данных. Они разделяют терабайты данных между несколькими, иногда удалёнными, согласованными группами репликации (шардами). Из-за ожидания часов и локализованных графов зависимостей обновлений они плохо подходят для распределённой координации. Данные организованы в таблицы с более богатым SQL, чем у etcd, ценой сложности обработки, планирования и оптимизации запросов.
Итого: для метаданных и координации распределённых приложений выбирайте etcd. Для объёмов более нескольких GB или полноценных запросов SQL выбирайте NewSQL.
Использование etcd для метаданных
etcd реплицирует все данные в одной согласованной группе. Для нескольких GB с согласованным порядком это наиболее эффективно. Каждому изменению состояния кластера присваивается глобальный уникальный возрастающий идентификатор — ревизия. Поскольку группа репликации одна, для фиксации запрос проходит только протокол Raft. Один консенсус обеспечивает согласованность, низкую задержку и высокую пропускную способность при простом протоколе.
Репликация etcd не масштабируется горизонтально без шардирования. NewSQL обычно распределяет терабайты данных между несколькими согласованными группами. Чтобы назначить каждому изменению глобальный возрастающий ID, запрос проходит дополнительную координацию между группами. Возможные конфликты ID заставляют повторять упорядоченные запросы, усложняя систему и обычно снижая производительность строгого порядка относительно etcd.
Если приложение в основном работает с метаданными и их порядком для координации процессов, выбирайте etcd. Для крупного хранилища между несколькими ЦОД без сильной зависимости от глобального порядка выбирайте NewSQL.
Использование etcd для распределённой координации
etcd изначально предоставляет наблюдения, аренды, выборы и распределённые совместные блокировки. У блокировок есть неочевидные свойства, описанные ниже. Примитивы сопровождают разработчики etcd; перенос их во внешние библиотеки оставляет базовую распределённую систему неполной. В NewSQL их обычно реализуют третьи стороны, у ZooKeeper есть независимая библиотека рецептов, а Consul предупреждает, что его встроенный API блокировок — «не безупречный метод ».
Теоретически такие примитивы можно построить над любым строго согласованным хранилищем. Но алгоритмы тонки: кажущаяся рабочей блокировка внезапно ломается из-за эффекта лавины запросов и рассинхронизации времени. Другие примитивы, например транзакционная память, зависят от модели MVCC etcd; одной строгой согласованности недостаточно.
Для распределённой координации etcd снижает эксплуатационные риски и экономит инженерные усилия.
Примечания об использовании блокировок и аренд
etcd предоставляет API блокировок на основе механизма аренды и его реализации в etcd . Сервер выдаёт клиенту токен — аренду — с TTL и отзывает её после истечения времени. Пока клиент держит неотозванную аренду, он может заявлять владение связанным ресурсом; в etcd это ключ. Но сами API блокировок не обеспечивают взаимное исключение. Название lock сохранено по историческим причинам ; ниже показано, как API оптимизирует механизм взаимного исключения.
Главное свойство аренды: TTL — физический интервал времени, который сервер и клиент измеряют собственными часами. Поэтому сервер может отозвать аренду, пока клиент всё ещё считает себя владельцем.
Следовательно, сама аренда не гарантирует взаимное исключение, а владение арендой не гарантирует удержание блокировки ресурса.
Для ключей etcd взаимное исключение реализуется проверкой номера версии (в
других системах — compare-and-swap). В RPC Put и Txn задаются условия по
ревизии и идентификатору аренды. При невыполнении условий операция завершается
ошибкой. Клиент знает, что получил блокировку ключа, когда кластер etcd успешно
завершил его запрос.
Подобные схемы описаны в литературе:
- в статье о Chubby вводится sequencer, приблизительно соответствующий сочетанию ревизии и ID аренды etcd;
- в How to do distributed locking Martin Kleppmann вводит fencing token, которому в etcd соответствует ревизия;
- в Practical Uses of Synchronized Clocks in Distributed Systems описана распределённая блокировка Thor на проверке версии и аренде.
Аренды нужны даже при проверке версий, поскольку уменьшают число прерванных запросов.
Ключи etcd эффективно блокируются благодаря аренде и проверке версии. Внешние ресурсы должны сами предоставлять проверку версий и согласованность реплик, подобную ключам etcd. Блокировки etcd не могут непосредственно защищать внешние ресурсы.