1. Опис

Apache Cassandra — розподілена система управління базами даних, що належить до класу NoSQL-систем і розрахована на створення високомасштабованих та надійних сховищ величезних масивів даних, представлених у вигляді хешу.

Спочатку проєкт був розроблений у надрах Facebook, і в 2009 році його передали під крило фонду Apache Software Foundation, ця організація продовжує розвиток проєкту. Промислові рішення на базі Cassandra розгорнуті для забезпечення таких компаній, як Cisco, IBM, Cloudkick, Reddit, Digg, Rackspace, Huawei, Netflix, Apple, Instagram, GitHub, Twitter і Spotify. До 2011 року найбільший кластер серверів, що обслуговує єдину базу даних під керуванням Cassandra, налічував понад 400 машин та містив дані розміром понад 300 ТБ.

Написана мовою Java, реалізує розподілену хеш-систему, подібну до DynamoDB, що забезпечує практично лінійну масштабованість при збільшенні обсягу даних. Використовує модель зберігання даних на базі сімейства стовпців, чим відрізняється від систем, подібних до MemcacheDB, які зберігають дані тільки у зв'язці «ключ-значення», можливістю організувати зберігання хешів з кількома рівнями вкладеності.

Належить до категорії стійких до відмови СУБД: поміщені в базу дані автоматично реплікуються на кілька вузлів розподіленої мережі або навіть рівномірно розподіляються в декількох дата-центрах. У разі збою вузла його функції на льоту підхоплюються іншими вузлами, додавання нових вузлів у кластер та оновлення версії Cassandra проводиться на льоту, без додаткового ручного втручання та переконфігурації інших вузлів.

Проте дуже рекомендується заново згенерувати ключі (мітки) для кожного вузла, включно з існуючими, щоб зберегти якість розподілу навантаження. Генерацію ключів для існуючих вузлів можна уникнути у разі кратного збільшення кількості вузлів (у 2 рази, у 3 рази тощо).

2. Модель даних

У термінології Кассандри програма працює з простором ключів (keyspace), що відповідає поняттю схеми бази даних (database schema) у реляційній моделі. У цьому просторі ключів можуть бути кілька колонкових сімейств (column family), що відповідає поняттю реляційної таблиці.

У свою чергу, колонкові сімейства містять колонки (column), які об'єднуються за допомогою ключа (row key) у записі (row). Колонка складається з трьох частин: імені (column name), мітки часу (timestamp) та значення (value). Колонки у межах запису впорядковані. На відміну від реляційної БД, жодних обмежень на те, щоб записи (а в термінах БД це рядки) містили шпальти з такими ж іменами, як і в інших записах — немає.

Колонкові сімейства можуть бути кількох видів, але в цій статті ми опускатимемо цю деталізацію. Також в останніх версіях Кассандри з'явилася можливість виконувати запити визначення та зміни даних (DDL, DML) за допомогою мови CQL, а також створювати вторинні індекси (secondary indices).

Конкретне значення, яке зберігається в касандрі, ідентифікується:

  • простір ключів — це прив'язка до програми (предметної області). Дозволяє одному кластері розміщувати дані різних програм;
  • колоночним сімейством — це прив'язка до запиту;
  • ключем – це прив'язка до вузла кластера. Від ключа залежить які вузли потраплять збережені колонки;
  • ім'ям колонки — це прив'язка до атрибуту запису. Дозволяє в одному записі зберігати кілька значень.

З кожним значенням пов'язана мітка часу — число, яке задається користувачем, яке використовується для вирішення конфліктів під час запису: чим більше число, тим колонка вважається новішою, а при порівнянні перетирає старі колонки.

3. Типи даних

За типами даних: простір ключів та колонкове сімейство — це рядки (імена); мітка часу - це 64-бітове число; а ключ, ім'я колонки та значення колонки — це масив байтів. Також Кассандра має поняття типів даних (data type). Ці типи можуть за бажанням розробника (опціонально) задаватися під час створення колонкового сімейства.

Для імен колонок це називається порівнятелем (comparator), для значень та ключів — валідатором (validator). Перший визначає, які байтові значення допустимі для імен колонок і як їх упорядкувати. Другий — які байтові значення допустимі для значень колонок та ключів.

Якщо ці типи даних не вказані, то Кассандра зберігає значення і порівнює їх як байтові рядки (BytesType), оскільки, по суті, вони зберігаються всередині.

Типи даних бувають такими:

  • BytesType: будь-які байтові рядки (без валідації)
  • AsciiType: ASCII рядок
  • UTF8Type: UTF-8 рядок
  • IntegerType: число з довільним розміром
  • Int32Type: 4-байтове число
  • LongType: 8-байтове число
  • UUIDType: UUID 1-го або 4-го типу
  • TimeUUIDType: UUID 1-го типу
  • DateType: 8-байтове значення мітки часу
  • BooleanType: два значення: true = 1 або false = 0
  • FloatType: 4-байтове число з плаваючою комою
  • DoubleType: 8-байтове число з плаваючою комою
  • DecimalType: число з довільним розміром та плаваючою комою
  • CounterColumnType: 8-байтовий лічильник

У Кассандрі всі операції запису даних — це завжди операції перезапису, тобто якщо до колонкової сім'ї приходить колонка з таким же ключем і ім'ям, які вже існують, і мітка часу більша, ніж та збережена, то значення перезаписується. Записані значення ніколи не змінюються, просто приходять нові колонки з новими значеннями.

Запис до Кассандри працює з більшою швидкістю, ніж читання. Це змінює підхід, який застосовується під час проєктування. Якщо розглядати Кассандру з погляду проєктування моделі даних, то простіше уявити колонкове сімейство не як таблицю, а як матеріалізоване представлення (materialized view) — структуру, що представляє дані деякого складного запиту, але зберігає їх у диску.

Замість того, щоб намагатися скомпонувати дані за допомогою запитів, краще постаратися зберегти в колоночне сімейство все, що може знадобитися для цього запиту. Тобто підходити необхідно не з боку відносин між сутностями або зв'язками між об'єктами, а з боку запитів: які поля потрібно вибрати; у якому порядку повинні йти записи; які дані, пов'язані з основними, повинні запитуватись спільно — все це вже повинно бути збережено в колонкове сімейство.

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