Write a redis client, so easy ~

Java technology stack 2020-11-09 12:27:59
write redis client easy


Preface

This article is very simple , Just write a Java Version of Redis Client, And it's not a production level project , It's just a validation type demo. Used to understand “ Achieve one Redis Client” What should I pay attention to .

reflection

  1. First ,Redis It's a server , Yes ip, There are ports , that , We can use it Java Of Socket To interact with him , It can also be used. telnet To interact . To put it bluntly , It's just one. TCP The server , Just open it TCP passageway , And then make a connection 3 The second handshake , Set up a full duplex channel , You can send data to each other .

  2. From our previous programming experience , That's true. , Interact with a server , It usually requires an agreement , for example HTTP The server , You need HTTP agreement , and Dubbo Interaction , You need to understand Dubbo agreement , Of course , These are all based on TCP Above the agreement . that ,Redis Maybe there is an agreement , Let's see later .

Hands on

Thinking about the two points above , We can try to do it .

We can use telnet Visit the following local Redis Server, for example :telnet 127.0.0.1 6379, as follows :

* master telnet 127.0.0.1 6379
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^\]'.
set baby hello
+OK
get baby
$5
hello
del baby
:1
xxx
-ERR unknown command 'xxx'

step :

  1. We're connected to the local Redis Server.

  2. perform set baby hello command , That is to save a key value pair .

  3. Back to +OK character string

  4. And then we get the just baby character string .

  5. Back to $5 Line break hello

  6. And then we deleted baby character string .

  7. Back to :1 ,1 Indicates that the deletion was successful .

  8. Then we try to execute a command that doesn't exist .

  9. Back to -ERR unknown command 'xxx'.

We use Redis Official redis-cli The client executes these commands and looks at the results :

* master redis-cli
127.0.0.1:6379> set baby hello
OK
127.0.0.1:6379> get baby
"hello"
127.0.0.1:6379> del baby
(integer) 1
127.0.0.1:6379> xxx
(error) ERR unknown command 'xxx'
127.0.0.1:6379>

Obviously ,redis-cli Client and telnet The difference between the use of the return value is the difference of the return value ,telnet There are some strange characters , Or in front of some return values, add some match , For example, in OK I added + Number . stay get baby after , Returned a $5 character string . We conjecture that ,telnet The data is Redis-Server The real data returned ,redis-cli These data are processed .

Okay , I have a general understanding of the operation , We use it Java Write a Socket Visit Redis Server.

use Java Socket visit Redis Server

The code is simple , as follows :

static Socket client = new Socket();
static InputStream is;
static OutputStream os;
static {
try {
client.connect(new InetSocketAddress("127.0.0.1", 6379));
is = client.getInputStream();
os = client.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws IOException {
writeAndFlush("set baby hello \\n");
printResult();
// result : +OK
writeAndFlush("get baby \\n");
Sleep.sleep(1);// etc. redis Return the data 
printResult();
// result : $5
// result : hello
writeAndFlush("del baby \\n");
Sleep.sleep(1);// etc. redis Return the data 
printResult();
// result :1
writeAndFlush("xxx \\n");
Sleep.sleep(1);// etc. redis Return the data 
printResult();
// -ERR unknown command \`xxx\`, with args beginning with:
writeAndFlush("mget hello baby \\r\\n");
Sleep.sleep(1);
printResult();
closeStream();
}
static void writeAndFlush(String content) {
try {
os.write(content.getBytes());
os.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void closeStream() {
try {
is.close();
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
static void printResult() {
try {
int a = is.available();
byte[] b = new byte[a];
is.read(b);
String result = new String(b);
System.out.println(result);
} catch (Exception e) {
e.printStackTrace();
}
}

You can see , Use Java Socket And use telnet The effect is the same .

therefore , To achieve redis-cli The effect of , Then we need to process the return value , for example $5 、:1 These symbols , What does it mean ? namely : analysis redis Own application layer protocol .

Redis Serialization protocol (RESP)

The answer lies in redis Official documents of , Communication protocol protocol: http://redisdoc.com/topic/protocol.html)

redis The agreement calls it RESP(REdis Serialization Protocol), namely redis Serialization protocol .

The design objective of the protocol is :

  1. Implement a simple .

  2. Fast parsing .

  3. Human readability .

All orders are in the form of \r\n ending .

Redis After receiving the order , Processing commands , Then return the data .

redis 1.2 After version , Support batch reply :Buik Reply.

About reply , There are many types of :
By checking the first byte of data the server sends back , Can you determine what type of response this is :

  • State the reply (status reply) The first byte of "+"

  • Error response (error reply) The first byte of "-"

  • Integer reply (integer reply) The first byte of ":"

  • Batch reply (bulk reply) The first byte of "$"

  • Multiple batch replies (multi bulk reply) The first byte of "*"

We go back to our Socket In the app , You can see ,

  • When I perform set command , The return is +OK, That is, this is the status reply .

  • When we execute xxx command , The return value begins with - Number , This is the wrong reply .

  • When we execute get command , The return is $5 hello, This is a batch reply , meanwhile 5 Indicates that it will return later 5 Bytes . The maximum length of a string is 512 MB.

  • When we execute del command , The return is :1, This is an integer reply , Only when the operation is actually executed , To return to 1 , Otherwise return to 0, 1 Express true.

  • When we execute mget hello baby \r\n when , The first character returned is * Number , It means that this is a batch reply .* The value after the sign records the number of multiple replies , What we're returning here is *2\r\n $5\r\n� world \r\n $-1\r\n, *2 It means that there is 2 A reply .$5 It means that there is 5 Bytes . $-1 Express baby This key There's no data ,-1 It means nothing .

Through the analysis of the agreement , We can make something like redis-cli The client of .

I'd like to introduce jade here , Wrote the simplest , Just look at it :)

public static void respParseHandler(String result) {
try {
if (result.startsWith("+")) {
// State the reply 
System.out.println(result.substring(1));
return;
}
if (result.startsWith("-")) {
// Error response 
System.err.println(result.substring(1));
return;
}
if (result.startsWith(":")) {
// Integer reply 
if (result.substring(1).equalsIgnoreCase("1")) {
System.out.println("success");
} else {
System.out.println("error");
}
return;
}
if (result.startsWith("$")) {
// Batch reply 
if (result.substring(1, 3).equalsIgnoreCase("-1")) {
System.out.println("no data, redis return -1");
return;
}
int line = result.indexOf("\\r\\n");
System.out.println(result.substring(line + 2));
return;
}
if (result.startsWith("*")) {
// Multiple batch replies 
char num = result.charAt(1);
int first = result.indexOf('$');
for (int i = 0; i < Integer.valueOf(String.valueOf(num)); i++) {
int next = result.indexOf('$', first + 1);
if (next != -1) {
respParseHandler(result.substring(first, next));
} else {
respParseHandler(result.substring(first));
}
first = next;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}

author : Mona Lu Road
link :https://www.jianshu.com/p/1aab4cbe4c3b
Recent hot article recommends :

1.Java 15 Official release , 14 A new feature , Refresh your mind !!

2. Finally, I got it through open source projects IntelliJ IDEA Activation code , It's delicious !

3. I use Java 8 Wrote a piece of logic , I can't understand it , You try ..

4. To hang up Tomcat ,Undertow It's very powerful !!

5.《Java Development Manual ( Song Mountain version )》 The latest release , Download it quickly !

I think it's good , Don't forget to like it + Forward !

版权声明
本文为[Java technology stack]所创,转载请带上原文链接,感谢

  1. 【计算机网络 12(1),尚学堂马士兵Java视频教程
  2. 【程序猿历程,史上最全的Java面试题集锦在这里
  3. 【程序猿历程(1),Javaweb视频教程百度云
  4. Notes on MySQL 45 lectures (1-7)
  5. [computer network 12 (1), Shang Xuetang Ma soldier java video tutorial
  6. The most complete collection of Java interview questions in history is here
  7. [process of program ape (1), JavaWeb video tutorial, baidu cloud
  8. Notes on MySQL 45 lectures (1-7)
  9. 精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件
  10. Refined spring boot 03: spring boot configuration files and configuration management, and reading configuration files in three ways
  11. 精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件
  12. Refined spring boot 03: spring boot configuration files and configuration management, and reading configuration files in three ways
  13. 【递归,Java传智播客笔记
  14. [recursion, Java intelligence podcast notes
  15. [adhere to painting for 386 days] the beginning of spring of 24 solar terms
  16. K8S系列第八篇(Service、EndPoints以及高可用kubeadm部署)
  17. K8s Series Part 8 (service, endpoints and high availability kubeadm deployment)
  18. 【重识 HTML (3),350道Java面试真题分享
  19. 【重识 HTML (2),Java并发编程必会的多线程你竟然还不会
  20. 【重识 HTML (1),二本Java小菜鸟4面字节跳动被秒成渣渣
  21. [re recognize HTML (3) and share 350 real Java interview questions
  22. [re recognize HTML (2). Multithreading is a must for Java Concurrent Programming. How dare you not
  23. [re recognize HTML (1), two Java rookies' 4-sided bytes beat and become slag in seconds
  24. 造轮子系列之RPC 1:如何从零开始开发RPC框架
  25. RPC 1: how to develop RPC framework from scratch
  26. 造轮子系列之RPC 1:如何从零开始开发RPC框架
  27. RPC 1: how to develop RPC framework from scratch
  28. 一次性捋清楚吧,对乱糟糟的,Spring事务扩展机制
  29. 一文彻底弄懂如何选择抽象类还是接口,连续四年百度Java岗必问面试题
  30. Redis常用命令
  31. 一双拖鞋引发的血案,狂神说Java系列笔记
  32. 一、mysql基础安装
  33. 一位程序员的独白:尽管我一生坎坷,Java框架面试基础
  34. Clear it all at once. For the messy, spring transaction extension mechanism
  35. A thorough understanding of how to choose abstract classes or interfaces, baidu Java post must ask interview questions for four consecutive years
  36. Redis common commands
  37. A pair of slippers triggered the murder, crazy God said java series notes
  38. 1、 MySQL basic installation
  39. Monologue of a programmer: despite my ups and downs in my life, Java framework is the foundation of interview
  40. 【大厂面试】三面三问Spring循环依赖,请一定要把这篇看完(建议收藏)
  41. 一线互联网企业中,springboot入门项目
  42. 一篇文带你入门SSM框架Spring开发,帮你快速拿Offer
  43. 【面试资料】Java全集、微服务、大数据、数据结构与算法、机器学习知识最全总结,283页pdf
  44. 【leetcode刷题】24.数组中重复的数字——Java版
  45. 【leetcode刷题】23.对称二叉树——Java版
  46. 【leetcode刷题】22.二叉树的中序遍历——Java版
  47. 【leetcode刷题】21.三数之和——Java版
  48. 【leetcode刷题】20.最长回文子串——Java版
  49. 【leetcode刷题】19.回文链表——Java版
  50. 【leetcode刷题】18.反转链表——Java版
  51. 【leetcode刷题】17.相交链表——Java&python版
  52. 【leetcode刷题】16.环形链表——Java版
  53. 【leetcode刷题】15.汉明距离——Java版
  54. 【leetcode刷题】14.找到所有数组中消失的数字——Java版
  55. 【leetcode刷题】13.比特位计数——Java版
  56. oracle控制用户权限命令
  57. 三年Java开发,继阿里,鲁班二期Java架构师
  58. Oracle必须要启动的服务
  59. 万字长文!深入剖析HashMap,Java基础笔试题大全带答案
  60. 一问Kafka就心慌?我却凭着这份,图灵学院vip课程百度云