②. 既然单线程这么好,为什么逐渐又加入了多线程特性?
①. 单线程也有单线程的苦恼(举个例子)
正常情况下使用del指令可以很快的删除数据,而当被删除的key是一个非常大的对象时,例如时包含了成千上万个元素的hash集合时,那么del指令就会造成Redis主线程卡顿
这就是redis3.x单线程时代最经典的故障,大key删除的头疼问题
由于redis是单线程的,del bigKey…(等待很久这个线程才会释放,类似加了一个synchronized锁,你可以想象高并发下,程序堵成什么样子?)
②. 如何解决:使用惰性删除可以有效的避免Redis卡顿的问题
③. 案列:
比如当我(Redis)需要删除一个很大的数据时,因为是单线程同步操作,这就会导致Redis服务卡顿
于是在Redis 4.0 中就新增了多线程的模块,当然此版本中的多线程主要是为了解决删除数据效率比较低的问题的
因为Redis是单个主线程处理,redis之父antirez一直强调"Lazy Redis is better Redis",而lazy free的本质就是把某些cost(主要时间复制度,占用主线程cpu时间片)较高删除操作,从redis主线程剥离让bio子线程来处理,极大地减少主线阻塞时间。从而减少删除导致性能和稳定性问题
④. 在Redis 4.0就引入了多个线程来实现数据的异步惰性删除等功能,但是其处理读写请求的仍然只有一个线程,所以仍然算是狭义上的单线程。
③. redis6的多线程和IO多路复用入门篇
- ①. 对于Redis主要的性能瓶颈是内存或者网络带宽而并非CPU
②. 最后Redis的瓶颈可以初步定为:网络IO(redis6,真正多线程登场)
③. Unix网络编程中的五种IO模型
Blocking IO - 阻塞IO
NoneBlocking IO - 非阻塞IO
IO multiplexing - IO多路复用
signal driven IO - 信号驱动IO
asynchronous IO - 异步IO
④. IO multiplexing - IO多路复用
这是IO模型的一种,即经典的Reactor设计模式,
I/O 多路复用,简单来说就是通过监测文件的读写事件再通知线程执行相关操作,保证 Redis 的非阻塞 I/O 能够顺利执行完成的机制
多路指的是多个socket连接,复用指的是复用一个线程。多路复用主要有三种技术:select,poll,epoll
epoll是最新的也是目前最好的多路复用技术。采用多路 I/O 复用技术可以让单个线程高效的处理多个连接请求(尽量减少网络IO的时间消耗),且Redis在内存中操作数据的速度非常快(内存内的操作不会成为这里的性能瓶颈),主要以上两点造就了Redis具有很高的吞吐量
⑤. Redis工作线程是单线程的,但是整个Redis来说,是多线程的;
⑥. I/O 的读和写本身是堵塞的,比如当 socket 中有数据时,Redis 会通过调用先将数据从内核态空间拷贝到用户态空间,再交给 Redis 调用,而这个拷贝的过程就是阻塞的,当数据量越大时拷贝所需要的时间就越多,而这些操作都是基于单线程完成的