我最近阅读了redis源代码,现在我正在研究网络代码。
Redis使用非阻塞模式和epoll(或类似的东西)进行网络数据读/写。当读取数据事件到达时,将调用“readQueryFromClient”函数,并在此函数中将请求数据重新加入缓冲区。
在“readQueryFromClient”函数中,如果确实有数据到达,数据将通过一个“读取”函数重新加入缓冲区,然后处理请求。
nread = read(fd, c->querybuf+qblen, readlen); // **one read function**
//... some other codes to check read function retuen value
processInputBuffer(c);// **request will be handled in this function**
我的问题是:redis如何确保所有请求数据只能通过一个'read'函数调用重新加入缓冲区,也许所有数据都会通过更多'read'函数调用获得?
答案 0 :(得分:2)
processInputBuffer(c); // 请求将在此函数中处理
那部分不是真的。 Redis协议旨在包括传递的每个数据块的长度。因此,服务器始终知道必须读取多少数据才能完成请求。在processInputBuffer
内,如果processInlineBuffer
和processMultibulkBuffer
都没有返回REDIS_OK
(即在缓冲区中找不到请求终结符/没有足够的参数),则控制简单地落在函数之外。在这种情况下processInputBuffer
做的所有事情都填满了客户端缓冲区的一大块并更新了解析状态。然后,在事件循环的下一次迭代中,在对aeProcessEvents
的调用中,如果套接字缓冲区中仍有未读数据,则将再次触发readQueryFromClient
回调以解析剩余数据。