- 基于内存:Redis 将数据存储在内存中,内存访问速度远高于磁盘访问速度,因此能够快速读写数据。
- 单线程模型:Redis 使用单线程模型来处理客户端请求,避免了多线程之间的切换开销,简化了并发控制,提高了数据处理速度。
- 多路复用IO:Redis 使用非阻塞 I/O 处理网络请求,可以处理大量并发连接而不会造成线程阻塞,提高了网络通信效率。
多路复用IO原理:
多路复用(Multiplexing)IO 是一种利用操作系统提供的机制同时监控多个文件描述符(sockets)的技术,通过一种非阻塞的方式实现对多个 IO 操作的复用,提高系统的 IO 操作效率。多路复用主要采用 select、poll、epoll 等系统调用来实现,这些调用可以同时监视多个文件描述符的可读、可写、异常等事件。
多路复用的基本原理包括以下几个步骤:
- 注册文件描述符:应用程序向操作系统内核注册多个文件描述符,告诉内核要监视的文件描述符和监视的事件类型。
- 阻塞等待:应用程序调用多路复用的系统调用(如 select、poll、epoll_wait)并进入阻塞等待状态,等待有任何一个注册的文件描述符发生事件(可读、可写等)。
- 事件触发:一旦有文件描述符上发生了监视的事件,内核将唤醒应用程序,返回就绪文件描述符的信息。
- 处理事件:应用程序通过轮询返回的就绪文件描述符集合,逐一处理每个就绪文件描述符上发生的事件,进行相应的 IO 操作。
select、poll、epoll 的区别:
select、poll 和 epoll 都是在网络编程中用于 I/O 复用的机制,它们的主要作用是在多个文件描述符中等待并检测哪些文件描述符已经就绪可进行 I/O 操作。
select:
- select 是最古老的 I/O 复用函数之一,在 POSIX 标准中提供支持。
- 通过调用 select 函数,可以同时监视多个文件描述符,当其中任何一个文件描述符就绪时,select 函数会返回,并告知哪些文件描述符已经就绪。
- 有三个主要限制:文件描述符数量上限受限于 FD_SETSIZE 宏定义(通常为 1024),每次调用都需要将文件描述符集合从用户态拷贝到内核态,效率较低,复杂度随着文件描述符数量增加而增加。
poll:
- poll 是对 select 的改进,也用于实现 I/O 复用。
- 与 select 不同,poll 没有文件描述符数量限制,使用对象是一个 pollfd 结构体数组。
- 调用 poll 函数时,内核会遍历所有的 pollfd 结构体,找出其中已经就绪的文件描述符,并返回。
- 虽然解决了 select 的文件描述符数量限制问题,但效率依然不高,因为每次调用 poll 都需要将 pollfd 结构体数组从用户态拷贝到内核态。
epoll:
- epoll 是 Linux 特有的 I/O 复用机制,相比于 select 和 poll 更加高效。
- epoll 使用一组事件管理文件描述符,无需将文件描述符从用户态拷贝到内核态,因此效率更高。
- 通过调用 epoll_create 创建 epoll 实例,然后使用 epoll_ctl 向 epoll 实例中添加、修改或删除需要关注的文件描述符,最后调用 epoll_wait 等待文件描述符就绪。
- epoll 支持水平触发和边缘触发两种模式,可以更灵活地处理事件
ps:以下是我整理的java面试资料,感兴趣的可以看看。最后,创作不易,觉得写得不错的可以点点关注!