масштабирование баз данных

common sense





Евгений Шишкин
DBA, wargaming.net
eshishki@gmail.com
— We define a DBMS as a complete software system used to define, create, manage, update and query a database.

© Gartner



 БД общего назначения, OldSQL: MySQL, PostgreSQL

 Специализированные, NewSQL: VoltDB, Vertica, Clustrix   

NoSQL: HBase, Cassandra, CouchDB, Aerospark, MongoDB


Scalability is a function


Мы хотим добавить ресурсов и работать быстрее или обрабатывать больше.

  • Amdahl's law
  • Gustafson-Barsis' Law
  • Neil J. Gunther's Universal Scalability Law

Amdahl's law

У нас есть алгоритм, который однопоточно работает за время T1.
Мы хотим добавить P процессоров и решить задачу быстрее.
Какое увеличение производительности S мы можем получить?

«В случае, когда задача разделяется на несколько частей, суммарное время её выполнения на параллельной системе не может быть меньше времени выполнения самого длинного фрагмента»

Amdahl's law


Ускорение ограничено той частью работы, которая не параллелизуется.
Например, если сериализованная часть алгоритма составляет только 0.1%, при 2048 процессорах ускорение будет только в 672 раза.

Gustafson-Barsis' Law


…speedup should be measured by scaling the problem to the number of processors, not by fixing the problem size.
— John Gustafson


В реальности, добившись нужного времени ответа системы, нас всё устраивает. И мы уже добавляем мощности под растущий размер, а не для сокращения латенси.  

Gustafson-Barsis' Law


Если объем данных увеличивается вместе с увеличением числа процессоров, а сериализовання часть растет медленно или фиксирована, ускорение растет пропорционально росту ресурсов.

Я ничего не понял


Разница в том, хотите ли вы ускорения при той же нагрузке или того же времени ответа при увеличении нагрузки.

В реальной жизни больше применим закон  Gustafson.

Но, если вам надо добиться более быстрой работы алгоритма при тех же данных, руководствуйтесь законом Амдала. 

Так какая же база масштабируется лучше?


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

Масштабирование это специализация.
Базы данных общего назначения в общем случае не масштабируются.

UNIVERSAL SCALABILITY LAW


Cost of sharing resources
Diminishing returns from contention
Negative returns from incoherency



Типичные профили нагрузки


  • oltp
  • short-request processing
  • web
  • olap/dwh

oltp


  • буква T это транзакции - забыли nosql сразу же
  • можно набить любимую базу данных до отказа памятью и ssd, но это будет печально и неэффективно
  • как нам сделать 500k TPS на одном сервере? никак
  • пошардили? добро пожаловать в дивный мир алгоритмов распределенного коммита

Почему всё так плохо работает? Вот redis же делает 200к на одном ядре!

OLTP

обычная база данных

OLTP

Прорывной ресерч H-Store http://hstore.cs.brown.edu/
Готовый продукт VoltDB

  • main memory database -> no buffer pool management
  •  каждому cpu свой кусочек памяти и однопоточное выполнение -> нет локов
  • вся работа в хранимых процедурах и куча ресерча ->
2pc иногда не нужен и во время ожидания можно выполнять другие транзакции

Подробнее тут http://hstore.cs.brown.edu/publications/ 

OLTP

Все основные сложности с распределенными транзакциями.
Рецепт - детерминизм.

Зная наперед в какой последовательности будут выполняться транзакции, у нас нет ожидания. База данных всегда делает полезную работу.

Подробности тут 
http://cs.yale.edu/homes/thomson/publications/calvin-sigmod12.pdf

short-request

PK/Index lookup

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

MySQL делает 200k rps, PostgreSQL 120k rps.
Невероятно, но редкая nosql система покажет такие числа.
Есть Mysql Cluster (NDB, не галера), есть Postgres-xc.
NoSQL, которые  AP, работают медленней CP.

WEB

  • short-request + joins + tons of order by + orm
  • 95%+ чтения
  • почти нет транзакций
  • небольшой объем горячих данных
  • data skew (zipfian distribution)

Нам хватает одного сервера, пока у него не кончается CPU.
MySQL Cluster, Postgres-xc, Pgpool и прочие шардят только по одному атрибуту.


WEB

Представьте себе табличку с постами 
create table thread_posts (
    post_id     bigint,
    thread_id   bigint,
    user_id     bigint,
    posted_on   timestamp,
    contents    text,
    primary key (thread_id, post_id),
    key (user_id, posted_on)
); 
И два популярных запроса:
select * from thread_posts where thread_id = 314 order by post_id;
select * from thread_posts where user_id = 546 order by posted_on desc limit 10;
Хочется пошардить и по thread_id, post_id и по user_id, posted_on
Выбирая только одно, далеко не уехать.

WEB

Нам надо:
  • отправлять запросы только туда, где лежат наши данные
  • избегать распределенных запросов
  • балансировать нагрузку

Хороший способ:
  • отвязать логическую схему от физической, чтобы шардить по разным атрибутам
  • использовать consistent hashing для балансирования данных
  • это сделано в Clustrix

WEB

Советики
чтобы избежать запросов на ноды, где данных нет
  • lookup таблица
  • bloom filter

  • можно шардить по двум атрибутам руками, делая две таблицы
  • можно денормализовать, помня про update, delete аномалии
  • можно материализовывать данные при записи (push модель) для сверхпопулярных пользователей (лента)

WEB

Если заморочиться
Проблема эффективного распределения данных по нодам это локальность данных и оверхед репликации данных.

Научный подход это положить данные вместе, не по хешу, а те, которые реально запрашиваются вместе.
  • Schism: a Workload-Driven Approach to Database Replication and Partitioning
  • The Little Engine(s) That Could: Scaling Online Social Networks

OLAP



  • огромный объем данных
  • огромные выборки
  • куча сортировок и джойнов
  • однотипные репорты
  • хорошо шардится
  • хорошо сжимается


OLAP



Можно:
  • пошардить руками
  • взять postgres-xc, mysql cluster, любой автоматический шардинг
  • и даже можно использовать materialized view (аля push)
  • и можно даже что-то денормализовать

OLAP


Нужно:
1. хранить данные в колонках
  • сжатие
  • векторизованный процессинг
  • эффективный доступ к данным
2. оперировать над сжатыми данными в памяти
3. делать row reconstructure только когда это необходимо
4. делать join индексы или prejoin проекции
5. хранить данные уже отсортированными (merge join бесплатный)

OLAP

Все эти "нужно" сделаны в Vertica.
Часть сделана в Cloudera Impala.

Greenplum не умеет column storage.
Oracle не умеет column storage.
NoSQL не умеет column storage.

DB2 и MSSQL умеют, но не MPP.

Половина NewSQL, которые про онлайн аналитику, это просто in memory базы. Очень часто даже без dictionary компрессии и RLE. 

SQL vs NOSQL

Представьте себе nosql базу данных, которая 
  • умеет secondary indexes
  • умеет эффективно выполнять часть запросов у себя
  • умеет транзакции
  • дает гарантии, когда это необходимо

Боже мой, да это же RDBMS!



Выводы

  • Используйте нужную базу данных для своей нагрузки
  • Не масштабируйте базу в отрыве от приложения
  • Если вы знаете, как решить свою проблему NoSQL базой, значит вы знаете, как решить проблему и в RDBMS
  • Не ленитесь думать и читать

Масштабирование баз данных

By eshishki

Масштабирование баз данных

  • 1,949