Redis是开源的、基于内存的数据结构存储系统,可用做数据库、缓存以及消息代理方面。Redis支持许多种数据结构,并内置了丰富的诸如冗余、脚本、事务、持久化等功能,深受业界喜好,被各类业务系统普遍使用。为了方便使用,Redis官网推荐了针对各类编程语言的多种客户端,支持java、c#、python、c++等主流编程语言。那么你们会问,既然Redis客户端已经这么丰富了,为何还要尝试本身编写客户端?个人见解是,知己知彼,本身尝试制做Redis客户端,不只能够加深对Redis的了解,并且能够通晓Redis客户端的原理,为从此的更好地使用、乃至定制改造Redis做好充分准备。java
要想亲自开发Redis客户端,须要如下知识:
一、网络编程基础
二、熟悉Redis协议
三、了解Redis的基本操做
另外文中的例子将会采用java编写,所以最好有基本的java编程知识。python
本文面向Redis各层次使用者。c++
Redis协议被称为:RESP (REdis Serialization Protocol),客户端经过TCP协议链接到客户端的6379端口(默认端口)。
RESP协议是在Redis1.2中引入的,不过如今已是Redis2.0中的标准协议了。因此你应该再Redis客户端中实现这个协议。git
RESP实际上是一个序列化协议,支持简单字符串、错误、整数、整块字符串和数组。数据类型依赖头文字,分别表示以下:
简单字符串的头文字是“+”
错误的头文字是“-”
整数的头文字是“:”
整块字符串的头文字是“$”
数组的头文字是“*”github
客户端向Redis服务器发送命令,以RESP整块字符串数组的形式。redis
服务器端根据命令的结果,选择适宜的一种RESP类型返回数据库
简单字符串是以半角加号开头,后跟随着不含回车换行的字符串,而后以回车换行结尾。
举例以下:+OK\r\n
简单字符串是非二进制安全的,若是须要二进制安全,可以使用“整块字符串”。编程
错误和简单字符串相似,但头文字换成半角减号了。后面跟随的文字,能够视为错误消息内容。
举例以下:
-ERR unknown command 'foobar'
-WRONGTYPE Operation against a key holding the wrong kind of valuec#
整数与简单字符串相似,头文字为半角冒号。
举例以下:
:0\r\n
:1000\r\n数组
整块字符串能够用来标示二进制安全的、最大512MB长度的字符串。它以$符号开头,后跟随实际字符串长度,以回车换行结尾,后跟随实际字符串,再最终以回车换行结尾。
举例以下:
$6\r\nfoobar\r\n
空字符串表现形式以下:$0\r\n\r\n
nil表现形式以下:$-1\r\n\r\n
数组以半角星号开头,后接数组中元素个数,而后以回车换行结尾,而后后接各个元素。
举例以下:
空数组:*0\r\n
包含两个整块字符串的数组:*2\r\n$3\r\nfoo\r\n$3\r\nbar\r\n
包含三个整数的数组:*3\r\n:1\r\n:2\r\n:3\r\n
数组还支持嵌套。
要实现和Redis服务端通讯,首先须要与Redis服务端创建TCP通讯链接,而后使用上述的RESP协议,将想要执行的Redis命令发送至服务端,并等待服务端响应,而后接收到响应结果,展现给用户。
如下代码实现了一个简单的获取info的操做。
package my_redis_client; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.Socket; import java.nio.CharBuffer; /** * Hello world! * */ public class App { public static void main( String[] args ) { //定义redis服务端默认端口 int port = 6379; Socket socket = null; BufferedReader in = null; PrintWriter out = null; try { //建立tcp链接 socket = new Socket("localhost", port); in = new BufferedReader(new InputStreamReader(socket.getInputStream())); out = new PrintWriter(socket.getOutputStream(), true); //传送info命令 //客户端向Redis服务器发送命令,以RESP整块字符串数组的形式 out.println("*1\r\n$4\r\ninfo\r\n"); System.out.println("Redis command wat sent successfully."); //接收服务器的回复 CharBuffer response = CharBuffer.allocate(1024); int readedLen = in.read(response); String responseBody = response.flip().toString(); //输出服务器的回复 System.out.println(responseBody); } catch(Exception e) { e.printStackTrace(); } finally { //最后关闭相关的流 if (out != null){ out.close(); out = null; } if (in != null) { try { in.close(); } catch(IOException e){ e.printStackTrace(); } in = null; } if (socket != null) { try { socket.close(); } catch(IOException e){ e.printStackTrace(); } socket = null; } } } }
运行后,系统将会在命令行界面输出info的执行结果。
根据上述代码所描述的方法,就能够继续扩展客户端的功能,实现Redis各类命令了。
https://github.com/yourcaptai...
<dependency> <groupId>net.yesdata</groupId> <artifactId>dudu-RESP-interpreter</artifactId> <version>1.0.4</version> </dependency>