Redis的单线程模型-探索简洁高效的数据处理方式 (redis的五种数据类型)
Redis 是一款单线程数据库,这意味着它在处理客户端请求、解析请求、进行数据读写操作以及发送数据给客户端等过程中,使用的是一个线程(主线程)。这正是我们常说 Redis 是单线程的原因。
单线程模型的优点
- 避免多线程之间的竞争和同步问题,简化程序设计和维护的复杂性。
- 由于 Redis 主线程只负责处理请求和数据读写操作,不需要频繁地进行上下文切换,因此可以更高效地利用 CPU 资源。
- 通过使用非阻塞 I/O 和事件驱动模型,能够处理大量的并发请求。
单线程模型的限制
- 由于主线程负责所有的请求处理和数据操作,如果某个请求需要执行一个耗时的操作,那么其他请求会被阻塞,导致响应时间延长。
后台线程
Redis 并不完全是单线程的。在启动时,Redis 会启动后台线程(BIO)来处理一些特定任务:
- 在 Redis 2.6 版本中,会启动两个后台线程,分别用于关闭文件和 AOF 刷盘等任务。
- 在 Redis 4.0 版本之后,新增了一个后台线程,用于异步释放 Redis 内存,即 lazyfree 线程。
异步操作
例如,执行
unlinkkey
、
flushdbasync
、
flushallasync
等命令时,这些删除操作会交给后台线程来执行,这样可以避免 Redis 主线程的阻塞。因此,当我们需要删除一个大 key 时,不应使用
del
命令,因为
del
命令是在主线程中执行的,这会导致 Redis 主线程阻塞。相反,我们应该使用
unlink
命令来异步删除大 key。
结论
Redis 是一种单线程数据库,但并不意味着它完全没有多线程的支持。通过后台线程的引入,Redis 能够在保持单线程的简洁性和高效性的同时,处理一些特定任务和异步操作,提升了系统的性能和稳定性。
redis为什么那么快
Redis采用的是基于内存的采用的是单进程单线程模型的KV数据库,由C语言编写。 官方提供的数据是可以达到+的qps。 这个数据不比采用单进程多线程的同样基于内存的KV数据库Memcached差。 Redis快的主要原因是:1.完全基于内存2.数据结构简单,对数据操作也简单3.使用多路 I/O 复用模型第一、二点不细讲,主要围绕第三点采用多路 I/O 复用技术来展开。 多路 I/O 复用模型是利用select、poll、epoll可以同时监察多个流的 I/O 事件的能力,在空闲的时候,会把当前线程阻塞掉,当有一个或多个流有I/O事件时,就从阻塞态中唤醒,于是程序就会轮询一遍所有的流(epoll是只轮询那些真正发出了事件的流),并且只依次顺序的处理就绪的流,这种做法就避免了大量的无用操作。 这里“多路”指的是多个网络连接,“复用”指的是复用同一个线程。 采用多路 I/O 复用技术可以让单个线程高效的处理多个连接请求(尽量减少网络IO的时间消耗),且Redis在内存中操作数据的速度非常快(内存内的操作不会成为这里的性能瓶颈),主要以上两点造就了Redis具有很高的吞吐量。 和Memcached不同,Redis并没有直接使用Libevent,而是自己完成了一个非常轻量级的对select、epoll、evport、kqueue这些通用的接口的实现。 在不同的系统调用选用适合的接口,linux下默认是epoll。 因为Libevent比较重更通用代码量也就很庞大,拥有很多Redis用不上的功能,Redis为了追求“轻巧”并且去除依赖,就选择自己去封装了一套。 单进程单线程好处1.代码更清晰,处理逻辑更简单。 2.不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗。 3.不存在多进程或者多线程导致的切换而消耗CPU。
Redis-I/O模型
Redis 单线程是指 Redis的网络IO和键值对读写 是由一个线程完成。这也是Redis提供存储服务的主流程。
对于一个多线程系统,在合理的资源分配情况下,提高线程数,可以有效的提高系统的吞吐量。但实际情况可能是,刚增加线程数时,系统吞吐量增加,但进一步增加线程数,吞吐量增长缓慢,甚至下降。
![Redis](https://tyye.cn/zb_users/theme/tpure/style/images/lazyload.png)
Redis采用多路复用机制,使其在网络I/O操作中可以大量并发处理客户端请求,实现高吞吐率。 I/O多路复用 在单线程中通过记录跟踪每一个I/O流的状态来管理多个I/O流。select, poll, epoll 都是I/O多路复用的具体的实现。
在 Redis 只运行单线程的情况下,该机制允许内核中,同时存在多个监听套接字和已连接套接字。内核会一直监听这些套接字上的连接请求或数据请求。一旦有请求到达,就会交给 Redis 线程处理,这就实现了一个 Redis 线程处理多个 IO 流的效果。
图中FD就是套接字,当select/epoll一旦监测到FD上有请求到达时,就会出发相应的事件,这些事件会被放进一个事件队列,Redis 单线程对该事件队列不断进行处理。这样一来,Redis 无需一直轮询是否有请求实际发生,这就可以避免造成 CPU 资源浪费。同时,Redis 在对事件队列中的事件进行处理时,会调用相应的处理函数,这就实现了基于事件的回调。因为 Redis 一直在对事件队列进行处理,所以能及时响应客户端请求,提升 Redis 的响应性能。 事件到了,在处理,这就是反应器模式。
免责声明:本文转载或采集自网络,版权归原作者所有。本网站刊发此文旨在传递更多信息,并不代表本网赞同其观点和对其真实性负责。如涉及版权、内容等问题,请联系本网,我们将在第一时间删除。同时,本网站不对所刊发内容的准确性、真实性、完整性、及时性、原创性等进行保证,请读者仅作参考,并请自行核实相关内容。对于因使用或依赖本文内容所产生的任何直接或间接损失,本网站不承担任何责任。