文档章节

Redis协议是什么样的

春哥大魔王的博客
 春哥大魔王的博客
发布于 01/20 13:49
字数 621
阅读 20
收藏 0

前言

我们用过很多redis的客户端,有没有相过自己撸一个redis客户端? 其实很简单,基于socket,监听6379端口,解析数据就可以了。

redis协议

解析数据的过程主要依赖于redis的协议了。 我们写个简单例子看下redis的协议:

public class RedisTest {
    public static void main(String[] args) {
        Jedis jedis = new Jedis("127.0.0.1", 6379);
        jedis.set("eat", "I want to eat");
    }
}

监听socket:

    public static void main(String[] args) throws IOException {
        ServerSocket server = new ServerSocket(6379);
        Socket socket = server.accept();
        byte[] chars = new byte[64];
        socket.getInputStream().read(chars);
        System.out.println(new String(chars));
    }

看下数据:

*3
$3
SET
$3
eat
$13
I want to eat

参照官方协议文档https://redis.io/topics/protocol, 解析下数据。

(1)简单字符串 Simple Strings, 以 "+"加号 开头 (2)错误 Errors, 以"-"减号 开头 (3)整数型 Integer, 以 ":" 冒号开头 (4)大字符串类型 Bulk Strings, 以 "$"美元符号开头,长度限制512M (5)组类型 Arrays,以 "*"星号开头 并且,协议的每部分都是以 "\r\n" (CRLF) 结尾的。

所以上面的数据的含义是:

*3   数组包含3个元素,分别是SET、eat、I want to eat
$3   是一个字符串,且字符串长度为3
SET  字符串的内容
$3   是一个字符串,且字符串长度为3
eat  字符串的内容
$13  是一个字符串,且字符串长度为13
I want to eat 字符串的内容

执行get 'eat'的数据如下:

*2
$3
GET
$3
eat

撸一个客户端

掌握了redis协议,socket之后,我们就可以尝试撸一个客户端了。

socket:

public RedisClient(String host, int port){
        try {
            this.socket = new Socket(host,port);
            this.outputStream = this.socket.getOutputStream();
            this.inputStream = this.socket.getInputStream();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

set协议:

    public String set(final String key, String value) {
        StringBuilder sb = new StringBuilder();
        //虽然输出的时候,会被转义,然而我们传送的时候还是要带上\r\n
        sb.append("*3").append("\r\n");
        sb.append("$3").append("\r\n");
        sb.append("SET").append("\r\n");
        sb.append("$").append(key.length()).append("\r\n");
        sb.append(key).append("\r\n");
        sb.append("$").append(value.length()).append("\r\n");
        sb.append(value).append("\r\n");
        byte[] bytes= new byte[1024];
        try {
            outputStream.write(sb.toString().getBytes());
            inputStream.read(bytes);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return new String(bytes);
    }

测试:

        RedisClient redisClient = new RedisClient("127.0.0.1", 6379);
        String result = redisClient.set("eat", "please eat");
        System.out.println(result);  

执行结果:

+OK

© 著作权归作者所有

共有 人打赏支持
春哥大魔王的博客
粉丝 22
博文 177
码字总数 126677
作品 0
海淀
程序员
私信 提问
【原创】自己动手写一个能操作redis的客户端

引言 redis大家在项目中经常会使用到。官网也提供了多语言的客户端供大家操作redis,如下图所示 但是,大家有思考过,这些语言操作redis背后的原理么?其实,某些大神会说 只要按照redis的协议...

孤独烟
2018/07/23
0
0
redis基本概念和原理

Redis简介 REmote DIctionary Server(Redis) 是一个由SalvatoreSanfilippo写的key-value存储系统。 Redis是一个开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日...

huojiao2006
2017/05/03
0
0
Redis数据库云端最佳技术实践

欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由腾讯云数据库 TencentDB发表于云+社区专栏 邹鹏,腾讯高级工程师,腾讯云数据库Redis负责人,多年数据库、网络安全研发经验...

腾讯云加社区
2018/11/06
0
0
SSDB 支持 Redis 协议!

终于, SSDB 支持 Redis 协议了! 这表示, 你可以用目前所有成熟的 Redis 客户端来连接 SSDB 服务器, 包括 hiredis, phpredis, redigo 等等. SSDB 支持 Redis 网络协议, 既是一个技术问题, 也有...

ideawu
2014/01/26
1K
7
Go-redis-server

Go-redis-server 是使用 Go 实现 Redis 服务协议的开发包。 有许多客户端能够实现 redis 协议,但很多服务器不能实现。 go-redis-server 不仅能通过 redis 协议,帮助构建服务器软件;还能够...

大胖森
2015/05/12
829
0

没有更多内容

加载失败,请刷新页面

加载更多

学习设计模式之路

https://java-design-patterns.com/patterns/ https://www.oodesign.com/ https://www.programering.com/a/MTNxAzMwATY.html https://design-patterns.readthedocs.io/zh_CN/latest/ https:/......

晨猫
今天
1
0
JDK1.8 jar包说明

JDK 1.8 lib:access-bridge-64.jarcharsets.jarcldrdata.jardeploy.jardnsns.jarjaccess.jarjavawa.jarjce.jarjfr.jarjfxrt.jarjfxswt.jarjsse.jarlocaledata.jar......

冷基
今天
1
0
判断用户的icloud是否开启【Swift4.2】

使用icloudkit存储用户私人数据时,必须判断用户的icloud是否开启【Swift4.2】 func isICloudContainerAvailable()-> Bool { if FileManager.default.ubiquityIdentityToken != ni......

叶落花开
今天
2
0
今天的学习

1、执行git add *命令就把改动提交到了暂存区,执行git pull命令将远程仓库的数据拉到当前分支并合并,执行git checkout [branch-name]切换分支 2、执行git commit -m '说明' 命令就把改动提...

墨冥
昨天
0
0
Android4.4 及以下TextView,Button等控件使用矢量图报错

1 问题描述 最近项目开发中,图标资源我尽量使用了矢量图,然而配置了基本的兼容设置,程序在低版本中运行还是出现了问题。 xml布局文件中,在TextView中使用矢量图,比如android:drawableS...

newtrek
昨天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部