golang实现简单的reids服务2

golang实现redis兼容的redis服务

  • 之前做的redis服务是通过tcp封装的自定义协议

原版项目地址:https://github.com/dengjiayue/my-redis.git

  • 那么能不能实现一个redis兼容的redis服务,这样一般的redis包也可以调用我们写的redis服务了呢?

当然可以,需要实现redis的RESP通信协议

新版项目地址: https://github.com/dengjiayue/my-redis-v2.0-RESP-.git

实现redis兼容的redis服务思路

  • 原本的数据处理模型不变,依旧使用单线程模型,map储存数据
  • 实现RESP协议的支持就可以了
    首先,我们需要知道redis一般收到的读写命令是什么样的去搞清楚RESP协议的原理

读

复制代码
"*2\r\n$3\r\nget\r\n$4\r\nname\r\n"

写

复制代码
"*3\r\n$3\r\nset\r\n$4\r\nname\r\n$8\r\nzhangsan\r\n"

RESP使用\r\n作为换行符

*2,*3表示命令的个数

一个命令包含前面一个命令数据的长度,比如$3 表示后面的数据长度为3; 然后在长度下一行才是数据;

一般第一个是方法名set,get什么的,第二个是key值,第三个是val值(如果是get就没有第三个),后面是过期时间什么的.

明白了工作原理我们就可以封装RESP协议支持了

  1. 根据换行符解析每一行数据
  2. 先解析第一行,获取整个请求的包含多少个命令
  3. 再解析每一个命令
  4. 先解析长度,再解析数据,
  5. 最后根据数据中的方法,key,val等消息做数据处理
  6. 封装返回:成功就返回"+{msg}\r\n",msg为处理结果;失败就返回"-Err {msg}\r\n",msg 为失败的信息

这样你就可以通过golang的redis包调用你的redis服务了

使用go-redis包做测试

go 复制代码
import (
	"context"
	"fmt"
	"time"

	"github.com/go-redis/redis/v8"
)

// 新建连接池
func NewPool() *redis.Client {
	return redis.NewClient(&redis.Options{
		Addr:         "localhost:8080",
		PoolSize:     1,
		MinIdleConns: 1,
	})
}

// 写入redis
func WriteRedis(client *redis.Client) {
	ctx := context.Background()
	// 写入redis
	rsp, err := client.Set(ctx, "name", "tom", time.Minute).Result()
	if err != nil {
		panic(err)
	}
	fmt.Println(rsp)
}

// 读取redis
func ReadRedis(client *redis.Client) {
	ctx := context.Background()
	// 读取redis
	rsp, err := client.Get(ctx, "name").Result()
	if err != nil {
		panic(err)
	}
	fmt.Println(rsp)
}

func TestWriteRedis(t *testing.T) {
	type args struct {
		client *redis.Client
	}
	tests := []struct {
		name string
		args args
	}{
		// TODO: Add test cases.
		{"test", args{NewPool()}},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			WriteRedis(tt.args.client)
		})
	}
}

func TestReadRedis(t *testing.T) {
	type args struct {
		client *redis.Client
	}
	tests := []struct {
		name string
		args args
	}{
		// TODO: Add test cases.
		{"test", args{NewPool()}},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			ReadRedis(tt.args.client)
			defer tt.args.client.Close()
		})
	}
}

// 读写测试
func TestReadWriteRedis(t *testing.T) {
	type args struct {
		client *redis.Client
	}
	tests := []struct {
		name string
		args args
	}{
		// TODO: Add test cases.
		{"test", args{NewPool()}},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			WriteRedis(tt.args.client)
			ReadRedis(tt.args.client)
			defer tt.args.client.Close()
		})
	}
}

// 读写测试
func TestReadWriteRedis(t *testing.T) {
	type args struct {
		client *redis.Client
	}
	tests := []struct {
		name string
		args args
	}{
		// TODO: Add test cases.
		{"test", args{NewPool()}},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			WriteRedis(tt.args.client)
			ReadRedis(tt.args.client)
			defer tt.args.client.Close()
		})
	}
}

读写结果

复制代码
=== RUN   TestReadWriteRedis
=== RUN   TestReadWriteRedis/test
OK
tom
--- PASS: TestReadWriteRedis/test (0.00s)
--- PASS: TestReadWriteRedis (0.00s)
PASS
ok      redis_performance_test/go_redis_read_write      0.756s

仓库地址: https://github.com/dengjiayue/my-redis-v2.0-RESP-.git

相关推荐
熊猫钓鱼>_>19 分钟前
三方库 NDK 原生模块跨平台适配与调试【鸿蒙心迹】
开发语言·华为·ai编程·harmonyos·鸿蒙·openharmony·鸿蒙心迹
HANDY0920025 分钟前
从“不照人”到“剂量达标”:扇叶遮挡式UV-C空气消毒的工程边界与可验证评估框架
开发语言·人工智能·嵌入式硬件·智能家居
十二同学啊41 分钟前
Go 工程化详解:项目结构、代码规范、测试体系与 CI/CD 实践
ci/cd·golang·代码规范
1024奇点9 小时前
【仓颉语言入门 · 第二篇 第 22 课】
开发语言·ide·开源
Warren2Lynch10 小时前
C4 模型详解:利用 Visual Paradigm 可视化软件架构的综合指南
开发语言·uml
Knight_AL11 小时前
Java 文件下载时文件名中的 `#` 被转换成 `%23`?一次 URL 编码与解码问题排查
java·开发语言
利威尔xu11 小时前
Go IM 源码实战(14):本地缓存快 3000 倍,失效却难 10 倍
后端·缓存·微服务·面试·golang
FRing0312 小时前
vue2干货总结2(v-bind、v-for、v-model、指令修饰符、v-bind操作class和style)
开发语言·前端·vue.js·vue2
by2099912 小时前
C++ 智能指针的所有权与使用
开发语言·c++·经验分享
砚底藏山河12 小时前
python量化自定义周期 K 线合成
java·开发语言·数据库·python·金融