当前位置: 首页 > 后端技术 > PHP

使用Go实现Redis4.实现上篇文章写的Redis协议交互

时间:2023-03-30 03:42:02 PHP

本文实现的Godis代码版本为:v0.0.3前三篇分别是client/server交互(基于textprotoco)、server端Initialization和get/set命令。如果你阅读过或调试过一个粗略的代码实现,你会发现使用文本协议进行交互不仅易读,而且解析效率比较低。因为我们的例子是“setalpha123n”,一个整齐的单空格和n划分可能划分效率更高;如果需要拆分,必然效率低下。在本文中,Redis1.2版本后,文本协议将替换为统一协议。Redis通信协议Redis通信协议分析高效,二进制安全,对人类友好(可以直接阅读分析)。协议格式Redis使用同一套标准协议来发送命令和返回结果。Reids协议是“肉眼可见的”。发送命令时,使用“multibulkreply”协议类型,回复时根据结果使用不同类型的协议。通过检查服务器发回的数据的第一个字节,可以判断是什么类型的回复:状态回复(statusreply)的第一个字节是“+”,错误回复(errorreply)的第一个字节)是“-”整数回复(integerreply)的第一个字节是“:”批量回复(bulkreply)的第一个字节是“$”多批量回复(multibulkreply)的第一个字节是“*”举两个例子:1、客户端执行命令“setalpha123”,服务器返回“OK”。约定的结果反馈给用户。2、客户端执行命令“setalpha123”,发送给服务端时也是按照协议格式进行交互。如前所述,发送命令使用“多批回复”类型协议,封装命令为*3\r\n$3\r\nset\r\n$5\r\nalpha\r\n$3\r\n123\r\n对应的ASCII码如下:符号'*'表示协议类型为多批回复,"rn"为元素分段标记;'$'表示后面是批量回复协议,要按照批量回复格式解析;'3'表示批量回复长度为3个字节;“set”为批量回复协议的内容;重复2-4直到协议分析完成。可以看出,协议的生成和解析可以简化理解为两个文本处理过程。Godis实现Redis通信协议GO版本协议实现初步探索很多Redis相关的GO组件、模块、工具都有协议生成和解析实现,并经过了生产环境的测试。比如go-redis、codis等知名项目。不考虑性能和可扩展性,协议生成的GO代码可以这样实现://将命令行转换为协议funcCmd2Protocol(cmdstring)(prostring){//cmd:="setalpha123"ret:=字符串。Split(cmd,"")//todovalidatecmdandparamsfork,v:=rangeret{ifk==0{pro=fmt.Sprintf("*%d\r\n",len(ret))}pro+=fmt.Sprintf("$%d\r\n%s\r\n",len(v),v)}return}上面的代码可以将命令“setalpha123”转换为Redis标准协议格式。对协议的解析可以拆解成以下过程:以前面的例子为例,拆解过程如下:最后的操作只是单一数据类型解析,数字解析将数字转为文本,文本解析读取字节数对应的字符。能。//将协议转换为argc,argvfuncProtocol2Args(protocolstring)(argv[]string,argcint){parts:=strings.Split(strings.Trim(protocol,""),"\r\n")iflen(parts)==0{returnnil,0}argc,err:=strconv.Atoi(parts[0][1:])iferr!=nil{returnnil,0}j:=0varvlen[]intfor_,v:=rangeparts[1:]{iflen(v)==0{continue}ifv[0]=='$'{tmpl,err:=strconv.Atoi(v[1:])如果err==nil{vlen=append(vlen,tmpl)}}else{ifj