Go-redis源码解析
本文对github上的go实现的redis客户端源码解析。
顾名思义,redis客户端作用是把redis命令发送到redis后端服务器执行,服务器执行完毕后将该次结果返回给客户端。从技术实现上来讲,首先客户端建立一条连接到redis后端的连接, 然后将要执行的redis命令及输入的key,value等参数,以和服务端约定的RESP协议编码为字符串数据,再把数据写入连接来向redis服务器发送命令数据,待服务端收到命令数据处理完毕后把回复字符串写入该连接,客户端即可通过连接读取到回复,再根据RESP通信协议解码返回的字符串数据则可得到服务端命令回复。
Go-redis的实现更为复杂些,首先,维护一个连接池来创建并管理多个连向服务端的连接,客户端每次执行一个redis命令时可直接从连接池中取一个空闲连接,命令执行完毕后再将连接放回到连接池中。其次,它还通过我们常用的增加过滤器(或者middleware)接口的方式,提供我们在每个redis命令发送到服务端执行前后增加自定义的处理逻辑。给每个执行命令增加的功能。源码主要通过创建并初始化一个Client结构体来实现整个客户端功能,Client结构体中有baseClient、cmdable、hooksMixin三个字段,分别对应连接池、具体的redis命令调用函数、过滤器三部分。下图描绘了整个Client结构初始化和执行某个命令的函数调用图.
hooksMixin:类似各种后端Web框架中的过滤器(middleware,洋葱结构)。通过调用AddHook函数增加新的Hook到处理链中,同时每次调用chain函数重组成一条新的hooks结构的处理链,Hook“吃一个“旧DialHook”吐一个“新DialHook出来,”吃一个“ProcessHook吐一个ProcessHook出来,最后一次吐出来的存储在current中作为执行redis命令调用入口。
最终组成如下的处理链,current值即为处理链的第一环Hook1。
Hook1 → Hook2 → … → Hookn → initial-Hook
Cmdable:这个函数根据redis命令名及其参数构造一个对应的新命令Cmder,之后通过调用自身函数来开始redis命令执行逻辑,同时它也起到连接池和函数处理链的中介桥接作用。