1. Redis简介
Redis(Remote Dictionary Server)是一个开源的、高性能的、基于内存的NoSQL数据库系统,它支持多种数据结构,如字符串(String)、哈希(Hash)、列表(List)、集合(Set)、有序集合(Zset)等。Redis是单线程的,但通过IO多路复用技术达到高并发读写的效果,而这也是Redis性能优秀的一个原因。
2. 为什么说Redis是单线程的
2.1 Redis主线程
Redis主线程是Redis使用的唯一线程。所有的请求都在主线程中依序执行,这就是Redis为什么被称为单线程的原因。在提高并发处理能力的同时,也降低了开发和运维的复杂性。
2.2 多路IO复用
虽然Redis主线程只有一个,但Redis使用了多路IO复用来实现一次处理多个客户端请求,提升了Redis的并发能力。
多路IO复用是指利用操作系统提供的select、poll、epoll等机制,将多个socket的I/O事件注册到一个fd_set集合中,通过select、poll、epoll等函数监听集合中所有socket的I/O事件,并在有I/O事件发生时,返回这些socket的标识符,以此来处理多个客户端的请求。
在Redis中,默认采用的是epoll机制。当客户端向Redis发送请求时,Redis的epoll循环可以同时监听多个客户端,当有客户端事件到来时,epoll会将事件添加到事件队列中,Redis主线程会从事件队列中提取出事件,执行对应的操作,最终向客户端返回结果。
2.3 Redis线程模型优势
Redis采用单线程的模型,有如下几个优势:
简单高效:单线程模型使得Redis的内部实现和对外提供的接口都非常简单。
避免加锁解锁的开销:Redis使用单线程模型来避免锁的竞争,避免加锁解锁的开销,减少多线程环境下锁的竞争导致的性能下降。
避免上下文切换带来的CPU开销:单线程模型使得Redis无需进行上下文切换,减少调度带来的CPU开销。
3. Redis单线程的性能优势
虽然Redis采用的是单线程模型,但Redis的性能非常出色,主要体现在以下几个方面:
3.1 内存读写
Redis采用的是内存读写的方式,能够实现非常高的读写性能。
set key value
以上指令能够在几微秒的时间内完成一个字符串的写入。而在读取键的值时,速度更快,所需的时间基本上可以忽略不计。
3.2 轻量级的结构和快速的持久化方式
在持久化方面,Redis提供了两种不同的选项:
快照持久化:在指定的时间间隔内,将内存中的数据以文件的形式保存到硬盘上,可以在 Redis 服务重启时使用。
记录式持久化:将每个操作都写入一个文件中,当 Redis 服务重启时,可以将这些操作逐一执行一次以得到最终的数据状态。
Redis的持久化方式非常轻量,数据写入速度非常快,Redis的单线程模型也使得数据写入操作的互斥访问非常高效,避免了多线程环境下相关操作之间的冲突和资源争夺问题。
3.3 数据结构的性能
Redis提供不同的数据结构,不同结构之间的性能表现很不相同,这里以Set为例:
Set主要支持 add、remove、is_member、multi_add、multi_remove等操作,其中最慢的操作是multi_remove。Set结构对multi_remove操作的复杂度为O(N),其中N为要删除的元素数量。
虽然删除速度不是很快,但是Redis在Set结构的读取和添加操作上表现良好。而即使在存在multi_remove操作时,Redis在Set结构上的性能也非常优秀。
4. 总结
Redis是一个高性能、基于内存的NoSQL数据库系统,采用单线程模型实现了高并发。Redis主线程负责监听客户端事件、IO操作和事件处理等任务,通过多路IO复用实现了一次处理多个客户端请求的效果。Redis采用单线程的模型,简单高效、避免加锁解锁的开销、避免上下文切换带来的CPU开销。Redis的性能优势体现在内存读写、轻量级的结构和快速的持久化方式、数据结构的性能等方面。