通过分布式缓存产品,我的意思是像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()很昂贵(例如,在本地复制两个映射),在这种情况下,它可能不足以锁定多个客户端。
此分布式同步问题是否有标准解决方案?
答案 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();
}