Google Cloud Spanner: огляд можливостей та перші враження від бази даних

Привіт! Мене звуть Роман Нога, я працюю Software Engineer у EPAM Ukraine (Львів). Вже не перший рік цікавлюся та слідкую за розробками інженерів Google. Хочу поділитися своїми дослідженнями можливостей Cloud Spanner. Хочу одразу зазначити, що наразі досвіду в продакшені з Cloud Spanner у мене немає. У статті поділюся враженнями від знайомства із сервісом і буду радий коментарям тих, хто має реальний досвід роботи зі Spanner.

Коротко про Google Cloud Spanner

У 2017 році Google анонсував Cloud Spanner як першу горизонтально масштабовану послідовну реляційну базу даних. Він був розроблений інженерами Google для внутрішніх сервісів корпорації і зараз використовується для Google+ і Gmail. Також заявлено, що Spanner дозволяє системі масштабуватись на мільйони обчислювальних вузлів через сотні дата-центрів і працювати з трильйонами рядків даних. Мене дуже зацікавили такі обіцянки, і я вирішив розібратись трошки глибше. Звісно, я не використовував таких великих обсягів даних, як згадано вище, але результати роботи Spanner мені дуже сподобались. До того ж, як і інші сервіси Google, Spanner має дуже зручну веб-консоль для створення таблиць, надає безліч репортів про використання бази та рекомендацію, коли потрібно маштабуватись. Отже, мені сподобалось експериментувати зі Spanner, тому вирішив написати про нього.

Проблеми скейлінгу

Зазвичай зі зростанням кількості користувачів з’являються проблеми з базою. Кількість запитів зростає, і настає момент, коли збільшується перформанс. Які шляхи вирішення цієї проблеми?

Можна використовувати існуючі технології кластеризації, такі як XtraDB або Vitess для MySQL і CitusDB для Postgres. Це може вирішити проблему, але також може частково не відповідати потребам проекту, принести додаткові складнощі та витрати на підтримку, або взагалі доведеться робити редизайн аплікації.

Також можна використати горизонтальне масштабування NoSQL. Для цього застосовуємо, наприклад, Cassandra, HBase, MongoDB, DynamoDB та BigTable. Тут слід пам’ятати, що ми позбуваємось деяких реляційних функцій, таких як JOIN, які приводять до того, що параметри запиту стають більш обмеженими. База даних, яка розміщена на хості, може бути виграшним рішенням в плані підтримки, однак перехід на NoSQL може бути неможливим через редизайн аплікації із сотнями таблиць і запитів.

Яке рішення пропонує Google

Spanner — горизонтально масштабована послідовна служба реляційних баз даних:

  • Повністю керована DBaaS з горизонтальним масштабом та автоматизованим шарінгом даних.
  • Традиційна модель реляційної семантики та послідовності: схеми, ACID транзакції, SQL.
  • Автоматична синхронна реплікація в межах та між регіонами.
  • Стандартний SQL.
  • Моніторинг, логування, IAM.
  • Клієнтські бібліотеки популярних мов (Java, Python, Go, C#, Node.js тощо).
  • JDBC драйвер для підключення до популярних сторонніх інструментів.

Spanner використовує Colossus (GFS нового покоління) як шар зберігання (storage) і алгоритм вирішення колізій Paxos. Дані в Spanner зберігаються в таблицях, які мають схему. Всі дані мають часову мітку (timestamp), що важливо для реалізації підтримки мультиверсійності даних.

Початок роботи зі Spanner

Google надає 300 у. о. на рік під час реєстрації усім для використання всіх своїх сервісів. Цього насправді більш, ніж достатньо, щоб розібратись і спробувати попрацювати з Spanner-ом та іншими сервісами. Після реєстрації в консолі ми можемо створити наш інстанс, де ми вказуємо ім’я інстансу, ID, регіон та кількість нодів, які ми хочемо.
Після створення інстансу формуємо нашу базу даних. Для цього ми вказуємо ім’я нашої бази та починаємо створювати схему бази.

Перед початком роботи з базою нам необхідно все «засетапити». Google надає туторіал для різних популярних мов програмуванні. Після сетапу, у випадку .NET, нам необхідно заінсталювати Google.Cloud.Spanner.Data через NuGet.

Далі все просто: створюємо connection string ($"DataSource=projects/{projectId}/instances/{instanceId}"), формуємо SpannerConnection та робимо звернення до бази. Spanner підтримує всі необхідні запити, такі як: SELECT, JOIN, GROUP BY, HAVING.

Cloud Spanner підтримує прості типи даних, такі як INTEGER, а також більш складні типи — ARRAY та STRUCT. Максимальний розмір значення стовпця — 10 Мб.

Нововведеням в Spanner є interleaved table. Interleaved table використовується, коли необхідно мати доступ до рядків двох таблиць для заданого первинного ключа (кожен раз, коли ми отримуємо дані рядка одної таблиці, нам також потрібно отримати доступ до рядків другої таблиці), або іншими словами, це заміна звичайного foreign key. Буде корисним, наприклад, при CASCADE DELETE.

Для створення таких таблиць нам необхідно в таблиці, що наслідується від базової, вказати два PRIMARY KEY, нашої таблиці та батьківської.

CREATE TABLE Singers (
  SingerId   INT64 NOT NULL,
  FirstName  STRING(1024),
  LastName   STRING(1024),
  SingerInfo BYTES(MAX),
) PRIMARY KEY (SingerId);

CREATE TABLE Albums (
  SingerId     INT64 NOT NULL,
  AlbumId      INT64 NOT NULL,
  AlbumTitle   STRING(MAX),
) PRIMARY KEY (SingerId, AlbumId),
  INTERLEAVE IN PARENT Singers ON DELETE CASCADE;

Отримаємо такий вигляд:

Image source

Також Google гарантує, що всі зміни у схемі бази, наприклад, ALTER TABLE Singers ADD COLUMN Age INT64; будуть відбуватися на льоту (zero-downtime).

Такі заяви Google підтверджує тим, що Spanner тестувався більше 5 років на їхніх продуктах (GooglePlay, AdWords).

Як працює Google Spanner

На малюнку зображено інстанс з трьома нодами і трьома репліками в трьох зонах. У кожній зоні є повна копія даних. Кожна Cloud Spanner нода забезпечує 10 тисяч QPS запитів та 2 тисячі QPS записів і має ліміт в 2 TiB/ноду.

Є можливість моніторингу за допомогою Google Stackdriver. Ну і найцікавіше, для масштабування достатньо додати ноду. Як ми знаємо, якщо нода падає, вона піднімається автоматично за лічені секунди. Тому, якщо ми використовуємо більше ніж одну ноду для Spanner, наша база буде завжди онлайн.

Cloud Spanner використовує Data Splits:

— Primary Key розділений на спліти.
— Кожен спліт реплікується на зони.
— Кожен спліт має так званого лідера.
Кожен Split має свого лідера в кожній зоні.

Під час звернення до бази даних репліка запитує в лідера, чи має актуальні дані:

SELECT * FROM Table WHERE Name = ‘DOU’;

  1. Запит.
  2. Чи можна читати?
  3. Так.
  4. Відповідь.

На малюнку зображено, які кроки будуть відбуватись в типовій ситуації, коли ми щось читаємо, а потім пишемо щось на основі того, що вичитали.

  1. Читання.
  2. Лок.
  3. Відповідь.
  4. Запис.
  5. Запис в репліки.
  6. Підтвердження запису від реплік.
  7. Зняття локу.
  8. Відповідь.

TrueTime API

Реалізація транзакцій стала можлива завдяки програмному інтерфейсу TrueTime API. TrueTime API надає глобальний час та деяку невизначеність — TTinterval. Для розподілених систем дуже складно гарантувати миттєвість відгуку вузлів, що важливо для забезпечення узгодженості даних у розподіленому сховищі.

Коли замість точного часу повертається деяких часовий інтервал виконання двох конкурентних транзакцій, то порівнюються TTinterval цих транзакцій. Якщо TTinterval транзакцій не перетинаються, то ми можемо точно знати, яка з транзакцій повинна бути виконана перша. Якщо TTinterval перетинається, то визначити, яка транзакція має виконуватись перша, можна з певним ступенем ймовірності.

Рекомендація Google, коли використовувати Spanner

Звісно Google не рекомендує використовувати Spanner для всіх типів проектів. Найкраще використовувати його, якщо у нас є структуровані та реляційні дані та коли нам необхідне горизонтальне масштабування.

Недоліки та обмеження

Cloud Spanner не є дешевим. Очевидно, що через ціну він не підійде на будь-який проект.

Cloud Spanner рекомендує використовувати interleaved table для перформенсу та для каскадного оновлення та видалення. В іншому випадку каскадні операції не будуть виконуватись.

Ключі таблиці не можуть змінюватися. Ми не можемо додавати key column до існуючої таблиці або видалити з існуючої таблиці. Це означає, що якщо ми хочемо змінити PK таблиці, то нам доведеться дропнути та створити заново цю таблицю.

Перенесення ворклоаду, наприклад з MySQL, вимагає великих зусиль, як у дизайні, так і в імплементації, для забезпечення ефективної реалізації. Помилки в дизайні схеми можуть призвести до даунтаймів.

Підсумки

Google Spanner є новим типом БД (NewSQL), який об’єднує в собі два світи SQL та NoSQL. Він надає можливість для обробки величезної кількості транзакцій. При цьому гарантує цілісність даних з можливістю їх розподілення по всьому світі без обмежень розміром сховища, що вражає. Хоча наразі технологія має відносно невеликий список клієнтів та побудованих на її основі сервісів, але вона заслуговує на увагу широкого кола ІТ-спеціалістів.

Корисні посилання

Google Cloud Spanner
Spanner. NewSQL хранилище от Google
Google запустила бета-версию Cloud Spanner — СУБД поколения NewSQL
Работа с временем в Google
Introducing Cloud Spanner: a global database service for mission-critical applications

Все про українське ІТ в телеграмі — підписуйтеся на канал DOU

👍ПодобаєтьсяСподобалось0
До обраногоВ обраному1
LinkedIn



23 коментарі

Підписатись на коментаріВідписатись від коментарів Коментарі можуть залишати тільки користувачі з підтвердженими акаунтами.

Походу, щось типу версійника з горизонтальним масштабуванням. Так, навскидку, два рівня транзакцій, FK як таких немає (можна об’явити таблицю чайлдом, тоді вона буде зберігатися разом з парентом — Cloud Spanner stores rows in sorted order by primary key values, with child rows inserted between parent rows that share the same primary key prefix), заморочки з PK (бажано хеш, бо — Cloud Spanner divides data among servers by key ranges і без нього ) . Хз як працює оптимізатор (рекомендується прописувати secondary indexes руками в SQL-запити, бо — Cloud Spanner chooses an index automatically only in rare circumstances. In particular, Cloud Spanner does not automatically choose a secondary index if the query requests any columns that are not stored in the index. І т.д. і т.п. SLA класно прописаний — а-ля „якщо ми його не будемо дотримуватись, зробимо вам скидку на наступні періоди користування системою”
P.S.
Із репортів, я так розумію, є Optiva
www.zdnet.com/...​-to-google-cloud-spanner
і Redknee,
www.newswire.ca/...​-customers-660527343.html
останні взагалі пишуть „For example, with our largest Oracle database, we’ve processed 50K transactions per second, while on Cloud Spanner, we’ve reached north of 500K,” said Danielle Royston, CEO, Redknee. „This allows us to significantly improve performance for our customers, with a dramatically reduced total cost of ownership.”

кратко просуммирую: ниочем

Вы кратко гоните.
Сама по себе SQL база с автоматическим горизонтальным масштабированием это уже заметное достижение, а если она доступна за относительные копейки — тем более.
Предыдущие доступные средства или были без привычного SQL (Riak, Cassandra, облачные S3/Dynamo/etc.-like хранилища), или не имели адекватного шардинга от слова «вообще», или требовали сложной ручной настройки и стоили бразиллионы денег (Оракловские кластера SQL).

Хотя какие-то реальные цифры хотелось бы увидеть, а также типовые грабли. Можно ли, например, подсказывать шаблоны распределения данных? Это уже вопрос к автору статьи.

так, багато просили реальні дані, тому я підготую тестовий проект і розпишу більш детальніше.

Во-первых научитесь понимать контекст: это сама статья ниочем, а технология неплохая в целом. Во-вторых если вы не знаете о существовании подобных технологий это не значит что их нет. Назову парочку: Apache Ignite, MemSql, AWS Redshift/Snowflake

это сама статья ниочем, а технология неплохая в целом.

Предположим, что вы вводите такой контекст, но не соглашусь — статья вполне достаточная для тех, кому важно, чтобы начать копать.

MemSql

Стоит дороговато, по отзывам. Жёсткое разделение на хранимое в памяти и на диске.

Apache Ignite

Не вижу дублирования хранимых данных в распределённом варианте. Хорошо спрятали?
Что у гугла есть такое дублирование — общеизвестно.

AWS Redshift/Snowflake

Завязано на Amazon. Да, Spanner завязан на Google, но тем, кто на нём хостится, амазон как-то мало в тему.

Пока что — всё не то, какие-то лягушки ©.

Вы несете чушь, клауд спаннер тоже не дешев и опыт работы с гугл подсказывает мне что граблей и ограничений там тоже достаточно будет. Вопрос фич цены и надежности заставляет многих юзать разных вендоров безотносительно где хостится основная часть серверов. Ну и курите доки — Ignite опционально поддерживает реплики для prtitioned схеми, да и что тут сложного то. А про статью — это провал, ноль информации проще вайтпейпер прочитать на сайте гугла.

Paxos — это алгоритм достижения консенсуса в распределенной системе, a не

алгоритм вирішення колізій

Рекомендую почитать оригинальный пейпер Лесли Лэмпорта «The Part-Time Parliament».

мультипаксос используется для согласования значения дистрибьютед лога (это, кстати, не самый лучший вариант), что само по себе не допускание коллизий. Не придирайтесь к словам.

Ну і поради у вас :D
~40 сторінок формальних визначень та доведень. Занадто академічно. Лампорт навіть спростив цей пейпер, бо важкувато він заходив аудиторії і опублікував «paxos made simple». imho з цього краще починати

алгоритм вирішення колізій Paxos.

про які колізії йдеться?

Всі дані мають часову мітку (timestamp), що важливо для реалізації підтримки мультиверсійності даних.

це про кортежі чи інший рівень абстракції?

Було б дуже цікаво невдовзі побачити результат цього jepsen.io тесту :)

про які колізії йдеться?

Вот тут описано более детально: courses.cs.washington.edu/...​apers/corbett-spanner.pdf

У них данные храняться в абстракции под названием tablet, каждая таблет расположена в другом фолт домейне. Paxos юзается для того чтобы согласовать значения и порядок коммита в разные регионы, если я правильно помню этот пейпер

ок, перегляну пейпер, дякую! Ну так, paxos там для узгодження replication log для різних регіонів.

ну так а я о чем:)

где-то в одной из лекций вот этого курса:

www.youtube.com/watch?v=I_G2K-f9U2s
courses.cs.washington.edu/courses/csep552/18wi

обсуждается более детально что это и для чего.

обов’язково зроблю. Дякую

Spanner підтримує всі необхідні запити, такі як: SELECT, JOIN, GROUP BY, HAVING.

А как же update, delete, insert?

або іншими словами, це заміна звичайного foreign key.

То есть, это кластеризация двух отношений с поддержкой каскадных удалений.
А если нужен внешний ключ без кластеризации, для контроля целостности, что делать?
А если нужно изменить первичный ключ/дополнить/создать дополнительные уникальные ключи?
А если нужно делать запросы к таблицам, которые не кластеризованы и при этом подразумеваются сложные соединения, как достигать приемлемой производительности?

Интересно было бы увидеть какие-то тесты производительности на разного типа нагрузке, если есть такие тесты в свободном доступе или может автор сам уже проводил такие тесты?

А как же update, delete, insert?

Тут еще можно отметить, что join, group by, having — это не запросы.

ну и где данные реального теста с 10 нодами например? Время транзакции, количество? 2к записей на ноду это вобщето меньше, чем mysql дает на ssd, намного меньше.
При описанной структуре запроса вам прийдется при 100 нодах получить 100 подтверждений. Както неочень, не?

На самом деле для горизонтального скалинга хуже всего ситуация, когда у вас 100 нод по 10к чтений, а потом одна нода делает транзакцию на 20 секунд, каждые 0.01секунды повторяет. Как этот тут решается?

дякую за комент, а можна уточнити яка конфігурація mysql про яку ви написали?

innodb, 32Gb ram, vultr.com baremetal(xeon 1270-v6, ssd INTEL SSDSC2BB240G6). в среднем выдает около 4500 на запись. sync включен. Это последний проект. В общемто до 10к транзакций на запись и до сотни на чтение можно вытянуть на mysql.

Естественно, я имею в виду mysql на единичной машине. Скалится он не очень. Вы ведь пишите про технологию, которая типа масштабируется. А по факту никаких тестов масштабирования не выполняете. Просто перепечатка гугла? А смысл?

Мне кажется вы сравниваете теплое с мягким. В данном случае основная трабла в использовании паксоса. Разные его варсии требуют 2-3 RTT per ballot round, так как реплики находятся в разных фолт доменах(на разных машинах далеко друг от друга). В случае mysql у вас ничего такого нет, но у вас есть availability risk.

Кроме того приведенный перфоманс это per tablet, таблеты могут автоматически разбиваться при достижении определенного размера или при определенной нагрузке, что удваивает их перфоманс.

пропустил

В данном случае основная трабла в использовании паксоса. Разные его варсии требуют 2-3 RTT per ballot round,

что довольно таки долго,

так как реплики находятся в разных фолт доменах

Підписатись на коментарі