Redis网络模型是一个使用IO多路复用、单线程、非阻塞的模型。这个模型的优点在于单线程不用考虑加锁,如果在单核环境上可以将效率发挥到最大。
通过aeCreateEventLoop创建核心aeEventLoop 通过anetTcpServer完成socket() bind() listen() 通过aeCreateFileEvent给fd注册相应的事件 aeMain循环检测每个fd是否有事件发生,如果有就交给相应的读/写处理程序。
- acceptHandler: 接受客户端连接,创建socket句柄,创建client结构(主要包含读写buffer),将socket句柄和读事件注册到eventloop中。
- readEventHandler: 从socket中读取数据,存到rbuffer中,检查是否是一个完整的数据包(头部长度+数据长度>buffer中的数据长度),如果不是完整的就退出,等下一次读。 如果是一个完整的数据包,则解析数据包中的内容,根据数据头中的type做出不同动作(1.返回一个字符串 2.print内容),如果需要返回的话就构建一个返回数据包 并写入wbuffer,尝试从wbuffer中写到socket中,如果没有写完则注册写事件到eventloop中,等待可写时继续从wbuffer中读取并写入
- writeEventHandler: 检测wbuffer中是否有剩余数据待写,如果没有了就从eventloop中删除写事件。
1. 由于TCP协议本身的机制(面向连接可靠的协议,三次握手四次挥手)客户段与服务端会建立一个链接,
数据在链接不断开的情况下, 可以持续不断地将多个数据包发往服务端,相当于一个流,但是如果发送的
网络数据包太小对较小的数据包进行合并(基于此,TCP的 网络延迟要UDP的高些,因为需要合并延时发送)
然后再发送(超时或者包大小足够)。这样的话,服务端在接收到消息(数据流)的 时候就无法区分哪些
数据包是客户端自己分开发送的,这样产生了粘包;
2. 服务端在接收到数据后,然后放到缓冲区中,如果消息没有被及时从缓存区取走,下次在取数据的时候
可能就会出现一次取出多个数据包的情况,造成粘包现象。