剖析Redis协议(续)

通过Jedis这个redis的client包,执行一个基本的命令:get Device:99为例,跟踪Jedis源码可知调用了redis.clients.jedis.Jedis中的get方法:

public String get(final String key) {
    checkIsInMultiOrPipeline();
    client.sendCommand(Protocol.Command.GET, key);
    return client.getBulkReply();
  }

再调用redis.clients.jedis.Connection中的:

protected Connection sendCommand(final Command cmd, final String... args) {
    final byte[][] bargs = new byte[args.length][];
    for (int i = 0; i < args.length; i++) {
      bargs[i] = SafeEncoder.encode(args[i]);
    }
    return sendCommand(cmd, bargs);
  }

代码解读:SafeEncoder.encode(args[i])实际上就是执行这个方法:str.getBytes(Protocol.CHARSET);,我这里的测试时cache key为Device:99,SafeEncoder.encode(args[i])的结果是:new byte[]{68,101,118,105,99,101,58,57,57},68这个ASCII值对应的字符就是D,101这个ASCII值对应的字符就是e,这个byte[]数值就是表示此次测试的cache key:Device:99;

最终实际调用redis.clients.jedis.Protocol.java中的:

private static void sendCommand(final RedisOutputStream os, final byte[] command,
      final byte[]... args) {
    try {
      os.write(ASTERISK_BYTE);
      os.writeIntCrLf(args.length + 1);
      os.write(DOLLAR_BYTE);
      os.writeIntCrLf(command.length);
      os.write(command);
      os.writeCrLf();

      for (final byte[] arg : args) {
        os.write(DOLLAR_BYTE);
        os.writeIntCrLf(arg.length);
        os.write(arg);
        os.writeCrLf();
      }
    } catch (IOException e) {
      throw new JedisConnectionException(e);
    }
  }

代码解读:从上面这段Java代码可以看出一些redis协议的端倪了:
os.write(ASTERISK_BYTE): 即向Redis服务器Socket端口写入一个星号"*";
os.writeIntCrLf(args.length + 1) 写入本次执行命令的总参数长度,为参数长度1+1,1表示有一个GET命令;
os.write(DOLLAR_BYTE) 写入一个Dollar符号:"$"
os.writeIntCrLf(command.length) 写入一个GET命令的长度并写入"\r\n"(CrLf);
os.write(command) 写入GET命令:GET命令已经转为byte数值(new byte[]{71, 69, 84})
os.writeCrLf() 写入"\r\n"(CrLf)
接下来for循环遍历参数,本次测试只有一个参数:Device:99,所以for遍历一次即可;for循环中解读:
os.write(DOLLAR_BYTE) 写入一个Dollar符号:"$"
os.writeIntCrLf(arg.length) 写入参数的长度并写入"\r\n"(CrLf);
os.write(arg) 写入参数
os.writeCrLf() 写入"\r\n"(CrLf);

反推Redis协议文本

通过上面的代码解读,反推出执行GET Device:99这个命令的Redis协议:

*2\r\n
$3\r\n
71 69 84\r\n
$9\r\n
68 101 118 105 99 101 58 57 57\r\n

转化为协议文本(文本需要unix2dos从而补上\r\n):

*2
$3
GET
$9
Device:99
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 本文将从Redis的基本特性入手,通过讲述Redis的数据结构和主要命令对Redis的基本能力进行直观介绍。之后概...
    kelgon阅读 61,271评论 23 625
  • 1.1 资料 ,最好的入门小册子,可以先于一切文档之前看,免费。 作者Antirez的博客,Antirez维护的R...
    JefferyLcm阅读 17,110评论 1 51
  • 安全性 设置客户端连接后进行任何其他指令前需要使用的密码。 警告:因为redis 速度相当快,所以在一台比较好的服...
    OzanShareing阅读 1,826评论 1 7
  • 遇见“你”之前,月光与我两点一线 1 七月决定独自留校学车,看着日渐空荡的宿舍,心底莫名生出一股恐慌的情绪,就像溺...
    言蹊clj阅读 336评论 0 5
  • 从小就被老师和家长们灌输“学习为了你自己,你要好好学”,可从小到大看到因为学习而快乐成长的孩子基本上10根手指头就...
    祁小熊阅读 997评论 3 2