Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Redis线程模型的前世今生

Redis线程模型的前世今生

原创
作者头像
2020labs小助手
发布于 2021-11-30 10:00:07
发布于 2021-11-30 10:00:07
3600
举报
文章被收录于专栏:vivo互联网技术vivo互联网技术

一、概述

众所周知,Redis是一个高性能的数据存储框架,在高并发的系统设计中,Redis也是一个比较关键的组件,是我们提升系统性能的一大利器。深入去理解Redis高性能的原理显得越发重要,当然Redis的高性能设计是一个系统性的工程,涉及到很多内容,本文重点关注Redis的IO模型,以及基于IO模型的线程模型。

我们从IO的起源开始,讲述了阻塞IO、非阻塞IO、多路复用IO。基于多路复用IO,我们也梳理了几种不同的Reactor模型,并分析了几种Reactor模型的优缺点。基于Reactor模型我们开始了Redis的IO模型和线程模型的分析,并总结出Redis线程模型的优点、缺点,以及后续的Redis多线程模型方案。本文的重点是对Redis线程模型设计思想的梳理,捋顺了设计思想,就是一通百通的事了。

注:本文的代码都是伪代码,主要是为了示意,不可用于生产环境。

二、网络IO模型发展史

我们常说的网络IO模型,主要包含阻塞IO、非阻塞IO、多路复用IO、信号驱动IO、异步IO,本文重点关注跟Redis相关的内容,所以我们重点分析阻塞IO、非阻塞IO、多路复用IO,帮助大家后续更好的理解Redis网络模型。

我们先看下面这张图;

2.1 阻塞IO

我们经常说的阻塞IO其实分为两种,一种是单线程阻塞,一种是多线程阻塞。这里面其实有两个概念,阻塞和线程。

阻塞:指调用结果返回之前,当前线程会被挂起,调用线程只有在得到结果之后才会返回;线程:系统调用的线程个数。

像建立连接、读、写都涉及到系统调用,本身是一个阻塞的操作。

2.1.1 单线程阻塞

服务端单线程来处理,当客户端请求来临时,服务端用主线程来处理连接、读取、写入等操作。

以下用代码模拟了单线程的阻塞模式;

代码语言:txt
AI代码解释
复制
import java.net.Socket;
 
public class BioTest {
 
    public static void main(String[] args) throws IOException {
        ServerSocket server=new ServerSocket(8081);
        while(true) {
            Socket socket=server.accept();
            System.out.println("accept port:"+socket.getPort());
            BufferedReader  in=new BufferedReader(new InputStreamReader(socket.getInputStream()));
            String inData=null;
            try {
                while ((inData = in.readLine()) != null) {
                    System.out.println("client port:"+socket.getPort());
                    System.out.println("input data:"+inData);
                    if("close".equals(inData)) {
                        socket.close();
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }      
        }
    }
}

我们准备用两个客户端同时发起连接请求、来模拟单线程阻塞模式的现象。同时发起连接,通过服务端日志,我们发现此时服务端只接受了其中一个连接,主线程被阻塞在上一个连接的read方法上。

我们尝试关闭第一个连接,看第二个连接的情况,我们希望看到的现象是,主线程返回,新的客户端连接被接受。

从日志中发现,在第一个连接被关闭后,第二个连接的请求被处理了,也就是说第二个连接请求在排队,直到主线程被唤醒,才能接收下一个请求,符合我们的预期。

此时不仅要问,为什么呢?

主要原因在于accept、read、write三个函数都是阻塞的,主线程在系统调用的时候,线程是被阻塞的,其他客户端的连接无法被响应。

通过以上流程,我们很容易发现这个过程的缺陷,服务器每次只能处理一个连接请求,CPU没有得到充分利用,性能比较低。如何充分利用CPU的多核特性呢?自然而然的想到了——多线程逻辑

2.1.2 多线程阻塞

对工程师而言,代码解释一切,直接上代码。

BIO多线程

代码语言:txt
AI代码解释
复制
package net.io.bio;
 
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
 
public class BioTest {
 
    public static void main(String[] args) throws IOException {
        final ServerSocket server=new ServerSocket(8081);
        while(true) {
            new Thread(new Runnable() {
                public void run() {
                    Socket socket=null;
                    try {
                        socket = server.accept();
                        System.out.println("accept port:"+socket.getPort());
                        BufferedReader  in=new BufferedReader(new InputStreamReader(socket.getInputStream()));
                        String inData=null;
                        while ((inData = in.readLine()) != null) {
                            System.out.println("client port:"+socket.getPort());
                            System.out.println("input data:"+inData);
                            if("close".equals(inData)) {
                                socket.close();
                            }
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    } finally {
                         
                    }
                }
            }).start();
        }
    }
 
}

同样,我们并行发起两个请求;

两个请求,都被接受,服务端新增两个线程来处理客户端的连接和后续请求。

我们用多线程解决了,服务器同时只能处理一个请求的问题,但同时又带来了一个问题,如果客户端连接比较多时,服务端会创建大量的线程来处理请求,但线程本身是比较耗资源的,创建、上下文切换都比较耗资源,又如何去解决呢?

2.2 非阻塞

如果我们把所有的Socket(文件句柄,后续用Socket来代替fd的概念,尽量减少概念,减轻阅读负担)都放到队列里,只用一个线程来轮训所有的Socket的状态,如果准备好了就把它拿出来,是不是就减少了服务端的线程数呢?

一起看下代码,单纯非阻塞模式,我们基本上不用,为了演示逻辑,我们模拟了相关代码如下;

代码语言:txt
AI代码解释
复制
package net.io.bio;
 
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.util.ArrayList;
import java.util.List;
 
import org.apache.commons.collections4.CollectionUtils;
 
 
public class NioTest {
 
    public static void main(String[] args) throws IOException {
        final ServerSocket server=new ServerSocket(8082);
        server.setSoTimeout(1000);
        List<Socket> sockets=new ArrayList<Socket>();
        while (true) {
            Socket socket = null;
            try {
                socket = server.accept();
                socket.setSoTimeout(500);
                sockets.add(socket);
                System.out.println("accept client port:"+socket.getPort());
            } catch (SocketTimeoutException e) {
                System.out.println("accept timeout");
            }
            //模拟非阻塞:轮询已连接的socket,每个socket等待10MS,有数据就处理,无数据就返回,继续轮询
            if(CollectionUtils.isNotEmpty(sockets)) {
                for(Socket socketTemp:sockets ) {
                    try {
                        BufferedReader  in=new BufferedReader(new InputStreamReader(socketTemp.getInputStream()));
                        String inData=null;
                        while ((inData = in.readLine()) != null) {
                            System.out.println("input data client port:"+socketTemp.getPort());
                            System.out.println("input data client port:"+socketTemp.getPort() +"data:"+inData);
                            if("close".equals(inData)) {
                                socketTemp.close();
                            }
                        }
                    } catch (SocketTimeoutException e) {
                        System.out.println("input client loop"+socketTemp.getPort());
                    }
                }
            }
        }
 
    }
}

系统初始化,等待连接;

发起两个客户端连接,线程开始轮询两个连接中是否有数据。

两个连接分别输入数据后,轮询线程发现有数据准备好了,开始相关的逻辑处理(单线程、多线程都可)。

再用一张流程图辅助解释下(系统实际采用文件句柄,此时用Socket来代替,方便大家理解)。

服务端专门有一个线程来负责轮询所有的Socket,来确认操作系统是否完成了相关事件,如果有则返回处理,如果无继续轮询,大家一起来思考下?此时又带来了什么问题呢。

CPU的空转、系统调用(每次轮询到涉及到一次系统调用,通过内核命令来确认数据是否准备好),造成资源的浪费,那有没有一种机制,来解决这个问题呢?

2.3 IO多路复用

server端有没专门的线程来做轮询操作(应用程序端非内核),而是由事件来触发,当有相关读、写、连接事件到来时,主动唤起服务端线程来进行相关逻辑处理。模拟了相关代码如下;

IO多路复用

代码语言:txt
AI代码解释
复制
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.Set;
 
public class NioServer {
 
    private static  Charset charset = Charset.forName("UTF-8");
    public static void main(String[] args) {
        try {
            Selector selector = Selector.open();
            ServerSocketChannel chanel = ServerSocketChannel.open();
            chanel.bind(new InetSocketAddress(8083));
            chanel.configureBlocking(false);
            chanel.register(selector, SelectionKey.OP_ACCEPT);
 
            while (true){
                int select = selector.select();
                if(select == 0){
                    System.out.println("select loop");
                    continue;
                }
                System.out.println("os data ok");
                 
                Set<SelectionKey> selectionKeys = selector.selectedKeys();
                Iterator<SelectionKey> iterator = selectionKeys.iterator();
                while (iterator.hasNext()){
                    SelectionKey selectionKey = iterator.next();
                     
                    if(selectionKey.isAcceptable()){
                        ServerSocketChannel server = (ServerSocketChannel)selectionKey.channel();
                        SocketChannel client = server.accept();
                        client.configureBlocking(false);
                        client.register(selector, SelectionKey.OP_READ);
                        //继续可以接收连接事件
                        selectionKey.interestOps(SelectionKey.OP_ACCEPT);
                    }else if(selectionKey.isReadable()){
                        //得到SocketChannel
                        SocketChannel client = (SocketChannel)selectionKey.channel();
                        //定义缓冲区
                        ByteBuffer buffer = ByteBuffer.allocate(1024);
                        StringBuilder content = new StringBuilder();
                        while (client.read(buffer) > 0){
                            buffer.flip();
                            content.append(charset.decode(buffer));
                        }
                        System.out.println("client port:"+client.getRemoteAddress().toString()+",input data: "+content.toString());
                        //清空缓冲区
                        buffer.clear();
                    }
                    iterator.remove();
                }
            }
 
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

同时创建两个连接;

两个连接无阻塞的被创建;

无阻塞的接收读写;

再用一张流程图辅助解释下(系统实际采用文件句柄,此时用Socket来代替,方便大家理解)。

当然操作系统的多路复用有好几种实现方式,我们经常使用的select(),epoll模式这里不做过多的解释,有兴趣的可以查看相关文档,IO的发展后面还有异步、事件等模式,我们在这里不过多的赘述,我们更多的是为了解释Redis线程模式的发展。

三、NIO线程模型解释

我们一起来聊了阻塞、非阻塞、IO多路复用模式,那Redis采用的是哪种呢?

Redis采用的是IO多路复用模式,所以我们重点来了解下多路复用这种模式,如何在更好的落地到我们系统中,不可避免的我们要聊下Reactor模式。

首先我们做下相关的名词解释;

Reactor:类似NIO编程中的Selector,负责I/O事件的派发;Acceptor:NIO中接收到事件后,处理连接的那个分支逻辑;Handler:消息读写处理等操作类。

3.1 单Reactor单线程模型

处理流程

  • Reactor监听连接事件、Socket事件,当有连接事件过来时交给Acceptor处理,当有Socket事件过来时交个对应的Handler处理。

优点

  • 模型比较简单,所有的处理过程都在一个连接里;
  • 实现上比较容易,模块功能也比较解耦,Reactor负责多路复用和事件分发处理,Acceptor负责连接事件处理,Handler负责Scoket读写事件处理。

缺点

  • 只有一个线程,连接处理和业务处理共用一个线程,无法充分利用CPU多核的优势。
  • 在流量不是特别大、业务处理比较快的时候系统可以有很好的表现,当流量比较大、读写事件比较耗时情况下,容易导致系统出现性能瓶颈。

怎么去解决上述问题呢?既然业务处理逻辑可能会影响系统瓶颈,那我们是不是可以把业务处理逻辑单拎出来,交给线程池来处理,一方面减小对主线程的影响,另一方面利用CPU多核的优势。这一点希望大家要理解透彻,方便我们后续理解Redis由单线程模型到多线程模型的设计的思路。

3.2 单Reactor多线程模型

这种模型相对单Reactor单线程模型,只是将业务逻辑的处理逻辑交给了一个线程池来处理。

处理流程

  • Reactor监听连接事件、Socket事件,当有连接事件过来时交给Acceptor处理,当有Socket事件过来时交个对应的Handler处理。
  • Handler完成读事件后,包装成一个任务对象,交给线程池来处理,把业务处理逻辑交给其他线程来处理。

优点

  • 让主线程专注于通用事件的处理(连接、读、写),从设计上进一步解耦;
  • 利用CPU多核的优势。

缺点

  • 貌似这种模型已经很完美了,我们再思考下,如果客户端很多、流量特别大的时候,通用事件的处理(读、写)也可能会成为主线程的瓶颈,因为每次读、写操作都涉及系统调用。

有没有什么好的办法来解决上述问题呢?通过以上的分析,大家有没有发现一个现象,当某一个点成为系统瓶颈点时,想办法把他拿出来,交个其他线程来处理,那这种场景是否适用呢?

3.3 多Reactor多线程模型

这种模型相对单Reactor多线程模型,只是将Scoket的读写处理从mainReactor中拎出来,交给subReactor线程来处理。

处理流程

  • mainReactor主线程负责连接事件的监听和处理,当Acceptor处理完连接过程后,主线程将连接分配给subReactor;
  • subReactor负责mainReactor分配过来的Socket的监听和处理,当有Socket事件过来时交个对应的Handler处理;

Handler完成读事件后,包装成一个任务对象,交给线程池来处理,把业务处理逻辑交给其他线程来处理。

优点

  • 让主线程专注于连接事件的处理,子线程专注于读写事件吹,从设计上进一步解耦;
  • 利用CPU多核的优势。

缺点

  • 实现上会比较复杂,在极度追求单机性能的场景中可以考虑使用。

四、Redis的线程模型

4.1 概述

以上我们聊了,IO网路模型的发展历史,也聊了IO多路复用的reactor模式。那Redis采用的是哪种reactor模式呢?在回答这个问题前,我们先梳理几个概念性的问题。

Redis服务器中有两类事件,文件事件和时间事件。

文件事件:在这里可以把文件理解为Socket相关的事件,比如连接、读、写等;时间时间:可以理解为定时任务事件,比如一些定期的RDB持久化操作。

本文重点聊下Socket相关的事件。

4.2 模型图

首先我们来看下Redis服务的线程模型图;

IO多路复用负责各事件的监听(连接、读、写等),当有事件发生时,将对应事件放入队列中,由事件分发器根据事件类型来进行分发;

如果是连接事件,则分发至连接应答处理器;GET、SET等redis命令分发至命令请求处理器。

命令处理完后产生命令回复事件,再由事件队列,到事件分发器,到命令回复处理器,回复客户端响应。

4.3 一次客户端和服务端的交互流程

4.3.1 连接流程

连接过程

  • Redis服务端主线程监听固定端口,并将连接事件绑定连接应答处理器。
  • 客户端发起连接后,连接事件被触发,IO多路复用程序将连接事件包装好后丢人事件队列,然后由事件分发处理器分发给连接应答处理器。
  • 连接应答处理器创建client对象以及Socket对象,我们这里关注Socket对象,并产生ae_readable事件,和命令处理器关联,标识后续该Socket对可读事件感兴趣,也就是开始接收客户端的命令操作。
  • 当前过程都是由一个主线程负责处理。

4.3.2 命令执行流程

SET命令执行过程

  • 客户端发起SET命令,IO多路复用程序监听到该事件后(读事件),将数据包装成事件丢到事件队列中(事件在上个流程中绑定了命令请求处理器);
  • 事件分发处理器根据事件类型,将事件分发给对应的命令请求处理器;
  • 命令请求处理器,读取Socket中的数据,执行命令,然后产生ae_writable事件,并绑定命令回复处理器;
  • IO多路复用程序监听到写事件后,将数据包装成事件丢到事件队列中,事件分发处理器根据事件类型分发至命令回复处理器;
  • 命令回复处理器,将数据写入Socket中返回给客户端。

4.4 模型优缺点

以上流程分析我们可以看出Redis采用的是单线程Reactor模型,我们也分析了这种模式的优缺点,那Redis为什么还要采用这种模式呢?

Redis本身的特性

命令执行基于内存操作,业务处理逻辑比较快,所以命令处理这一块单线程来做也能维持一个很高的性能。

优点

  • Reactor单线程模型的优点,参考上文。

缺点

  • Reactor单线程模型的缺点也同样在Redis中来体现,唯一不同的地方就在于业务逻辑处理(命令执行)这块不是系统瓶颈点。
  • 随着流量的上涨,IO操作的的耗时会越来越明显(read操作,内核中读数据到应用程序。write操作,应用程序中的数据到内核),当达到一定阀值时系统的瓶颈就体现出来了。

Redis又是如何去解的呢?

哈哈~将耗时的点从主线程拎出来呗?那Redis的新版本是这么做的吗?我们一起来看下。

4.5 Redis多线程模式

Redis的多线程模型跟”多Reactor多线程模型“、“单Reactor多线程模型有点区别”,但同时用了两种Reactor模型的思想,具体如下;

Redis的多线程模型是将IO操作多线程化,本身逻辑处理过程(命令执行过程)依旧是单线程,借助了单Reactor思想,实现上又有所区分。将IO操作多线程化,又跟单Reactor衍生出多Reactor的思想一致,都是将IO操作从主线程中拎出来。

命令执行大致流程

  • 客户端发送请求命令,触发读就绪事件,服务端主线程将Socket(为了简化理解成本,统一用Socket来代表连接)放入一个队列,主线程不负责读;
  • IO 线程通过Socket读取客户端的请求命令,主线程忙轮询,等待所有 I/O 线程完成读取任务,IO线程只负责读不负责执行命令;
  • 主线程一次性执行所有命令,执行过程和单线程一样,然后需要返回的连接放入另外一个队列中,有IO线程来负责写出(主线程也会写);
  • 主线程忙轮询,等待所有 I/O 线程完成写出任务。

五、总结

了解一个组件,更多的是要去了解他的设计思路,要去思考为什么要这么设计,做这种技术选型的背景是啥,对后续做系统架构设计有什么参考意义等等。一通百通,希望对大家有参考意义。

作者:vivo互联网服务器团队-Wang Shaodong

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Redis线程模型
Redis是一个开源的远程内存型数据库(Remote Dictionary Server(远程字典服务器)),它不仅性能强劲,而且提供了5 种不同类型的数据结构,我们项目实践中可能会遇到的大部分问题都可以很自然地映射到这些数据结构上。除此之外,Redis通过复制、持久化(persistence)、Redis Sentinel、客户端分片(client-side sharding)等特性,让用户可以很方便地将Redis 扩展成一个高可用能够包含数百GB 数据、每秒处理上百万次请求的系统。
加多
2021/11/24
8550
Redis线程模型
线程模型Reactor/Proactor的区别
反应器(Reactor)是一种为处理服务请求并发提交到一个或者多个服务处理程序的事件设计模式,当接收请求后,服务处理程序使用解多路分配策略,然后同步地派发这些请求至相关的请求处理程序。 处理特点: 1.事件驱动(event handling)
Monica2333
2020/06/19
4390
Redis 和 Memcached 有什么区别?Redis 的线程模型是什么?为什么 Redis 单线程却能支撑高并发
Redis 和 Memcached 有什么区别?Redis 的线程模型是什么?为什么 Redis 单线程却能支撑高并发?
MickyInvQ
2022/05/06
5240
Redis 和 Memcached 有什么区别?Redis 的线程模型是什么?为什么 Redis 单线程却能支撑高并发
【Redis破障之路】三:Redis单线程架构
众所周知,Redis是一个单线程架构的NoSQL数据库,但是是单线程模型的Redis为什么性能如此之高?这就是我们接下来要探究学习的内容。 1、Redis的单线程架构 1.1、Redis单线程简介 首
三分恶
2021/04/28
8100
【Redis破障之路】三:Redis单线程架构
Redis 6.0 为什么要引入多线程呢?
Redis 是基于 Reactor 模式开发了网络事件处理器,这个处理器称为文件事件处理器。组成结构为4个部分:
王小明_HIT
2020/12/14
1.4K0
Redis 6.0 为什么要引入多线程呢?
Redis 线程模型
【1】Redis 是基于 Reactor 模式开发的网络事件处理器:这个处理器被称为文件事件处理器(file event handler),这个文件事件处理器是单线程的,所以 Redis 才叫做单线程的模型: ■ 文件事件处理器使用 I/O 多路复用(multiplexing)机制监听多个套接字 Socket,根据 Socket 上的事件来选择对应的事件处理器进行处理。 ■ 当被监听的套接字准备好执行连接应答(accept)、读取(read)、写入(write)、关闭(close)等操作时。与操作相对应的文件事件就会产生,这时文件事件处理器就会调用套接字之前关联好的事件处理器来处理这些事件。 【2】虽然文件事件处理器以单线程的方式运行,但其使用 I/O 多路复用程序来监听多个套接字,文件事件处理器既实现了高性能的网络通信模型,又可以很好地与 Redis 服务器中其他同样以单线程方式运行的模块进行对接,这保持了 Redis 内部单线程设计的简单性。
Java架构师必看
2021/04/25
5590
Redis 线程模型
redis单线程为什么这么快
redis的数据类型有string、list、hash、set、sortedset
大侠之运维
2025/04/27
1060
redis单线程为什么这么快
Redis 新特性篇:多线程模型解读
Redis 官方在 2020 年 5 月正式推出 6.0 版本,提供很多振奋人心的新特性,所以备受关注。
码哥字节
2021/07/27
3200
深度解析Redis线程模型设计原理
我们通常说Redis是单线程,主要指Redis的网络I/O和KV对读写是由一个线程完成,是Redis对外提供KV存储服务的主要流程。 但Redis其它功能如持久化、异步删除、集群数据同步等,是由额外线程执行的。
JavaEdge
2021/12/07
3470
深度解析Redis线程模型设计原理
redis的线程模型
(1)纯内存访问。数据存放在内存中,内存的响应时间大约是100纳秒,这是Redis每秒万亿级别访问的重要基础。 (2)非阻塞I/O多路复用,Redis采用epoll做为I/O多路复用技术的实现,再加上Redis自身的事件处理模型将epoll中的连接,读写,关闭都转换为了时间,不在I/O上浪费过多的时间。 (3)单线程避免了线程切换和竞态产生的消耗。 (4)单线程操作,避免了不必要的上下文切换和竞争条件。也没有加解锁的操作。
Java技术债务
2022/08/09
6920
redis的线程模型
《【面试突击】— Redis篇》--Redis的线程模型了解吗?为啥单线程效率还这么高?
《【面试突击】— Redis篇》-- Redis的线程模型了解吗?为啥单线程效率还这么高?
编程大道
2020/02/14
7350
彻底搞懂 netty 线程模型
netty线程模型netty单线程模型Reactor多线程模型Reactor主从多线程模型netty线程模型思考netty线程模型实践
luoxn28
2019/11/25
1.3K0
彻底搞懂 netty 线程模型
Redis为啥这么快?&Redis的线程模型&Redis通讯过程
redis基于reactor模式开发了网络事件处理器,这个处理器叫做文件事件处理器,file event handler。这个文件事件处理器,是单线程的,redis才叫做单线程的模型,采用IO多路复用机制同时监听多个socket,根据socket上的事件来选择对应的事件处理器来处理这个事件。
名字是乱打的
2022/05/13
4640
Redis为啥这么快?&Redis的线程模型&Redis通讯过程
Redis 多线程网络模型全面揭秘
导语 | Redis 从本质上来讲是一个网络服务器,而对于一个网络服务器来说,网络模型是它的精华,搞懂了一个网络服务器的网络模型,你也就搞懂了它的本质,跟随本文视角带你吃透 Redis 整个核心网络模型的原理和源码。 引言 在目前的技术选型中,Redis 俨然已经成为了系统高性能缓存方案的事实标准,因此现在 Redis 也成为了后端开发的基本技能树之一,Redis 的底层原理也顺理成章地成为了必须学习的知识。 Redis 从本质上来讲是一个网络服务器,而对于一个网络服务器来说,网络模型是它的精华,
腾讯云开发者
2021/02/23
1.3K0
Redis 6.0 新特性-多线程连环13问!
在全国一片祥和IT民工欢度五一节假日的时候,Redis 6.0不声不响地于5 月 2 日正式发布了,吓得我赶紧从床上爬起来,学无止境!学无止境!
牧码哥
2020/05/06
2.4K0
Redis 6.0 新特性-多线程连环13问!
Redis篇:单线程 reactor 模型
redis 的高性能 纯内存访问,所有数据都在内存中,所有的运算都是内存级别的运算,内存响应时间的时间为纳秒级别。因此 redis 进程的 cpu 基本不存在磁盘 I/O 等待时间、内存读写性能问题,CPU 不是 redis 的瓶颈(内存大小和网络I/O 才是 redis 的瓶颈,也就是客户端和服务端之间的网络传输延迟) 采用单线程模型,单线程实现简单。避免了多线程频繁上下文切换,以及同步机制加锁带来的开销 简单高效的基础数据结构:动态字符串(SDS),链表,字典,跳跃链表,整数集合和压缩列表。然后 red
潜行前行
2022/01/18
1.1K0
Redis篇:单线程 reactor 模型
说说Netty的线程模型
最近发现极客时间的很多课程中,都穿插到了 Netty,可见 Netty 的重要性。基于此,给大家推荐一下这篇文章!
Bug开发工程师
2019/08/20
4970
说说Netty的线程模型
小红书抗住高并发的背后:Redis 7.0 性能必杀技之 I/O 多线程模型
在《Redis 为什么这么快》这篇文章中,我们已经知道 Redis 使用全局 dict 字典表 + 内存数据库 + 丰富高效的数据结构 + 单线程模型 + I/O 多路复用事件驱动框架使得 Redis 快到飞起。
码哥字节
2025/01/20
3820
小红书抗住高并发的背后:Redis 7.0 性能必杀技之 I/O 多线程模型
深度解析Redis线程模型设计原理
所以虽然FEH是单线程运行,但通过I/O多路复用监听多个socket,不仅实现高性能的网络通信模型,又能和 Redis 服务器中其它同样单线程运行的模块交互,保证了Redis内部单线程模型的简洁设计。
JavaEdge
2020/09/01
9670
redis缓存重要特性单线程模型
所有的客户端对服务端请求socket连接,服务端都会专门建立一个socket与其连接。
Tim在路上
2020/08/04
3710
相关推荐
Redis线程模型
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档