如何在分布式缓存产品中传达在多个分布式映射上运行的事务

时间:2011-09-19 22:17:52

标签: java hazelcast distributed-cache

通过分布式缓存产品,我的意思是像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 个答案:

答案 0 :(得分:1)

如果要序列化写访问(互斥),分布式锁是一种可行的方法。如果您使用的是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();
  }