news 2026/4/16 8:43:46

Redis 协议兼容:编写一个支持 RESP 协议的 KV Server

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Redis 协议兼容:编写一个支持 RESP 协议的 KV Server

标签:#Redis #RESP #Go语言 #网络编程 #中间件开发 #Socket


📜 一、 破译 RESP:Redis 的通信语言

RESP 是一个基于文本的协议,极其简单且高效。它主要由前缀符号CRLF (\r\n)组成。

客户端发送给服务端的,永远是一个RESP 数组 (Array),其中包含了命令和参数。

核心数据类型:
类型前缀示例含义
简单字符串++OK\r\n操作成功
错误--Error message\r\n报错
整数::100\r\n数字结果
多行字符串$$5\r\nhello\r\n字符串 “hello” (长度5)
数组**2\r\n$3\r\nGET\r\n$1\r\na\r\n命令数组["GET", "a"]

举个栗子:
当你输入SET name gemini时,客户端实际发送的是:

*3\r\n (数组长度 3) $3\r\nSET\r\n (第一个元素,长度3,内容SET) $4\r\nname\r\n (第二个元素,长度4,内容name) $6\r\ngemini\r\n (第三个元素,长度6,内容gemini)

🏗️ 二、 架构设计:从 Socket 到存储

我们要实现的 Server 架构非常清晰:

TCP Socket

服务端内部逻辑

Accept

Read Bytes

Command Object

Response Object

Write Bytes

TCP Listener (Port 6379)

Connection Handler

RESP 解析器

命令执行引擎 (Map)

RESP 序列化器

redis-cli (客户端)

你的 Go 程序


💻 三、 代码实战:Go 语言实现

为了保持代码简洁,我们只实现最核心的SETGET命令。

1. 编写 RESP 解析器 (Parser)

这是最难的部分。我们需要读取流,解析出*开头的数组。

packagemainimport("bufio""fmt""io""net""strconv""strings""sync")// 内存数据库,简单的并发安全 MapvarkvStore=struct{sync.RWMutex mmap[string]string}{m:make(map[string]string)}funcmain(){// 1. 启动 TCP 监听listener,err:=net.Listen("tcp",":6379")iferr!=nil{fmt.Println("Error starting server:",err)return}fmt.Println("🚀 Mini-Redis is running on port 6379...")for{conn,err:=listener.Accept()iferr!=nil{continue}// 为每个连接启动一个协程gohandleConnection(conn)}}funchandleConnection(conn net.Conn){deferconn.Close()reader:=bufio.NewReader(conn)for{// 2. 解析 RESP 协议 (简化版,只处理 Arrays)// 读取第一个字节,必须是 '*'prefix,err:=reader.ReadByte()iferr==io.EOF{break}ifprefix!='*'{// 这里简单处理,忽略非数组请求或 pingreader.ReadString('\n')continue}// 读取数组长度line,_:=reader.ReadString('\n')arrLen,_:=strconv.Atoi(strings.TrimSpace(line))// 读取命令参数args:=make([]string,0,arrLen)fori:=0;i<arrLen;i++{// 读取多行字符串前缀 '$'reader.ReadByte()// 读取长度line,_=reader.ReadString('\n')strLen,_:=strconv.Atoi(strings.TrimSpace(line))// 读取实际内容buf:=make([]byte,strLen)io.ReadFull(reader,buf)args=append(args,string(buf))// 读取末尾的 CRLFreader.ReadString('\n')}// 3. 执行命令response:=executeCommand(args)// 4. 发送响应conn.Write([]byte(response))}}
2. 编写命令执行引擎 (Handler)

这里处理业务逻辑,并返回符合 RESP 格式的字符串。

funcexecuteCommand(args[]string)string{iflen(args)==0{return"-ERR empty command\r\n"}cmd:=strings.ToUpper(args[0])switchcmd{case"PING":return"+PONG\r\n"case"SET":iflen(args)!=3{return"-ERR wrong number of arguments for 'set' command\r\n"}key,val:=args[1],args[2]kvStore.Lock()kvStore.m[key]=val kvStore.Unlock()return"+OK\r\n"// 简单字符串case"GET":iflen(args)!=2{return"-ERR wrong number of arguments for 'get' command\r\n"}key:=args[1]kvStore.RLock()val,ok:=kvStore.m[key]kvStore.RUnlock()if!ok{return"$-1\r\n"// Null Bulk String (表示不存在)}// 返回 Bulk Stringreturnfmt.Sprintf("$%d\r\n%s\r\n",len(val),val)default:returnfmt.Sprintf("-ERR unknown command '%s'\r\n",cmd)}}

🎩 四、 见证奇迹时刻

1. 运行你的服务端
go run main.go# 输出: 🚀 Mini-Redis is running on port 6379...
2. 使用官方 Redis-CLI 连接

打开一个新的终端窗口:

redis-cli -p6379

输入命令测试:

127.0.0.1:6379>PING PONG127.0.0.1:6379>SET user gemini OK127.0.0.1:6379>GET user"gemini"127.0.0.1:6379>GET unknown(nil)

成功了!你的程序现在“骗”过了官方客户端,它以为自己在跟真正的 Redis 对话。


🔍 五、 为什么这很重要?

掌握 RESP 协议解析,意味着你拥有了开发以下系统的能力:

  1. Redis Proxy (代理):像 Twemproxy 或 Codis 一样,拦截客户端请求,实现分片(Sharding)或读写分离。
  2. 兼容 Redis 的新数据库:比如你可以用 RocksDB 做底层存储,外面套一层 RESP 协议,做一个持久化的“大容量 Redis”。
  3. 流量录制与回放:通过解析 RESP 流量,分析热 Key 或进行故障复现。

🎯 总结

Redis 之所以流行,除了它快,还因为它简单的协议设计。RESP 协议通过简单的文本规则,实现了高性能与易读性的平衡。
今天的代码虽然简单,但它已经包含了一个数据库中间件的雏形:监听 -> 解析 -> 路由 -> 执行 -> 响应

Next Step:
目前的解析器是同步阻塞的,效率较低。
尝试引入 Go 的bufioScanner机制,或者尝试支持PIPELINE(一次发送多条命令),这将极大提升你的 Server 吞吐量。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/10 18:31:11

XMLHttpRequest 从入门到实战:GET/POST 请求完整案例

一、前言 在前后端分离开发模式中&#xff0c;AJAX 是实现页面无刷新数据交互的核心技术&#xff0c;而 XMLHttpRequest&#xff08;简称 XHR&#xff09;正是浏览器原生支持的 AJAX 底层 API。 相比于现代的 fetch 和 Axios&#xff0c;XMLHttpRequest 兼容性更好&#xff0…

作者头像 李华
网站建设 2026/4/15 16:03:35

基于Java的家政搬家智慧管理系统的设计与实现全方位解析:附毕设论文+源代码

1. 为什么这个毕设项目值得你 pick ? 家政搬家智慧管理系统的主要功能模块包括会员管理、订单管理等23个子系统&#xff0c;覆盖了从客户注册到售后服务的全流程。开发背景分析基于传统管理模式效率低下且无法提供个性化服务的实际问题。创新性在于将现代技术与实际需求相结合…

作者头像 李华
网站建设 2026/4/15 11:42:59

【开题答辩全过程】以地铁安全管理信息系统设计与实现为例,包含答辩的问题和答案

个人简介一名14年经验的资深毕设内行人&#xff0c;语言擅长Java、php、微信小程序、Python、Golang、安卓Android等开发项目包括大数据、深度学习、网站、小程序、安卓、算法。平常会做一些项目定制化开发、代码讲解、答辩教学、文档编写、也懂一些降重方面的技巧。感谢大家的…

作者头像 李华
网站建设 2026/4/12 13:35:23

从 2025 到 2026,Berachain 的“攻”与“守”

​——当 L1 不再靠叙事生存&#xff0c;它还能做什么&#xff1f;2025 年成为 L1 赛道发展的关键分水岭。早期依赖技术先行的叙事——不断追求更高的 TPS、更低的 Gas 成本——已经难以继续支撑估值扩张。基础设施本身并未失去价值&#xff0c;但它不再自动等价于代币价值&…

作者头像 李华
网站建设 2026/3/26 20:20:46

服装管理订单ERP是什么?主要包括哪些功能?

服装管理订单ERP系统的功能解析与应用 服装管理订单ERP系统是一款专为服装电商行业设计的综合软件&#xff0c;它集成了多个功能模块&#xff0c;包括进销存管理、发货管理、财务管理和商品管理。这些模块相互连接&#xff0c;形成了一个高效的运营平台。进销存管理能够实时监控…

作者头像 李华
网站建设 2026/3/28 10:35:13

学长亲荐9个AI论文写作软件,专科生轻松搞定毕业论文!

学长亲荐9个AI论文写作软件&#xff0c;专科生轻松搞定毕业论文&#xff01; 专科生的论文救星&#xff0c;AI 工具如何改变你的写作方式 对于许多专科生来说&#xff0c;毕业论文既是一道门槛&#xff0c;也是一次挑战。尤其是在时间紧张、资料匮乏、写作经验不足的情况下&…

作者头像 李华