Как передать транзакции, работающие на нескольких распределенных картах, в продукте распределенного кэша - PullRequest
3 голосов
/ 20 сентября 2011

Под продуктом распределенного кэша я имею в виду что-то вроде Coherence или Hazelcast. Я буду использовать Hazelcast в качестве примера.

Предположим, у меня есть объект, который сохраняет состояние на нескольких картах:

class DataState {
    Map<ID, Dog> dogs = Hazelcast.getMap("dog");
    Map<ID, Owner> owners = Hazelcast.getMap("owner");

    public void associate(Dog dog, Owner owner) { 
          /* ... put in maps and set up references */ 
    }
}

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

class DataStateClient {
     Map<ID, Dog> dogs = Hazelcast.getMap("dog");
     Map<ID, Owner> owners = Hazelcast.getMap("owner");

     public void doSomething() {
        // oops, owner2 is associated with dog1 but
        // dog1 is not yet in the map!
    }
}

Теперь Hazelcast распространил блокировки, чтобы решить что-то вроде этого, но каковы последствия для производительности? Предположим, что doSomething () стоит дорого (например, копирование обеих карт локально), и в этом случае может быть недостаточно заблокировать несколько клиентов.

Существует ли стандартное решение этой проблемы распределенной синхронизации?

1 Ответ

1 голос
/ 20 сентября 2011

Если вы хотите сериализовать доступ для записи (взаимное исключение), распределенная блокировка - это путь. Если бы вы использовали Cacheonix, ваш пример мог бы иметь более высокую производительность, если бы вы использовали блокировки чтения / записи Cacheonix. Таким образом, у читателей может быть одновременный доступ для чтения, и им не придется ждать завершения работы одного сервера, что было бы в случае использования простого мьютекса:

Автор:

  final Cacheonix cacheonix = Cacheonix.getInstance();
  final ReadWriteLock rwLock = cacheonix.getCluster().getReadWriteLock();
  final Lock writeLock = rwLock.writeLock();
  writeLock.lock();
  try {
     // No one else can enter this section

     // Update dogs

     // Update owners
  } finally {
     writeLock.unlock();
  }

...

Читатели:

  final Cacheonix cacheonix = Cacheonix.getInstance();
  final ReadWriteLock rwLock = cacheonix.getCluster().getReadWriteLock();
  final Lock readLock = rwLock.readLock();
  readLock.lock();
  try {
     // Readers can enter this section simultaneously 

     // Read dogs

     // Read owners
  } finally {
     readLock.unlock();
  }
...