【问题标题】:prevent conflict with spymemcached防止与 spymemcached 冲突
【发布时间】:2011-06-15 19:02:50
【问题描述】:

我正在尝试使用 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 客户端的反馈。

【问题讨论】:

    标签: java memcached couchbase spymemcached


    【解决方案1】:

    CASMutator/CASMutation 捕捉最佳实践和工作流程,以便为您完成正确的事情。

    你的反例看起来更简单,因为你并没有说你实际上用这些方法做什么。您在上面发布的示例显示了一个从 memcached 中拉出的列表,向其中添加了一个新项目,有条件地从中删除了一些项目,然后将其放回原处。您发布的文本中至少有一半仍然需要编写。

    如果你不使用 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;
    }
    

    【讨论】:

    • 好吧,你说的很对,但是你不觉得这个解决方案很麻烦吗?
    • 以什么方式侵入?它以处理器上的 CAS 操作为模型,除了在单键高竞争的地方外,应该可以很好地扩展。老实说,Java 让它变得更难了。大多数代码只是许多语言中的简单 lambda 表达式。 Java 只是带来了一堆语法来包裹它。
    • 这对我来说似乎是侵入性的,因为我必须将我的业务代码放在 spymemcached getNewValue 函数定义中。你不觉得使用一些图案或分离层是不可能的吗?
    • 不同的层。您必须更具体地说明您希望此转换做什么,但是无论您想要做什么,您只需让客户端在靠近服务器的地方进行操作,或者您手动进行并在服务器上做更多的工作外部。您可以使用一切可能的东西,但我不知道您认为哪些干扰较小。
    猜你喜欢
    • 2022-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多