• 技术文章 >数据库 >Redis

    浅析Redis6中的单线程和多线程模型

    青灯夜游青灯夜游2022-01-26 10:38:02转载191
    本篇文章带大家了解一下Redis6中的线程模型,介绍一下单线程模型和多线程模型,希望对大家有所帮助!

    1. Redis演进史

    如果单纯的说redis是单线程或多线程,这个回答肯定不严谨,不同版本使用的线程模型是不一样的。【相关推荐:Redis视频教程

    1.png

    2. Redis单线程模型

    2.1 单线程真实含义

    主要是指Redis的网络IO和键值对读写是由一个线程来完成的,Redis在处理客户端的请求时包括获取 (socket 读)、解析、执行、内容返回 (socket 写) 等都由一个顺序串行的主线程处理,这就是所谓的“单线程”。这也是Redis对外提供键值存储服务的主要流程。image.png
    但Redis的其他功能, 比如持久化、异步删除、集群数据同步等等,其实是由额外的线程执行的。 可以这么说,Redis工作线程是单线程的。但是,整个Redis来说,是多线程的

    2.2 单线程性能快原因

    Redis 3.x 单线程时代但是性能很快的主要原因

    2.3 采用单线程原因

    Redis 是基于内存操作的, 因此他的瓶颈可能是机器的内存或者网络带宽而并非 CPU ,既然 CPU 不是瓶颈,那么自然就采用单线程的解决方案了,况且使用多线程比较麻烦。 但是在 Redis 4.0 中开始支持多线程了,例如后台删除等功能
    简单来说,Redis 4.0 之前一直采用单线程的主要原因有以下三个:

    3. Redis多线程模型

    3.1 引入多线程原因

    既然单线程那么好,为啥又要引入多线程?单线程也有自己的烦恼,比如大key删除问题: 正常情况下使用 del 指令可以很快的删除数据,而当被删除的 key 是一个非常大的对象时,例如时包含了成千上万个元素的 hash 集合时,那么 del 指令就会造成 Redis 主线程卡顿。

    因此,在 Redis 4.0 中就新增了多线程的模块,当然此版本中的多线程主要是为了解决删除数据效率比较低的问题。可以通过惰性删除有效避免Redis卡顿问题(大key删除等问题),步骤如下:

    因为Redis是单个主线程处理,redis之父antirez一直强调"Lazy Redis is better Redis". 而lazy free的本质就是把某些cost(主要时间复制度,占用主线程cpu时间片)较高删除操作, 从redis主线程剥离让bio子线程来处理,极大地减少主线阻塞时间。从而减少删除导致性能和稳定性问题。

    Redis 4.0 就引入了多个线程来实现数据的异步惰性删除等功能,但是其处理读写请求的仍然只有一个线程,所以仍然算是狭义上的单线程。

    从上一小结分析:Redis的主要性能瓶颈是内存或网络带宽而并非CPU。内存问题比较好解决,因此Redis的瓶颈原因为网络IO。接下来,引入多线程模型。

    3.2 多线程工作原理

    I/O 的读和写本身是堵塞的,比如当 socket 中有数据时,Redis 会通过调用先将数据从内核态空间拷贝到用户态空间,再交给 Redis 调用,而这个拷贝的过程就是阻塞的,当数据量越大时拷贝所需要的时间就越多,而这些操作都是基于单线程完成的。image.png

    在 Redis 6.0 中新增了多线程的功能来提高 I/O 的读写性能,他的主要实现思路是将主线程的 IO 读写任务拆分给一组独立的线程去执行,这样就可以使多个 socket 的读写可以并行化了,采用多路 I/O 复用技术可以让单个线程高效的处理多个连接请求(尽量减少网络IO的时间消耗),将最耗时的Socket的读取、请求解析、写入单独外包出去,剩下的命令执行仍然由主线程串行执行并和内存的数据交互。image.png
    结合上图可知,将网络数据读写、请求协议解析通过多个IO线程的来处理,对于真正的命令执行来说,仍然使用主线程操作(线程安全),是个不错的折中办法。因此,对于整个Redis来说是多线程的,但是对于工作线程(命令执行)仍旧是单线程

    3.3 工作流程

    核心流程大概如下:image.png
    流程简述如下:

    特点如下:

    经过有心人士的压测,目前性能能提高 1 倍以上

    疑问1:等待列表不满 一直阻塞不处理吗?
    回复:image.png阻塞时检测的是,IO 线程是否还有任务。等处理完了才继续往下。这些任务是在执行时添加的,如果 任务数< 线程数,那有些线程就拿不到任务,它的待处理任务就是 0 。分配了任务的线程,在处理好 IO 事件后,pending 就会清零,没拿到任务的线程 pending 本来就是 0,所以不会阻塞。 这块还是有点疑问,哪位大佬可以解释下(评论哈)?

    3.4 默认开启多线程吗?

    在Redis6.0中, 多线程机制默认是关闭的 ,如果需要使用多线程功能,需要在redis.conf中完成两个设置。image.png

    4. 总结

    Redis自身出道就是优秀,基于内存操作、数据结构简单、多路复用和非阻塞 I/O、避免了不必要的线程上下文切换等特性,在单线程的环境下依然很快;

    但对于大数据的 key 删除还是卡顿厉害,因此在 Redis 4.0 引入了多线程unlink key/flushall async 等命令,主要用于 Redis 数据的异步删除;

    而在 Redis 6.0 中引入了 I/O 多线程的读写,这样就可以更加高效的处理更多的任务了, Redis 只是将 I/O 读写变成了多线程 ,而 命令的执行依旧是由主线程串行执行的 ,因此在多线程下操作 Redis 不会出现线程安全的问题

    Redis 无论是当初的单线程设计,还是如今与当初设计相背的多线程,目的只有一个:让 Redis 变得越来越快。

    更多编程相关知识,请访问:编程入门!!

    以上就是浅析Redis6中的单线程和多线程模型的详细内容,更多请关注php中文网其它相关文章!

    声明:本文转载于:掘金社区,如有侵犯,请联系admin@php.cn删除
    上一篇:保证mysql和redis的双写一致性 下一篇:Redis源码解析之深入了解Makefile文件
    PHP编程就业班

    相关文章推荐

    • 聊聊redis中多样的数据类型,以及集群相关的知识• 浅析Redis挖矿原理,看看如何预防(技巧分享)• 聊聊Redis中的主从复制、哨兵、集群• 解析Redis中的哨兵模式,聊聊搭建和执行流程• 浅析Redis中的锁,聊聊Redlock(redis分布式锁)• 什么是事务的ACID?Redis事务能实现ACID吗?

    全部评论我要评论

  • 取消发布评论发送
  • 1/1

    PHP中文网