防止与spymemcached冲突

发布于 2024-11-15 15:04:37 字数 1421 浏览 8 评论 0 原文

我正在尝试使用spymemcached 2.6与更新同步,我发现了以下两种使用它的方法:

  • 使用CASMutation定义CASMutator,这是一种相当侵入性的实现方式,让我们看一个例子:

    公共列表<项目>; addAnItem(final Item newItem) 抛出异常 {
    
        // 这就是当我们在缓存中找到列表时修改列表的方式。
        CASMutation<列表<项目>>突变 = new CASMutation>() {
    
            // 仅当值实际存在时才会调用。
            公共列表<项目> getNewValue(List 当前) {
                // 如果您将存储指定为,则并非绝对必要
                // LinkedList(我们的初始值不是),但我喜欢保留
                // 无论如何,事情都是有用的,所以我要复制这个列表
                // 第一的。
                链接列表<项目> ll = new LinkedList(当前);
    
                // 如果列表已经“满”,则从末尾弹出一个。
                if(ll.size() > 10) {
                    ll.removeLast();
                }
                // 首先添加我的。
                ll.addFirst(newItem);
    
                返回ll;
            }
        };
    
        // 初始值——仅当没有列表存储时使用
        // 密钥。
        列表<项目>初始值=Collections.singletonList(newItem);
    
        // 将完成所有低级工作的 mutator。
        CASMutor<列表<项目>> mutator = new CASMutor>(客户端,转码器);
    
        // 这将返回成功存储在
        // 缓存——或者是上面的初始列表,或者是一个变异的现有列表
        // 一
        return mutator.cas("myKey",initialValue,0,mutation);
    }
    

使用cas方法

cas(String key, long casId, Object value)

或者在完成后

gets(String key, Transcoder<T> tc) 

:第二个确实更多简单,我明白为什么我会使用 CASMutation... 我真的很高兴得到一些关于使用这个 couchbase 客户端的反馈。

I'm trying to use spymemcached 2.6 with synchronization on update and I found the two following way to use it:

  • using CASMutation defining a CASMutator which is quite an invasive way to implement it, let see an example:

    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);
    }
    

or by using cas method

cas(String key, long casId, Object value)

after have done:

gets(String key, Transcoder<T> tc) 

The second one is really more simple, and I understand why I would use CASMutation...
I would be really pleased to get some feedback about the use of this couchbase client.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

携君以终年 2024-11-22 15:04:37

CASMutor/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;
}

CASMutator/CASMutation captures the best practices and workflow so that the right thing is done for you.

Your counter-example looks more simple since you aren't saying what you'd actually do with those methods. The sample you posted above is showing a List being pulled out of memcached, a new item added to it, conditionally removing some items from it, and then putting it back. At least half of that text you posted you'd still need to write.

If you don't use CASMutator, you'll end up reinvent it, and that's not all that simple. This is what it does for you today:

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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文