redis基础----->redis的基本使用(一)

  这里我们就在虚拟机中安装redis,并且使用java和python实现简单的操作。深情是我承担不起的重担,情话只是偶尔兑现的谎言。

redis的使用

下载地址:https://redis.io/。安装过程,可以参考博客:http://www.linuxidc.com/Linux/2014-05/101544.htm

启动服务,参考博客:http://www.linuxidc.com/Linux/2014-05/101544p2.htm

一、非本地访问redis服务器,需要修改redis.conf文件的内容

redis.conf文件的位置:tar解压的位置/redis.3.2.8里面。

  • 注释bind 127.0.0.1,使所有的主机都可以访问
  • 修改protected-mode的yes为no

如果要生效还需要先停掉redis的服务,再redis-server redis.conf。这个redis.conf需要带上。

参考博客: http://blog.csdn.net/only1994/article/details/52785306

二、java的测试使用

依赖jar包:jedis-2.9.0.jar和commons-pool2-2.4.2.jar。使用maven,需要在pom.xml文件中添加内容:

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>2.9.0</version>
    <type>jar</type>
    <scope>compile</scope>
</dependency>

具体的java代码如下:

public void redis_1() {
    Jedis jedis = new Jedis("192.168.146.131", 6379); // 测试用的是虚拟机
    jedis.set("foo", "bar");
    String value = jedis.get("foo");
    jedis.close();
    System.out.println(value); // foo
}

三、对于Jedis原理的理解

我们通过socket连接redis服务器,发送请求命令的数据,然后打印返回的数据。

package com.linux.huhx.redis;

import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;

/**
 * @Author: huhx
 * @Date: 2017-11-23 下午 5:48
 */
public class RedisTest {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("localhost", 6379);
        socket.setReuseAddress(true);
        String data = "get username
";
        socket.getOutputStream().write(data.getBytes());

        InputStream inputStream = socket.getInputStream();
        int length = inputStream.available();
        byte[] buffer = new byte[length];
        inputStream.read(buffer);

        // 对buffer做处理
        String string = new String(buffer, "utf-8");
        System.out.println(string);
        socket.close();
    }
}

如下是打印的结果,可以得到redis中username对应的value。

$4
huhx

  其实上述JRedis的原理和这个差不多,都是通过socket连接,发送命令数据到服务器。然后得到响应的数据,现在我们就JRedis的源码对这个流程做一个分析。首先是Jedis jedis = new Jedis("127.0.0.1", 6379);初始化Connection的地址和端口。

public Connection(final String host, final int port) {
    this.host = host;
    this.port = port;
}

String value = jedis.get("username");这段代码的源码如下:

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

checkIsInMultiOrPipeline方法是检查Multi和Pipeline,具体的这两个是开什么的,目前不怎么了解。后续补上

protected void checkIsInMultiOrPipeline() {
    if (client.isInMulti()) {
      throw new JedisDataException(
          "Cannot use Jedis when in Multi. Please use Transation or reset jedis state.");
    } else if (pipeline != null && pipeline.hasPipelinedResponse()) {
      throw new JedisDataException(
          "Cannot use Jedis when in Pipeline. Please use Pipeline or reset jedis state .");
    }
}

我们的重点代码是client.sendCommand(Protocol.Command.GET, key);如下:

protected Connection sendCommand(final Command cmd, final String... args) {
    // 对请求的参数utf-8编码
    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);
}

sendCommand的方法如下:

protected Connection sendCommand(final Command cmd, final byte[]... args) {
    try {
   // 建立socket连接,socket是一个keep active的连接,这个方法在建立连接之前会检查是否是连接状态的。
      connect();
      // 用上述的socket发送数据,对于发送的数据Jredis做了一些处理
      Protocol.sendCommand(outputStream, cmd, args);
      pipelinedCommands++;
      return this;
    } catch (JedisConnectionException ex) {
      /*
       * When client send request which formed by invalid protocol, Redis send back error message
       * before close connection. We try to read it to provide reason of failure.
       */
      try {
        String errorMessage = Protocol.readErrorLineIfPossible(inputStream);
        if (errorMessage != null && errorMessage.length() > 0) {
          ex = new JedisConnectionException(errorMessage, ex.getCause());
        }
      } catch (Exception e) {
        /*
         * Catch any IOException or JedisConnectionException occurred from InputStream#read and just
         * ignore. This approach is safe because reading error message is optional and connection
         * will eventually be closed.
         */
      }
      // Any other exceptions related to connection?
      broken = true;
      throw ex;
    }
}

最后我们就可以通过client.getBulkReply()的方法得到响应的数据并做处理返回。

private static Object process(final RedisInputStream is) {

    final byte b = is.readByte();
    if (b == PLUS_BYTE) {
      return processStatusCodeReply(is);
    } else if (b == DOLLAR_BYTE) {
      return processBulkReply(is);
    } else if (b == ASTERISK_BYTE) {
      return processMultiBulkReply(is);
    } else if (b == COLON_BYTE) {
      return processInteger(is);
    } else if (b == MINUS_BYTE) {
      processError(is);
      return null;
    } else {
      throw new JedisConnectionException("Unknown reply: " + (char) b);
    }
}

其实这个方法针对于返回的数据相应做了处理的,在我们RedisTest的测试中。返回的数据是$4 huhx。这里经过process方法的处理,只会返回huhx的数据。具体的这里不作分析。

友情链接

原文地址:https://www.cnblogs.com/huhx/p/baseuseredis1.html