Решения Java для распределенных транзакций и / или данных, совместно используемых в кластере - PullRequest
21 голосов
/ 24 октября 2009

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

  • Какие технологии (методы разработки программного обеспечения или конкретные технологии) вы бы предложили для решения проблемы такого типа?
  • Какие методы вы используете, чтобы создать постоянный слой для масштабирования многими читателями / писателями Масштабировать транзакции приложений и масштабировать доступ к совместно используемым данным (лучший подход - исключить совместно используемые данные; какие методы вы можете применить для удаления совместно используемых данных).
  • Кажется, что нужны разные подходы в зависимости от того, являются ли ваши транзакции тяжелыми для чтения или записи, но я чувствую, что вы можете оптимизировать тяжелое приложение для "записи", которое также будет эффективно для "чтения"

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

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

  1. Явные блокировки (которые чрезвычайно подвержены ошибкам и медленно координируются между несколькими узлами в распределенной системе)
  2. Программная транзакционная память (STM) AKA оптимистичный параллелизм, при котором транзакция откатывается во время принятия, если она обнаруживает, что общее состояние изменилось (и транзакция может быть позже повторена). Какой подход лучше масштабируется и каковы компромиссы в распределенной системе?

Я исследовал решения для масштабирования (и в общих приложениях, которые предоставляют пример того, как масштабировать), такие как:

  1. Terracotta - обеспечивает «прозрачное» масштабирование, расширяя модель памяти Java, чтобы включить распределенную разделяемую память, используя механизм блокировки параллелизма Java (синхронизированный, ReentrantReadWriteLocks).
  2. Google App Engine Java - Позволяет вам писать приложения Java (или python), которые будут распределены между «облачными» серверами, где вы распределяете, какой сервер обрабатывает транзакцию, и вы используете BigTable для хранения ваших постоянных данных. (не знаете, как вы проводите транзакции, которые получают доступ к общим данным или обрабатывают конфликты блокировок, чтобы иметь возможность эффективно масштабировать)
  3. Darkstar MMO Server - Darkstar - MMO-сервер Sun с открытым исходным кодом (массовая многопользовательская онлайн-игра), который масштабирует транзакции в потоковом режиме, позволяя данной транзакции выполняться только для определенной суммы и совершая транзакции, и если занимает много времени, это будет откат (вроде как программная транзакционная память). Они исследовали поддержку настройки многоузлового сервера для масштабирования.
  4. Оптимистическая блокировка Hibernate - если вы используете Hibernate, вы можете использовать их поддержку оптимистичного параллелизма для поддержки программной транзакционной памяти поведение типа
  5. Apache CouchDB должен «масштабироваться» до многих БД для чтения / записи в конфигурации сетки естественным образом. (Есть ли хороший пример того, как вы управляете блокировкой данных или обеспечением изоляции транзакций?):
  6. JCache - Масштабирование «чтения» тяжелых приложений путем кэширования результатов в общих запросах, которые можно использовать в приложении Google для доступа к memcached и для кэширования других часто читаемых данных.

Terracotta представляется наиболее полным решением, поскольку вы можете "легко" изменить существующее серверное приложение для поддержки масштабирования (после определения объектов @Root и методов @ AutoLockRead / Write). Проблема состоит в том, чтобы действительно получить максимальную производительность от распределенного приложения, оптимизация для распределенных систем не является запоздалой мыслью, что вы должны разработать ее, зная, что доступ к объектам потенциально может быть заблокирован сетевым вводом-выводом.

Для правильного масштабирования кажется, что это всегда сводится к разделению данных и транзакциям балансировки нагрузки, так что данный «исполнительный модуль» (ядро ЦП -> поток -> узел распределенного приложения -> главный узел БД)

Похоже, что для правильного масштабирования любого приложения путем кластеризации необходимо иметь возможность разделять транзакции с точки зрения их доступа к чтению / записи данных. Какие решения предлагают люди для распространения данных своих приложений (Oracle, Google BigTable, MySQL, хранилище данных), и, как правило, как вы управляете секционированием данных (многие мастера записи, с большим количеством читаемых БД и т. Д.).

С точки зрения масштабирования уровня сохраняемости данных, какой тип конфигурации лучше всего масштабируется с точки зрения разделения ваших данных среди многих читателей / многих авторов (как правило, я делю свои данные на основе данного пользователя (или любой основной сущности, которая как правило, ваша «корневая» объектная сущность) принадлежит одной главной БД)

Ответы [ 6 ]

3 голосов
/ 20 мая 2010

Я думал, что нашел отличную платформу Java Clustering / Distributed, хотел открыть это-

Оформить заказ http://www.hazelcast.com

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

2 голосов
/ 24 октября 2009
2 голосов
/ 24 октября 2009

Спасибо за хорошее обобщение всех возможностей в одном месте.

Хотя здесь не хватает одной техники. Это MapReduce-Hadoop. Если возможно вписать проблему в парадигму MapReduce, это, пожалуй, наиболее широко доступное решение. Мне также интересно, можно ли распространить шаблон Actor Framework (JetLang, Kilim и т. Д.) На кластер.

1 голос
/ 12 августа 2013

В то время как Oracle Coherence и многие другие предложенные решения хороши для совместного использования данных, вы указали только блокировку и STM как способы управления мутацией состояния в распределенной среде; и то, и другое - довольно плохие способы масштабирования государственного управления. На другом сайте я недавно разместил следующую информацию о том, как реализовать (например) счетчики последовательности:

Если вы смотрите на счетчик, то с помощью чего-то вроде Coherence EntryProcessor легко можно добиться поведения «один-единственный-один-единственный» и HA для любого количества монотонно увеличивающихся последовательностей; вот полная реализация:

public class SequenceCounterProcessor
        extends AbstractProcessor
    {
    public Object process(InvocableMap.Entry entry)
        {
        long l = entry.isPresent() ? (Long) entry.getValue() + 1 : 0;
        entry.setValue(l);
        return l;
        }
    }

Да. Вот и все. Автоматическая и плавная HA, динамическая эластичность при горизонтальном масштабировании, поведение «один-единственный-единственный раз» и т. Д. Готово.

EntryProcessor - это тип распределенного замыкания, который мы представили в 2005 году.

Кроме того, в Java 8 (еще не выпущен) проект Lambda вводит официальную поддержку закрытия в языке и стандартных библиотеках.

По сути, идея заключается в том, чтобы обеспечить закрытие местоположения «владельца» данных в распределенной среде. Coherence динамически управляет владением данными, используя динамическое разбиение, что позволяет распределенной системе распределять данные о нагрузке между различными машинами и узлами, которые работают. На самом деле, по умолчанию все это на 100% автоматизировано, поэтому вы никогда не скажете ему, куда помещать данные или куда они идут. Кроме того, существуют вторичные (и, возможно, третичные и т. Д.) Копии данных, управляемые на других узлах и других физических серверах, для обеспечения высокой доступности в случае сбоя процесса или смерти сервера. Опять же, управление этими резервными копиями является полностью автоматическим и полностью синхронным по умолчанию, что означает, что система по умолчанию имеет 100% HA (т.е. без конфигурации).

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

Несколько оптимизаций к вышеперечисленному: добавление интерфейсов ExternalizableLite и PortableObject для оптимизированной сериализации и недопущение сериализации в штучной упаковке путем прямого перехода к форме «готовности к сети»:

public Object process(InvocableMap.Entry entry)
    {
    try
        {
        BinaryEntry binentry = (BinaryEntry) entry;
        long l = entry.isPresent() ? binentry.getBinaryValue()
                .getBufferInput().readLong() + 1 : 0L;
        BinaryWriteBuffer buf = new BinaryWriteBuffer(8);
        buf.getBufferOutput().writeLong(l);
        binentry.updateBinaryValue(buf.toBinary());
        return l;
        }
    catch (IOException e)
        {
        throw new RuntimeException(e);
        }
    }

А так как он не имеет состояния, почему бы не подготовить экземпляр синглтона?

public static final SequenceCounterProcessor INSTANCE =
        new SequenceCounterProcessor();

Использовать его из любой точки сети так же просто, как и одну строку кода:

long l = (Long) sequences.invoke(x, SequenceCounterProcessor.INSTANCE);

Где "x" - это любой объект или имя, которое идентифицирует конкретный счетчик последовательности, который вы хотите использовать. Для получения дополнительной информации см. Базу знаний Coherence по адресу: http://coherence.oracle.com/

Oracle Coherence - распределенная система. Каждый раз, когда вы запускаете узел Coherence, он соединяется с другими уже запущенными узлами Coherence и динамически формирует эластичный кластер. Этот кластер размещает данные в многораздельном, высокодоступном (HA) и транзакционно-согласованном виде, а также размещает операции (подобные той, что я показал выше), которые обрабатывают эти данные «один раз и только один раз».

Кроме того, в дополнение к возможности вызывать любую из этой логики или осуществлять прозрачный доступ к любым из этих данных из любого узла Coherence, вы также можете вызывать любую из этой логики или осуществлять прозрачный доступ к любым из этих данных из любого процесса в сети ( подлежит аутентификации и авторизации, конечно). Таким образом, этот код будет работать с любого узла кластера Coherence или с любого (Java / C / C ++ / C # / .NET) клиента:

Ради полного раскрытия я работаю в Oracle. Мнения и взгляды, выраженные в этом посте, являются моими собственными и не обязательно отражают мнения или взгляды моего работодателя.

1 голос
/ 24 октября 2009

Не забывайте, Мнезия Эрланга .

Mnesia предоставляет вам такие вещи, как транзакции, к которым вы привыкли в обычной БД, но обеспечивает операции в реальном времени и отказоустойчивость. Плюс вы можете перенастроить вещи без простоя. Недостатком является то, что это резидентная база данных, поэтому вам нужно фрагментировать очень большие таблицы. Самый большой размер таблицы - 4 ГБ.

0 голосов
/ 11 декабря 2009

Может быть, эти слайды будут полезны. Исходя из нашего опыта, я бы порекомендовал Oracle (Tangosol) Coherence и GigaSpaces в качестве наиболее мощных сред распространения данных и обработки данных. В зависимости от точного характера проблемы, один из них может сиять. Терракота также вполне применима для некоторых проблем.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...