В то время как 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. Мнения и взгляды, выраженные в этом посте, являются моими собственными и не обязательно отражают мнения или взгляды моего работодателя.