Еще раз про HBase

27 августа 2008 13 комментариев Иван Блинков

Некоторое время назад Neuronus в одном из комментариев к посту «Hadoop возвращается» не согласился с моим кратким определением HBase как «нереляционная база данных» (позаимствованным, собственно говоря, откуда-то с официального портала продукта). Этот факт подтолкнул меня попытаться найти более корректное определение в англоязычных источниках информации, получилось вполне успешно. Хочется прочитать более детально что к чему? Вперед!

Если Вам уже приходилось иметь дело с этой системой,возможно Вы уже поняли, что самым сложным этапом работы является просто-напросто осознавание того, чем она на самом деле является. Обычно приходится мысленно отказаться от всех привычек, доставшихся при работе с традиционный RDBMS, и начинать постигать базовые принципы организации хранения данных с нуля.

Стоит напомнить, что проект позиционируется как opensource реализация BigTable от Google. Да, проекты имплементированы разными людьми на разных языках программирования, но общие идеи и принципы функционирования у них сильно пересекаются. Наиболее значимой общей характеристикой у них является очень схожие модели данных (о чем упоминается в вики HBase), а в свою очередь в документации BigTable она описывается очень четко и определенно, точно определяя чем эти продукты по сути являются:

A Bigtable is a sparse, distributed, persistent multidimensional sorted map.

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

map

За этим термином нет четкого устоявшегося обозначения в русском языке (да и в английском тоже все далеко не так однозначно), математики обычно называют это отображением одного множества в другое, в то время как если Вы знакомы с программированием, то Вам наверняка больше знакомы будут более знакомы такие обозначения, как ассоциативный массив (PHP), словарь (Python), хэш (Ruby) или объект (JavaScript).

По сути же имеется ввиду просто набор однозначно соответствующих пар ключ-значение, в роли которых выступают массивы байт. Во все той же статейке в вики все очень наглядно демонстрируется примерами в нотации JSON, позволю себе тоже приводить аналогичные примеры. В JSON наш map выглядел бы следующим образом:

{
  "qqqq" : "some",
  "abc" : "sample",
  "zz" : "JSON",
  "123" : "map",
  "mnbvcxz" : "looks like this"
}

persistent

Это прилагательное обозначает всего лишь «постоянный», то есть в данном контексте оно говорит только о том, что данная система не зависит от использующих ее приложений, а также хранится на устройствах постоянного хранения данных, а не в оперативной памяти.

distributed

Распределенность этих систем можно рассматривать с двух точек зрения:

  • Как HBase, так и BigTable сами по себе могут функционировать на большом количестве серверов, которые можно разделить на две большие категории: master и slave. Slave сервера собственно выполняют всю работу с данными, а master — лишь только координируют их действия и управляют процессом в целом. Этот факт обеспечивают высокую степень устойчивости к сбоям (в HBase правда количество master-серверов ограничено одним, что представляет собой единственную точку, сбой в которой приведет к отказу всей системы, но это лишь временная проблема, которую наверняка устранят в следующих версиях), а также существенно облегчает масштабируемость всей системы так как добавление дополнительных серверов (а значит и увеличение производительности и вместительности системы) достаточно тривиально, безболезненно и не мешает общему ее функционированию.
  • Помимо этого каждая из этих систем обычно использует для хранения данных кластерную файловую систему (HBase — HDFS, а BigTable — GFS), которые тоже по своей природе являются распределенными и функционируют по схожему принципу, обеспечивая дополнительную сохранность данных, реплицируя их в нескольких экземплярах на нескольких серверах (обычно трех).

sorted

HBase и BigTable не строят никакие индексы для ускорения процесса извлечения данных, единственное используемое в них правило заключается в следующем: каждый slave-сервер в системе отвечает за определенный диапазон ключей (от и до определенных его значений), и держит все записи в строгом лексикографическом порядке по ключам (заметьте: сортировку значений никто не гарантирует!). Продолжая пример с JSON это выглядело бы примерно вот так:

{
  "123" : "map",
  "abc" : "sample",
  "mnbvcxz" : "looks like this",
  "qqqq" : "some",
  "zz" : "JSON"
}

Этим фактом можно активно пользоваться при планировании использовании системы, например если в качестве ключей планируется использовать доменные именные имена, то имеет смысл использовать их в «развернутом» виде, например: «com.example.www» вместо «www.example.com». Это почти наверняка обеспечит попадание всех поддоменов одного и того же домена на один slave-сервер, а также группировку доменов по зонам.

multidimensional

До сих пор ключ интерпретировался нами как нечто единое и неделимое, но на самом деле в данной ситуации это далеко не так. На самом деле пространство имен HBase и BigTable имеет несколько пространств, по аналогии с трехмерным материальным пространством, где есть ширина, высота и глубина. Если мы попытаемся представить это с помощью JSON, то это будет выглядеть как набор вложенных простых map'ов:

{
  "table-1":
  {
     "column-family-1":
     {
        "column-1":
        {
           "row-1":
           {
              "timestamp-1": "value-1",
              "timestamp-2": "value-2",
              "timestamp-3": "value-3"
           },
           "row-2":
           {
              "timestamp-1": "value-4",
              "timestamp-2": "value-5",
              "timestamp-3": "value-6"
           }
        },
        "column-2":
        {
           "row-1":
           {
              "timestamp-1": "value-1",
              "timestamp-3": "value-3"
           },
           "row-2":
           {
              "timestamp-1": "value-4",
              "timestamp-2": "value-5",
              "timestamp-3": "value-6"
           }
        }
     "column-family-2":
     {
        "column-1":
        {
           // ...
        },
        "":
        {
           "row-1": "some-value"
        }
        // ...
     }
     }
  }
}

Как можно увидеть из примера, таких пространств используется пять:

  • таблицы;
  • наборы столбцов;
  • столбцы;
  • строки;
  • время;

Таким образом, каждое значение в хранилище данных однозначно соответствует ключу, состоящему из пяти компонентов, например в примере значению «value-5» соответствует ключ, состоящий из:

  • table-1;
  • column-family-1;
  • column-1;
  • row-2;
  • timestamp-2;

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

Хочется обратить внимание, что ассортимент наборов столбцов (column family) указывается при создании таблиц, и изменения в них должны производиться с помощью специального запроса, в то время как сами столбцы являются динамическими и для его создания достаточно лишь добавить в него данные.

sparse

Развивая мысль предыдущего абзаца, можно понять, что наличие значения столбца в каждой строке вовсе не обязательно, оно запросто может и отсутствовать вовсе. Таким образом каждая строка может содержать произвольное количество значений для столбцов в рамках одной column family, ровно как может и не содержать их вовсе. Несуществующие данные не хранятся в виде какого-либо NULL-значения, они просто отсутствуют. Запрос на несуществующие данные просто вернет пустой результат. Если же взглянуть с другой стороны, то тот же самый факт можно представить и как возможность наличия пробелов в списке ключей строк.

И напоследок…

хочется сказать, что все это лишь дело терминологии, ровно то же самое можно подразумевать и под краткой фразой «нереляционная база данных», не смотря на то, что она существенно менее точна и полноценна. В данном контексте самое главное лишь чтобы люди просто понимали друг друга. Надеюсь после прочтения этого поста в вашем сознании сложилась четкая картина этого продукта и предоставляемых им возможностей, которая Вам пригодится как для «общего развития», так и для потенциального практического применения этого продукта. Если остались неясные моменты — смело оставляйте комментарии. Традиционная подписка на RSS — приветствуется :)

Метки: , , ,

  • http://jenyay.net Jenyay

    Вообще чтобы разобраться является ли база реляционной надо понять основана ли она на отношениях (собственно, откуда название и пошло).

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

    А вообще некоторые моменты, особенно persistent, напоминают объектную БД.

  • http://neuronus.blogspot.com Neuronus

    Благодарю за «разжовывание» :) это вполне очевидные, для специалистов, аспекты. Однако именно подобных «мелочей» и зачастую НЕ понимают технические начальники. Например, наше «техническое моск» до недавнего времени пребывало в полной уверенности, что с HBase можно работать ТАКЖЕ как и с любой RDBMS!!! И еще, приводили в «доказательство» наличие там HQL (типо похожего на SQL). Это реальный случай из жизни, когда именно неточная формулировка могла привести к необратимым последствиям. Отчасти по этой причине, я и комментировал в таком стиле :)

    P.S.

    Кстати, про адекватность представления данных из RDBMS формы в HBase пытаются написать: wiki.apache.org/hadoop/Hb...ataModel#example

  • Игорь Голодницкий

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

    Правда вот думаю о полнотекстовом поиске в данном случае. Чтобы отыскивать элементы, особенно по нескольким словам, непонятно как ограничиться одним сервером slavem. Выходит что при поиске Гугла, одним запросом занято сразу множество slave серверов ((

  • http://www.insight-it.ru Иван Блинков

    [quote comment="1124"]Вообще чтобы разобраться является ли база реляционной надо понять основана ли она на отношениях (собственно, откуда название и пошло).[/quote]Акцента на них не было как раз так как они не предусмотрены, по крайней мере на уровне самого хранилища данных.

    [quote comment="1125"]Благодарю за «разжовывание» :) это вполне очевидные, для специалистов, аспекты. Однако именно подобных «мелочей» и зачастую НЕ понимают технические начальники. Например, наше «техническое моск» до недавнего времени пребывало в полной уверенности, что с HBase можно работать ТАКЖЕ как и с любой RDBMS!!! И еще, приводили в «доказательство» наличие там HQL (типо похожего на SQL). Это реальный случай из жизни, когда именно неточная формулировка могла привести к необратимым последствиям. Отчасти по этой причине, я и комментировал в таком стиле :) [/quote]

    Ну из формата поста по-моему вполне очевидно, что он расчитывался не на специалистов, а как раз на тех, кто только начинает знакомиться с системами такого типа ;) .

    [quote comment="1126"]Правда вот думаю о полнотекстовом поиске в данном случае. Чтобы отыскивать элементы, особенно по нескольким словам, непонятно как ограничиться одним сервером slavem. Выходит что при поиске Гугла, одним запросом занято сразу множество slave серверов (([/quote]Да, в Google именно так оно и проиходит, и это «несколько» измеряется сотнями и тысячами — в одной из их презентаций был слайд на эту тему.

  • Green

    Для более полного понимания в статье не хватает примеров с запросами к хранимым данным

  • http://www.insight-it.ru Иван Блинков

    [quote comment="1150"]Для более полного понимания в статье не хватает примеров с запросами к хранимым данным[/quote]А смысл? При таких объемах данных основная работа как ни крути идет по API, а command line запросы предельно тривиальны и легко осваиваются за пару минут чтения help'а (при понимании общих принципов функционирования системы).

  • http://www.temoto.ru/ Сергей Шепелев

    Очепятка:

    целочисленного значения, обозначающего количество секунд**а** с начала эпохи

    Спасибо, Иван.

  • http://www.temoto.ru/ Сергей Шепелев

    [quote comment="1150"]Для более полного понимания в статье не хватает примеров с запросами к хранимым данным[/quote]

    Ровно тот же SQL. Только нет JOIN, вот и всё. Это в целом относится к любой нереляционной базе. Не конкретно к хадупу.

  • http://www.insight-it.ru Иван Блинков

    [quote comment="1189"]Очепятка:

    целочисленного значения, обозначающего количество секунд**а** с начала эпохи[/quote]Спасибо, исправил.

    [quote comment="1190"][quote comment="1150"]Для более полного понимания в статье не хватает примеров с запросами к хранимым данным[/quote]

    Ровно тот же SQL. Только нет JOIN, вот и всё. Это в целом относится к любой нереляционной базе. Не конкретно к хадупу.[/quote]Относительно HBasr это устаревшая информация, так как в HBase больше нет HQL (который как раз был отдаленно похож на традиционный SQL). Начиная с версии 0.2.0 вместо него в консольном клиенте используется абсолютно новый язык запросов (не менее тривиальный, чем HQL), который даже не знаю на что похож, как-то связан с JRuby, может быть...

  • gbeauty

    Что-то это мне напоминает объектную базу данных...

  • http://koreiz.cn/ Саша

    Спасибо за отличный материал Вам! Буду у Вас частым гостем). Начал изучать базы основательно...

  • Алексей

    Может кто в курсе, есть ли где нагрузочные тесты на Hbase?

    Хотябы в сравнении с тем же Hypertable (code.google.com/p/hyperta...eTestAOLQueryLog)?

  • Pingback: asash's blog » Подходы к масштабированию баз данных