我正在尝试使用spymemcached 2.6同步更新,我发现以下两种方式使用它:
使用CASMutation定义CASMutator,这是一种非常具有侵略性的实现方式,让我们看一个例子:
public List<Item> addAnItem(final Item newItem) throws Exception {
// This is how we modify a list when we find one in the cache.
CASMutation<List<Item>> mutation = new CASMutation<List<Item>>() {
// This is only invoked when a value actually exists.
public List<Item> getNewValue(List<Item> current) {
// Not strictly necessary if you specify the storage as
// LinkedList (our initial value isn't), but I like to keep
// things functional anyway, so I'm going to copy this list
// first.
LinkedList<Item> ll = new LinkedList<Item>(current);
// If the list is already "full", pop one off the end.
if(ll.size() > 10) {
ll.removeLast();
}
// Add mine first.
ll.addFirst(newItem);
return ll;
}
};
// The initial value -- only used when there's no list stored under
// the key.
List<Item> initialValue=Collections.singletonList(newItem);
// The mutator who'll do all the low-level stuff.
CASMutator<List<Item>> mutator = new CASMutator<List<Item>>(client, transcoder);
// This returns whatever value was successfully stored within the
// cache -- either the initial list as above, or a mutated existing
// one
return mutator.cas("myKey", initialValue, 0, mutation);
}
或使用cas
方法
cas(String key, long casId, Object value)
完成后:
gets(String key, Transcoder<T> tc)
第二个真的更简单,我理解为什么我会使用CASMutation ...... 我很高兴得到一些关于使用这个couchbase客户端的反馈。
答案 0 :(得分:3)
CASMutator / CASMutation捕获最佳实践和工作流程,以便为您完成正确的事情。
您的反例看起来更简单,因为您没有说明您使用这些方法实际做什么。您在上面发布的示例显示了一个从memcached中拉出的List,添加了一个新项目,有条件地从中删除了一些项目,然后将其放回原处。你发布的文本中至少有一半仍然需要写。
如果你没有使用 CASMutator,你最终会重新发明它,而这并不是那么简单。这就是它今天为你做的事情:
public T cas(final String key, final T initial, int initialExp,
final CASMutation<T> m) throws Exception {
T rv=initial;
boolean done=false;
for(int i=0; !done && i<max; i++) {
CASValue<T> casval=client.gets(key, transcoder);
T current=null;
// If there were a CAS value, check to see if it's compatible.
if(casval != null) {
T tmp = casval.getValue();
current=tmp;
}
// If we have anything mutate and CAS, else add.
if(current != null) {
// Declaring this impossible since the only way current can
// be non-null is if casval was set.
assert casval != null : "casval was null with a current value";
rv=m.getNewValue(current);
// There are three possibilities here:
// 1) It worked and we're done.
// 2) It collided and we need to reload and try again.
// 3) It disappeared between our fetch and our cas.
// We're ignoring #3 because it's *extremely* unlikely and the
// behavior will be fine in this code -- we'll do another gets
// and follow it up with either an add or another cas depending
// on whether it exists the next time.
if(client.cas(key, casval.getCas(), rv, transcoder)
== CASResponse.OK) {
done=true;
}
} else {
// No value found, try an add.
if(initial == null) {
done = true;
rv = null;
} else if(client.add(key, initialExp, initial, transcoder).get()) {
done=true;
rv=initial;
}
}
}
if(!done) {
throw new RuntimeException("Couldn't get a CAS in " + max
+ " attempts");
}
return rv;
}