手把手教你编写入门级redis客户端

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: 既然Redis客户端已经这么丰富了,为什么还要尝试自己编写客户端?我的看法是,知己知彼,自己尝试制作Redis客户端,不仅可以加深对Redis的了解,而且可以通晓Redis客户端的原理,为今后的更好地使用、乃至定制改造Redis作好充分准备。

Redis是开源的、基于内存的数据结构存储系统,可用作数据库、缓存以及消息代理方面。Redis支持许多种数据结构,并内置了丰富的诸如冗余、脚本、事务、持久化等功能,深受业界喜爱,被各种业务系统广泛使用。为了方便使用,Redis官网推荐了针对各种编程语言的多种客户端,支持java、c#、python、c++等主流编程语言。那么大家会问,既然Redis客户端已经这么丰富了,为什么还要尝试自己编写客户端?我的看法是,知己知彼,自己尝试制作Redis客户端,不仅可以加深对Redis的了解,而且可以通晓Redis客户端的原理,为今后的更好地使用、乃至定制改造Redis作好充分准备。

知识准备

要想亲自开发Redis客户端,需要以下知识:
1、网络编程基础
2、熟悉Redis协议
3、了解Redis的基本操作
另外文中的例子将会采用java编写,因此最好有基本的java编程知识。

面向读者

本文面向Redis各层次使用者。

Redis Protocal

Redis协议被称为:RESP (REdis Serialization Protocol),客户端通过TCP协议连接到客户端的6379端口(默认端口)。
RESP协议是在Redis1.2中引入的,不过现在已经是Redis2.0中的标准协议了。所以你应该再Redis客户端中实现这个协议。

RESP描述

RESP其实是一个序列化协议,支持简单字符串、错误、整数、整块字符串和数组。数据类型依赖头文字,分别表示如下:
简单字符串的头文字是“+”
错误的头文字是“-”
整数的头文字是“:”
整块字符串的头文字是“$”
数组的头文字是“*”

RESP在请求-响应模型中的用法

-客户端向Redis服务器发送命令,命令的格式是仅以RESP整块字符串构成的数组。。
-服务器端根据命令的结果,选择适宜的一种RESP类型返回

简单字符串

简单字符串是以半角加号开头,后跟随着不含回车换行的字符串,然后以回车换行结尾。
举例如下:+OKrn
简单字符串是非二进制安全的,如果需要二进制安全,可使用“整块字符串”。

错误

错误和简单字符串类似,但头文字换成半角减号了。后面跟随的文字,可以视为错误消息内容。
举例如下:
-ERR unknown command 'foobar'
-WRONGTYPE Operation against a key holding the wrong kind of value

整数

整数与简单字符串类似,头文字为半角冒号。
举例如下:
:0rn
:1000rn

整块字符串

整块字符串可以用来标示二进制安全的、最大512MB长度的字符串。它以$符号开头,后跟随实际字符串长度,以回车换行结尾,后跟随实际字符串,再最终以回车换行结尾。
举例如下:
$6rnfoobarrn
空字符串表现形式如下:$0rnrn
nil表现形式如下:$-1rnrn

数组

数组以半角星号开头,后接数组中元素个数,然后以回车换行结尾,然后后接各个元素。
举例如下:
空数组:*0rn
包含两个整块字符串的数组:*2rn$3\r\nfoo\r\n$3rnbarrn
包含三个整数的数组:*3rn:1rn:2rn:3rn
数组还支持嵌套。

Redis客户端原理

要实现和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/yourcaptain/dudu-RESP_intepreter

maven中央仓库###:

<dependency>
  <groupId>net.yesdata</groupId>
  <artifactId>dudu-RESP-interpreter</artifactId>
  <version>1.0.4</version>
</dependency>

maven中央仓库地址

https://oss.sonatype.org/#nexus-search;classname~RESP

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
2月前
|
缓存 NoSQL Redis
【Azure Redis 缓存】Redission客户端连接Azure:客户端出现 Unable to send PING command over channel
【Azure Redis 缓存】Redission客户端连接Azure:客户端出现 Unable to send PING command over channel
|
2天前
|
NoSQL Redis 数据安全/隐私保护
Redis 最流行的图形化界面下载及使用超详细教程(带安装包)! redis windows客户端下载
文章提供了Redis最流行的图形化界面工具Another Redis Desktop Manager的下载及使用教程,包括如何下载、解压、连接Redis服务器以及使用控制台和查看数据类型详细信息。
15 6
Redis 最流行的图形化界面下载及使用超详细教程(带安装包)! redis windows客户端下载
|
2天前
|
NoSQL Redis 数据库
Redis 图形化界面下载及使用超详细教程(带安装包)! redis windows下客户端下载
文章提供了Redis图形化界面工具的下载及使用教程,包括如何连接本地Redis服务器、操作键值对、查看日志和使用命令行等功能。
23 0
Redis 图形化界面下载及使用超详细教程(带安装包)! redis windows下客户端下载
|
14天前
|
JSON NoSQL Java
redis的java客户端的使用(Jedis、SpringDataRedis、SpringBoot整合redis、redisTemplate序列化及stringRedisTemplate序列化)
这篇文章介绍了在Java中使用Redis客户端的几种方法,包括Jedis、SpringDataRedis和SpringBoot整合Redis的操作。文章详细解释了Jedis的基本使用步骤,Jedis连接池的创建和使用,以及在SpringBoot项目中如何配置和使用RedisTemplate和StringRedisTemplate。此外,还探讨了RedisTemplate序列化的两种实践方案,包括默认的JDK序列化和自定义的JSON序列化,以及StringRedisTemplate的使用,它要求键和值都必须是String类型。
redis的java客户端的使用(Jedis、SpringDataRedis、SpringBoot整合redis、redisTemplate序列化及stringRedisTemplate序列化)
|
2月前
|
NoSQL 网络协议 Linux
【AKS+Redis】AKS中客户端(ioredis)遇见Azure Redis服务Failover后链接中断的可能性
【AKS+Redis】AKS中客户端(ioredis)遇见Azure Redis服务Failover后链接中断的可能性
|
2月前
|
NoSQL 网络协议 Linux
【Azure Redis】Lettuce客户端遇见连接Azure Redis长达15分钟的超时
【Azure Redis】Lettuce客户端遇见连接Azure Redis长达15分钟的超时
|
2月前
|
NoSQL 网络协议 Linux
【Azure Redis】Redis客户端出现15分钟的超时异常
【Azure Redis】Redis客户端出现15分钟的超时异常
|
2月前
|
缓存 监控 NoSQL
【Azure Redis 缓存】Azure Redis出现了超时问题后,记录一步一步的排查出异常的客户端连接和所执行命令的步骤
【Azure Redis 缓存】Azure Redis出现了超时问题后,记录一步一步的排查出异常的客户端连接和所执行命令的步骤
|
2月前
|
缓存 NoSQL Java
【Azure Redis 缓存 Azure Cache For Redis】当使用Jedis客户端连接Redis时候,遇见JedisConnectionException: Could not get a resource from the pool / Redis connection los
【Azure Redis 缓存 Azure Cache For Redis】当使用Jedis客户端连接Redis时候,遇见JedisConnectionException: Could not get a resource from the pool / Redis connection los
102 0
|
3月前
|
JSON NoSQL Java
Redis18的Java客户端-StringRedisTemplate,序列化存在的问题,使用StringRedisTemplate解决序列化的方法
Redis18的Java客户端-StringRedisTemplate,序列化存在的问题,使用StringRedisTemplate解决序列化的方法