这里我们就在虚拟机中安装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\n"; 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的数据。具体的这里不作分析。
友情链接