1. 首页
  2. redis实践

剖析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

作者:阿飞的博客

来源:https://www.jianshu.com/p/78b94407f59c


JS中文网,Javascriptc中文网是中国领先的新一代开发者社区和专业的技术媒体,一个帮助开发者成长的社区,是给开发者用的 Hacker News,技术文章由为你筛选出最优质的干货,其中包括:Android、iOS、前端、后端等方面的内容。目前已经覆盖和服务了超过 300 万开发者,你每天都可以在这里找到技术世界的头条内容。

本文著作权归作者所有,如若转载,请注明出处

转载请注明:文章转载自「 Java极客技术学习 」https://www.javajike.com

标题:剖析Redis协议(续)

链接:https://www.javajike.com/article/1819.html

« redis实现自动补全
Redis源码涉及C语言»

相关推荐

QR code