• memcached(七)--常用指令抓包分析


      使用spymemcached客户端,通过wireshark抓包,更清晰的看到memcached的命令。

      先来一个简单的demo:

    package spymc;
    
    import java.io.IOException;
    import java.net.InetSocketAddress;
    
    import net.spy.memcached.CASResponse;
    import net.spy.memcached.CASValue;
    import net.spy.memcached.MemcachedClient;
    
    public class TestSpyMc {
    
        public static void main(String[] args) throws IOException {
            MemcachedClient c = new MemcachedClient(new InetSocketAddress("aliyun.9game.cn", 11211));
            
            c.set("abc", 3600, "hello");
            System.err.println(c.get("abc"));
            
            //CASValue<Object> vasValue = c.gets("abc");
            //CASResponse resp= c.cas("abc", vasValue.getCas(), "pre");
            //System.out.println(resp.name());
            //resp= c.cas("abc", vasValue.getCas(), "after");
            //System.out.println(resp.name());
            c.shutdown();
        }
    }

      抓包的结果会看到:

    set abc 0 3600 5
    hello
    get abc
    STORED
    VALUE abc 0 5
    hello
    END

      粉色代表请求,蓝色代表响应。spymemcached在上一节说了,spymemcached是非阻塞的。所以发出set指令响应之前,get命令都发出去了。

      然后看看 gets 和cas。尝试做两次cas操作:

    package spymc;
    
    import java.io.IOException;
    import java.net.InetSocketAddress;
    
    import net.spy.memcached.CASResponse;
    import net.spy.memcached.CASValue;
    import net.spy.memcached.MemcachedClient;
    
    public class TestSpyMc {
    
        public static void main(String[] args) throws IOException {
            MemcachedClient c = new MemcachedClient(new InetSocketAddress("aliyun.9game.cn", 11211));
            
            //c.set("abc", 3600, "hello");
            //System.err.println(c.get("abc"));
            
            CASValue<Object> vasValue = c.gets("abc");
            CASResponse resp= c.cas("abc", vasValue.getCas(), "pre");
            System.out.println(resp.name());
            resp= c.cas("abc", vasValue.getCas(), "after");
            System.out.println(resp.name());
            c.shutdown();
        }
    }

      首先, 输出结果是:

    OK
    EXISTS

      抓包看到的是:

    gets abc
    VALUE abc 0 3 2272929
    pre
    END
    cas abc 0 0 3 2272929
    pre
    STORED
    cas abc 0 0 5 2272929
    after
    EXISTS

      gets 和cas 通过版本号实现原子性操作,重复两次cas,相同的版本号,第二次是失败的

      然后试试gets和sets之间,做一次set操作。java代码:

    package eGroup.spymcTest;
    
    import java.io.IOException;
    import java.net.InetSocketAddress;
    
    import net.spy.memcached.CASResponse;
    import net.spy.memcached.CASValue;
    import net.spy.memcached.MemcachedClient;
    
    public class TestSpyMc {
    
        public static void main(String[] args) throws IOException {
            MemcachedClient c = new MemcachedClient(new InetSocketAddress("aliyun.9game.cn", 11211));
            
            CASValue<Object> vasValue = c.gets("abc");
            
            c.set("abc", 3600, "hello sb");
            
            CASResponse resp= c.cas("abc", vasValue.getCas(), "pre");
            System.out.println(resp.name());
            c.shutdown();
        }
    }

      IDE控制台输出:

    EXISTS

      抓包得出:

    gets abc
    VALUE abc 0 8 2279149
    hello sb
    END
    set abc 0 3600 8
    hello sb
    cas abc 0 0 3 2279149
    pre
    STORED
    EXISTS

      set成功,cas就失败了。

      可见, gets&cas,是乐观锁的概念。并不是‘独占’数据的。

      重复add操作。java代码:

            c.add("addTest", 3600, "hello");
            
            c.add("addTest", 3600, "hello");

      抓包得出:

    add addTest 0 3600 5
    hello
    add addTest 0 3600 5
    hello
    STORED
    NOT_STORED

      mc 的add指令,如果有key存在了,后续的add操作是会失败的单点memcached的话可以当互斥锁来玩。

      试试二进制协议操作。memcached默认是既支持文本协议,又支持二进制协议的(具体是通过memcached请求的header来判定的)。不过spymemcached的客户端,要设置二进制协议的工厂才行。

      参考:https://code.google.com/p/spymemcached/wiki/Examples

      参考代码:

            MemcachedClient c = new MemcachedClient(new BinaryConnectionFactory(),
                    AddrUtil.getAddresses("aa.cc.bb:11211"));
            
            c.set("abc", 3600, "hello");
            
            Thread.sleep(1000);
            
            System.err.println(c.get("abc"));

       是个二进制协议啦,还好,wireshark对memcached的二进制协议作出优化,可以很容易看得到请求&响应。

      set 请求&响应:

      get的请求&响应:

      以下是对指令的一些总结:

    1. gets &cas 应该成对出现。在gets中会获取到一个数值类型的版本号,cas操作的时候要设置这个版本号。但是!如果gets、cas之间有改变这个数,cas会失败的。
    2. add操作不能设置重复key,否则会失败的。
  • 相关阅读:
    函数获取常用路径 SHGetSpecialFolderLocation、SHGetPathFromIDList
    [转载]Delphi线程池(Delphi2009以上版本适用)
    给 System.Zip 增长了个(多文件解压时的)解压进度事务
    sql操蛋的孤独账号。
    不错的几个jq控件
    jquery的跨域访问
    MVC3中输出Html标签的方法
    MVC_HtmlHelper用法大全
    execute sp_executesql 用变量获取返回值
    Asp.Net MVC中的RenderPartial 和 RenderAction
  • 原文地址:https://www.cnblogs.com/ELMND/p/4598610.html
Copyright © 2020-2023  润新知