Статьи

BigMemory 4.0 технический обзор

Для тех, кто работает с огромными наборами данных (от гигабайтов до терабайтов), BigMemory — продукт, который стоит рассмотреть, поскольку он позволяет вашему java-приложению обрабатывать большие объемы данных в памяти. Это означает, что вы получаете быстрый доступ к вашим данным.

Версия 4.0 вышла через несколько дней, давайте посмотрим, что внутри.

1) «Быстрый доступ к данным в терабайтном масштабе»

Есть интересная статья, которая была опубликована в прошлом году. Это сообщает о результатах масштабирования тестового приложения. Размер набора данных начинался с 2 ГБ и доходил до 1,8 ТБ. Пропускная способность оставалась в пределах приблизительно 10% от среднего значения без скачков задержки, вызванных сборкой мусора. В целом, скорость чтения / записи в BigMemory примерно одинакова: от гигабайтов до терабайтов данных.

Архитектура следующая:

Каждый экземпляр вашего приложения использует Ehcache для кэширования набора данных в куче. Затем вы определяете в Ehcache нужный вам размер магазина BigMemory. Эта часть называется offheap, так как это память, которая не обрабатывается сборщиком мусора (таким образом, это не куча)

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

BigMemoryArchi

С точки зрения разработки, если вы знакомы с Ehcache, вы не будете потеряны.

Создание экземпляра Bigmemory будет выглядеть так:

import net.sf.ehcache.*;
import net.sf.ehcache.config.*;

Configuration cfg = new Configuration()
    .terracotta(new TerracottaClientConfiguration().url("localhost:9510"))
    .cache(new CacheConfiguration().name("myDataTableExample")
    .maxBytesLocalHeap(1, MemoryUnit.GIGABYTES)
    .maxBytesLocalOffHeap(4, MemoryUnit.GIGABYTES)
    .terracotta(new TerracottaConfiguration())
);
CacheManager manager = CacheManager.newInstance(cfg);
Ehcache myDataTableExample = manager.getEhcache("myDataTableExample");

String key = "some key";
SomeCustomEntity value = ....
SomeCustomEntity newValue = ....

myDataTableExample.put(new Element(key, value));

myDataTableExample.replace(new Element(key, newValue));

value = (SomeCustomEntity)myDataTableExample.get(key).getObjectValue();

myDataTableExample.remove(key);

manager.shutdown();

2) «Мониторинг»

Это относится к инструменту мониторинга под названием TMC.
После установки архива BigMemory вы сможете запустить его из командной строки с помощью одного из следующих сценариев, в зависимости от используемой версии:

tools/management-console/bin/start-tmc.sh

или же

management-console/bin/start-tmc.sh

Тогда приложение мониторинга можно открыть в вашем браузере на

http://localhost:9889/tmc

ТМС

В этом примере хранилище кластеризовано (совместно используется различными JVM) через сервер Terracotta, а консоль мониторинга получает информацию с сервера Terracotta.

Это означает, что в случае, если вы находитесь в автономном режиме (хранилище работает в одной JVM), вы не используете сервер Terracotta. Вам необходимо указать в своей конфигурации, что вы собираетесь публиковать свои данные в консоли мониторинга:

ManagementRESTServiceConfiguration restCfg = new ManagementRESTServiceConfiguration();
restCfg.setSecurityServiceLocation("http://localhost:9889/tmc/api/assertIdentity");

Configuration cfg = new Configuration()
    .managementRESTService(restCfg)
    .cache(new CacheConfiguration().name("myDataTableExample")
    .maxBytesLocalHeap(1, MemoryUnit.GIGABYTES)
    .maxBytesLocalOffHeap(4, MemoryUnit.GIGABYTES)
);

3) «Быстрый перезапуск для аварийного восстановления»

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

Есть 4 варианта, но я сосредоточусь на двух самых важных: localRestartable и распределенный

a) localRestartable используется для автономной конфигурации, сохраняя данные на диск

Configuration cfg = new Configuration()
    .diskStore(new DiskStoreConfiguration().path("/mydisk/mystore/"))
    .cache(new CacheConfiguration().name("myPersistentDataTableExample")
    .maxBytesLocalHeap(1, MemoryUnit.GIGABYTES)
    .maxBytesLocalOffHeap(4, MemoryUnit.GIGABYTES)
    .persistence(new PersistenceConfiguration().strategy(PersistenceConfiguration.Strategy.LOCALRESTARTABLE))
);

б) распределенный используется для кластерной конфигурации, сохраняя данные на сервере терракоты, который будет отвечать за сохранение их на диске

Configuration cfg = new Configuration()
    .diskStore(new DiskStoreConfiguration().path("/mydisk/mystore/"))
    .terracotta(new TerracottaClientConfiguration().url("localhost:9510"))
    .cache(new CacheConfiguration().name("myPersistentDataTableExample")
    .maxBytesLocalHeap(1, MemoryUnit.GIGABYTES)
    .maxBytesLocalOffHeap(4, MemoryUnit.GIGABYTES)
    .terracotta(new TerracottaConfiguration())
    .persistence(new PersistenceConfiguration().strategy(PersistenceConfiguration.Strategy.DISTRIBUTED))
);

И добавьте в конфигурацию сервера терракоты (tc-config.xml):

<restartable enabled="true"/>

<offheap>
<enabled>true</enabled>
<maxDataSize>....</maxDataSize>
</offheap>

4) «Поддержка поиска»

Как мы уже видели, с BigMemory у нас есть хранилище данных <Key, Value> в памяти, которое можно кластеризовать и сохранить на диске.

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

Для описания всех функций поддержки поиска потребуется целый пост, поэтому приведу простой пример:

Скажем, мы помещаем в память экземпляры класса Person, которые будут иметь эти два поля:

private String familyName;
private Integer age;

Найти каждого человека с фамилией, начинающейся с ‘A’, будет:

import net.sf.ehcache.search.*;
import net.sf.ehcache.search.aggregator.*;

Query query = myPersistentDataTableExample.createQuery()
     .addCriteria(new ILike("familyName", "A%"))
     .includeValues()
     .addOrderBy(new Criteria("familyName"), Direction.ASCENDING);

Results results = query.execute();
List<Result> all = results.all();
for (Result result : all) {
    Person person = (Person)result.getValue();
}

5) «Hadoop Ready»

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

Он очень мощный, потому что вы можете использовать обычные серверы, а Hadoop позаботится о распределении работы между ними.

Hadoop имеет собственную файловую систему с именем HDFS, и вам сначала необходимо импортировать данные в систему HDFS, прежде чем их можно будет обработать.

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

Появляются некоторые решения, такие как запросы Cloudera Impala в реальном времени.

BigMemory решает проблему, предоставляя разъем Hadoop. С помощью этого соединителя Hadoop может отправлять данные в BigMemory, как только они обрабатываются, делая их доступными для памяти в режиме реального времени.

В Hadoop интерфейсы OutputFormat и RecordWriter определяют, как обрабатываются выходные данные сопоставления / сокращения заданий.

Например, по умолчанию TextOutputFormat помещает данные в файл в системе HDFS.
Вместо этого вы можете использовать EhcacheOutputFormat, то есть пользовательскую реализацию OutputFormat, которая будет записывать данные в BigMemory.

Если мы возьмем известный пример Hadoop Wordcount,

  public static void main(String[] args) throws Exception {
          JobConf conf = new JobConf(WordCount.class);
          conf.setJobName("wordcount");

          conf.setOutputKeyClass(Text.class);
          conf.setOutputValueClass(IntWritable.class);

          conf.setMapperClass(Map.class);
          conf.setCombinerClass(Reduce.class);
          conf.setReducerClass(Reduce.class);

          conf.setInputFormat(TextInputFormat.class);
          conf.setOutputFormat(TextOutputFormat.class);

          FileInputFormat.setInputPaths(conf, new Path(args[0]));
          FileOutputFormat.setOutputPath(conf, new Path(args[1]));

          JobClient.runJob(conf);
        }

это превратится в

  public static void main(String[] args) throws Exception {
          JobConf conf = new JobConf(WordCount.class);
          conf.setJobName("wordcount");

          conf.setOutputKeyClass(Text.class);
          conf.setOutputValueClass(EhcacheElementWritable.class);

          conf.setMapperClass(Map.class);
          conf.setCombinerClass(Reduce.class);
          conf.setReducerClass(Reduce.class);

          conf.setInputFormat(TextInputFormat.class);
          conf.setOutputFormatClass(EhcacheOutputFormat.class);   //

          FileInputFormat.setInputPaths(conf, new Path(args[0]));

          JobClient.runJob(conf);
        }

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

6) Еще
Под капотом есть другие вещи.

Библиотека инструментов доступна для кластерных объектов (таких как коллекции, блокировки, синхронизация …).

Функциональность безопасности была улучшена. Как и в версии 3.7, связь на основе SSL доступна для безопасной настройки. Кроме того, вы можете использовать сервер LDAP или Active Directory для хранения учетных данных.

А также, Java 7 поддерживается …

Так что, если вы заинтересованы в мире больших данных, вы обязательно должны проверить это здесь.

Не стесняйтесь оставлять комментарии, если вам нужно больше точности!