Статьи

MapDB: Agile Java Data Engine

MapDB — это чистая база данных Java, специально разработанная для разработчика Java. Фундаментальная концепция MapDB очень умна, но естественна в использовании: предоставляет надежный, полнофункциональный и «настраиваемый» механизм баз данных, использующий API Java Collections.

MapDB 1.0 был только что выпущен, это кульминация многолетних исследований и разработок, чтобы довести проект до этой точки. Ян Котек (Jan Kotek), основной разработчик MapDB, также работал над предшествующими проектами (JDBM), начиная MapDB как полностью переписанный с нуля. Опыт и преданность Яна низкоуровневой отладке дали отличные результаты, создавая простую в использовании базу данных для Java со сравнимой производительностью со многими ядрами на основе Си.

Что отличает MapDB — это концепция «карты». Идея состоит в том, чтобы использовать полностью естественный API коллекций Java — настолько знакомый Java-разработчикам, что большинство из них буквально ежедневно используют его в своей работе. Для большинства взаимодействий базы данных с Java-приложением необходим какой-то переводчик. Существует множество инструментов объектно-реляционного отображения (ORM), которые называют только одну категорию таких компонентов. Цель всегда заключалась в том, чтобы сделать естественным кодирование объектов на языке Java и преобразование их в определенный синтаксис базы данных (например, SQL). Однако такие усилия всегда заканчивались неудачей, что усложняло как разработчика приложений, так и архитектора данных.

При использовании MapDB отсутствует «слой перевода» объекта — разработчики просто получают доступ к данным в привычных структурах, таких как Карты, Наборы, Очереди и т. Д. Синтаксис не отличается от типичного Java-кодирования, за исключением краткого синтаксиса инициализации и управления транзакциями. Разработчик может буквально за считанные секунды преобразовать карты с ограниченным объемом памяти в высокоскоростное постоянное хранилище (обычно изменяя только одну строку кода).

Пример MapDB

Вот простой пример MapDB, показывающий, насколько просто и интуитивно понятно использовать его в приложении Java:

// Initialize a MapDB database
DB db = DBMaker.newFileDB(new File("testdb"))
          .closeOnJvmShutdown()
.make();
// Create a Map:
Map<String,String> myMap = db.getTreeMap(“testmap”);

// Work with the Map using the normal Map API.
myMap.put(“key1”, “value1”);
myMap.put(“key2”, “value2”);

String value = myMap.get(“key1”);
...

Это все, что вам нужно сделать, теперь у вас есть карта с файловой поддержкой практически любого размера.

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

  • Реализация в памяти
  • Включить транзакции
  • Настраиваемое кеширование

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

Еще одна очень мощная функция заключается в том, что MapDB использует некоторые из расширенных вариантов коллекций Java, такие как ConcurrentNavigableMap. С этим типом карты вы можете выйти за рамки простой семантики ключ-значение, так как это также отсортированная карта, позволяющая получать доступ к данным по порядку и находить значения рядом с ключом. Мало кто знает об этом расширении API коллекций, но оно чрезвычайно мощное и позволяет вам многое делать с базой данных MapDB (я расскажу об этих возможностях в следующей статье).

Agile Аспект MapDB

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

Ключ к этой возможности присущ архитектуре MapDB и тому, как она переводится в сам API MapDB. Вот простая схема архитектуры MapDB:

Как видно из диаграммы, в MapDB есть 3 уровня:

  • API коллекций: это знакомый API коллекций Java, который каждый разработчик Java использует для поддержания состояния приложения. Он имеет простое расширение в стиле компоновщика, позволяющее вам контролировать точные характеристики данной базы данных (включая ее внутренний формат или структуру записи).
  • Механизм: Механизм является реальным ключом к MapDB, именно здесь контролируются записи для базы данных — включая их внутреннюю структуру, контроль параллелизма, семантику транзакций. MapDB поставляется уже с несколькими движками, и легко добавить собственный движок, если это необходимо для специализированной обработки данных.
  • Том: это физический уровень хранения (например, на диске или в памяти). MapDB имеет несколько стандартных реализаций Volume, и их должно хватить для большинства проектов.

Суть в том, что API разработки полностью отличается от реализации Engine (сердце MapDB), и оба они отделены от реального уровня физической памяти. Это предлагает очень гибкий подход, позволяющий разработчикам точно контролировать, какой тип внутренней структуры необходим для данной базы данных, и как выглядит фактическая структура данных из API коллекций верхнего уровня.

Чтобы сделать вещи еще более расширяемыми и гибкими, MapDB использует концепцию Engine Wrappers. Оболочка двигателя позволяет добавлять дополнительные функции и опции поверх определенного слоя двигателя. Например, если стандартный движок Map используется для создания карты на основе B-Tree, целесообразно включить (или отключить) поддержку кэширования. Эта функция кэширования выполняется через Engine Wrapper, и именно это проявляется в API-интерфейсе в стиле компоновщика, который используется для настройки конкретной базы данных. Хотя целую статью можно написать именно об этом, суть в том, что это добавляет присущую гибкой природе MapDB.

В качестве примера, вот как вы конфигурируете чистую базу данных в памяти без транзакционных возможностей:

// Initialize an in-memory MapDB database 
// without transactions
DB db = DBMaker.newMemoryDB()
		.transactionDisable()
          .closeOnJvmShutdown()
.make();

// Create a Map:
Map<String,String> myMap = db.getTreeMap(“testmap”);

// Work with the Map using the normal Map API.
myMap.put(“key1”, “value1”);
myMap.put(“key2”, “value2”);

String value = myMap.get(“key1”);
...

Это оно! Все, что было нужно, это изменить вызов DBMaker, чтобы добавить новые опции, все остальное работает точно так же, как в примере, показанном ранее.

Agile Data Model

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

Вероятно, это похоже на то, как вы пишете свой код при создании стандартных структур Java в памяти. Например, допустим, вам нужно искать объект Person по имени пользователя или по personID. Просто создайте объект Person и две Карты, чтобы удовлетворить ваши потребности:

public class Person {

private Integer personID;
private String username;
...

// Setters and getters go here
...

}

// Create a Map of Person by username.
Map<String,Person> personByUsernameMap = ...

// Create a Map of Person by personID.
Map<Integer,Person> personByPersonIDMap = ...

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

Еще одна интересная концепция со структурами данных MapDB — это некоторые ключевые расширения обычного API коллекций Java. Общим требованием в приложениях является наличие карты с ключом / значением, и в дополнение к поиску значения для ключа, чтобы можно было выполнить обратное: поиск ключа для данного значения. Мы можем легко сделать это, используя расширение MapDB для двунаправленных карт:

// Create a primary map
HTreeMap<Long,String> map = DBMaker.newTempHashMap();

// Create the inverse mapping for primary map
NavigableSet<Fun.Tuple2<String, Long>> inverseMapping = 
  new TreeSet<Fun.Tuple2<String, Long>>();

// Bind the inverse mapping to primary map, so it is auto-updated each time the primary map gets a new key/value
Bind.mapInverse(map, inverseMapping);

map.put(10L,"value2");
map.put(1111L,"value");
map.put(1112L,"value");
map.put(11L,"val");

// Now find a key by a given value.
Long keyValue = Fun.filter(inverseMapping.get(“value2”);

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

Завершение

Я показал очень краткое введение в MapDB и как этот продукт работает. Как вы можете видеть, его сильные стороны — это использование естественного API Java Collections, гибкая природа самого движка и поддержка практически любого типа модели данных или схемы, которая нужна вашему приложению. MapDB свободно доступна для любого использования под лицензией Apache 2.0.

Чтобы узнать больше, проверьте:  www.mapdb.org .