本文共 8062 字,大约阅读时间需要 26 分钟。
Redis的基础介绍与安装使用步骤:
Redis的基础数据结构与使用: Redis核心原理: Redis 5 之后版本的高可用集群搭建: Redis 5 版本的高可用集群的水平扩展: Redis 5 集群选举原理分析:优秀博客:
Redis Protocol specification:
通信协议(protocol):
* <参数数量> CR LF$ <参数 1 的字节数量> CR LF <参数 1 的数据> CR LF...$ <参数 n 的字节数量> CR LF <参数 n 的数据> CR LF 参数> 参数> 参数> 参数> 参数数量>
*3$3SET$5mykey$7myvalue
"*3\r\n$3\r\nSET\r\n$5\r\nmykey\r\n$7\r\nmyvalue\r\n"
状态回复(status reply)的第一个字节是 "+"错误回复(error reply)的第一个字节是 "-"整数回复(integer reply)的第一个字节是 ":"批量回复(bulk reply)的第一个字节是 "$"多条批量回复(multi bulk reply)的第一个字节是 "*"
+OK
引用:
[root@localhost redis-5.0.2]# src/redis-server redis.conf2800:C 17 Dec 2018 22:53:50.981 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo2800:C 17 Dec 2018 22:53:50.982 # Redis version=5.0.2, bits=64, commit=00000000, modified=0, pid=2800, just started2800:C 17 Dec 2018 22:53:50.982 # Configuration loaded[root@localhost redis-5.0.2]# ps -ef|grep redisroot 2801 1 0 22:53 ? 00:00:00 src/redis-server *:6379root 2806 2674 0 22:53 pts/0 00:00:00 grep --color=auto redis[root@localhost redis-5.0.2]#
redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketTimeoutException: connect timed out
/sbin/iptables -I INPUT -p tcp --dport 6379 -j ACCEPT
vim redis.conf
protected-mode no
redis.clients jedis 2.9.0
代码很简单:
package com.demo.redis.client;import redis.clients.jedis.Jedis;public class RedisClient {public static void main(String[] args) { Jedis jedis = new Jedis("192.168.5.100",6379); System.out.println(jedis.set("name","xxx")); System.out.println(jedis.get("name"));}}
OKxxx
> redis.clients.jedis.Jedis#set(java.lang.String, java.lang.String) >redis.clients.jedis.Client#set(java.lang.String, java.lang.String) >redis.clients.jedis.BinaryClient#set(byte[], byte[]) >redis.clients.jedis.Connection#sendCommand(redis.clients.jedis.Protocol.Command, byte[]...) >redis.clients.jedis.Protocol#sendCommand(redis.clients.util.RedisOutputStream, redis.clients.jedis.Protocol.Command, byte[]...) >redis.clients.jedis.Protocol#sendCommand(redis.clients.util.RedisOutputStream, byte[], byte[]...)
核心代码如下:
package com.demo.redis.client;import com.demo.redis.connection.Connection;import com.demo.redis.protocol.Protocol;/** * 提供api服务 * @author zyy * @date 2018年12月17日 * */public class Client { private Connection connection; public Client(String host, int port) { connection = new Connection(host, port); } public String set(String key, String value) { set(SafeEncoder.encode(key), SafeEncoder.encode(value)); return connection.getStatusReply(); } public void set(byte[] key, byte[] value) { this.connection.sendCommand(Protocol.Command.SET,new byte[][]{key,value}); } public String get(String key) { this.connection.sendCommand(Protocol.Command.GET,SafeEncoder.encode(key)); return connection.getStatusReply(); }}
package com.demo.redis.client;import redis.clients.jedis.exceptions.JedisDataException;import redis.clients.jedis.exceptions.JedisException;import java.io.UnsupportedEncodingException;/** * 编码 * @author zyy * @date 2018年12月17日 * */public class SafeEncoder { public static byte[] encode(String str) { try { if (str == null) { throw new JedisDataException("value sent to redis cannot be null"); } else { return str.getBytes("UTF-8"); } } catch (UnsupportedEncodingException var2) { throw new JedisException(var2); } }}
package com.demo.redis.connection;import com.demo.redis.protocol.Protocol;import redis.clients.jedis.exceptions.JedisConnectionException;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.Socket;/** * 建立连接 * * @author zyy * @date 2018年12月17日 */public class Connection { private Socket socket; private String host; private int port; private OutputStream outputStream; private InputStream inputStream; public Connection(String host, int port) { this.host = host; this.port = port; } //发送命令 public Connection sendCommand(Protocol.Command cmd, byte[]... args) { try { this.connect(); Protocol.sendCommand(this.outputStream, cmd, args); //++this.pipelinedCommands; return this; } catch (JedisConnectionException var6) { throw var6; } } //如果未建立连接,则scoket 连接 public void connect() { try { if (!isConnected()) { socket = new Socket(host, port); inputStream = socket.getInputStream(); outputStream = socket.getOutputStream(); } } catch (IOException e) { e.printStackTrace(); } } //判断是否已建立连接 public boolean isConnected() { return socket != null && socket.isBound() && !socket.isClosed() && socket.isConnected() && !socket.isInputShutdown() && !socket.isOutputShutdown(); } //获取返回信息 public String getStatusReply() { byte b[] = new byte[1024]; try { socket.getInputStream().read(b); } catch (IOException e) { e.printStackTrace(); } return new String(b); }}
package com.demo.redis.protocol;import java.io.IOException;import java.io.OutputStream;/** * 进行协议编码 * @author zyy * @date 2018年12月17日 * */public class Protocol { /** * * <参数数量> CR LF * $ <参数 1 的字节数量> CR LF * <参数 1 的数据> CR LF * ... * $ <参数 n 的字节数量> CR LF * <参数 n 的数据> CR LF * */ public static final String PARAM_BYTE_NUM = "$"; public static final String PARAM_NUM = "*"; public static final String TERMINATION = "\r\n"; public static void sendCommand(OutputStream outputStream, Command command, byte[]... b) { /* 照着 SET mykey myvalue 的格式进行编码: *3 $3 SET $5 mykey $7 myvalue 最终如下: "*3\r\n$3\r\nSET\r\n$5\r\nmykey\r\n$7\r\nmyvalue\r\n" */ StringBuffer stringBuffer = new StringBuffer(); stringBuffer.append(PARAM_NUM).append(b.length + 1).append(TERMINATION); stringBuffer.append(PARAM_BYTE_NUM).append(command.name().length()).append(TERMINATION); stringBuffer.append(command).append(TERMINATION); for (byte[] arg : b) { stringBuffer.append(PARAM_BYTE_NUM).append(arg.length).append(TERMINATION); stringBuffer.append(new String(arg)).append(TERMINATION); } try { outputStream.write(stringBuffer.toString().getBytes()); } catch (IOException e) { e.printStackTrace(); } } public static enum Command { SET, GET; }} 参数> 参数> 参数> 参数> 参数数量>
package com.demo.redis.client;public class Jedis { public static void main(String[] args) { Client client = new Client("192.168.5.100",6379); System.out.println(client.set("name","xxxx")); System.out.println(client.get("name")); }}
+OK$4xxxx