今天和大家简单介绍下Redis的多路复用及内核中的请求数据结构分析
一.多路复用执行流程
老样子,先上图:
redis客户端和服务端建立连接的时候,会在双方各自建立一个socket,之后会通过socket建立长连接,并以此来进行后续的通信。
redis2.6版本之后,默认的最大client连接数是10000,最大可设置为100000。socket连接对建立了之后,client后续对于redis的操作命令,就会通过socket发送给服务端的socket。redis服务端里有个线程,会将所有socket接收到的操作命令放到队列里面,之后会通过文件事件调度器,将不同的命令分别分发到对应命令类型的处理器中,处理器会将命令写到输入缓冲区中,然后解析请求并找到对应的redis操作命令,执行完之后会将处理结果放到输出缓冲区,命令相应处理器会从输出缓存区中获取响应结果,之后将结果返给client。
二.Redis内核中的请求数据结构分析
网络通信的过程中,代码里的对象和数据结构,往往需要按照协议来进行封装和组织,按照协议的标准将数据组织成指定格式,然后会得到一堆协议数据,例如一个set key value 的命令,会被redis协议组织成: 3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$5\r\nvalue\r\n ( * 是请求命令的前缀,第二个数字是指命令字符串长度,第三个数字是指key的长处,第四个数字是指value的长度)
之后就将这串数据进行序列化,将其转换成byte[]数组,转成字节数据流之后,才能通过socket,使用网络去传输到server端去。
server端的socket接收到client发送的数据流之后,会先将字节流进行反序列化,拿到3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$5\r\nvalue\r\n的请求串,然后会被放到对应的RedisClient的输入缓冲区里,如下图所示:
在server中,多个RedisClient会被串行起来,组成一个client数组,每次socket接到命令之后,会遍历这个数组,知道找到对应的client,每个client中会有自己的缓冲区queryBuf和请求解析后数据存放结构argv,queryBuf下有个sdshdr的数据结构,该数据结构下,有free字段(记录还有多少空闲空间),len(已经存放的数据长度),buf(反序列化之后的数据)。buf里的数据会根据redis协议进行解析,解析后的数据会被存放到argv数据结构中,该数据结构是个数组,将redis操作命令分解成单个字段。
命令解析出来之后,就会根据命令,找到server中的命令查找表,命令查找表里的命令都会有个指针,分别对应着不同的RedisCommand,client根据命令查找表找到对应的命令,然后根据表中命令的指针找到对应的RedisCommand,这个RedisCommand会被存储到Client的cmd字段中,之后通过调用命令函数来执行对应的命令。过程如下图所示:
当命令执行完毕之后,会将执行结果存放到client的输出缓冲区中,之后会通过redis协议将结果组织,然后再序列化,通过socket将执行结果响应给client。如下图所示:
到此为止,redis的请求数据结构分析就结束了