Redis使用单线程却快到飞起的原因

文章目录

    • Redis为什么用单线程?
      • 多线程的开销
    • Redis使用单线程为什么还这么快?
    • 网络与IO操作的潜在阻塞点
    • 基于多路复用的高性能IO模型
      • 回调机制
    • Redis的性能瓶颈点
    • 其他Redis相关的有趣问题
      • 1. 为什么要用Redis,直接访问内存不好吗?
      • 2. 数据太多内存放不下怎么办?比如我要缓存100G的数据,怎么办?

在这里插入图片描述

Redis想必大家都或多或少听过吧,我们在工作学习中通常用它来作为缓存使用,既然是作为缓存,大家的第一反应肯定是:这家伙很快!

实际上它确实也很快 : ),但Redis底层却是单线程的!有同学可能就要有疑问了,为什么单线程的Redis却能够快到飞起?

别急,我尽量用通俗易懂的语言来给各位说道说道~~


Redis是单线程,主要是指Redis的网络IO和读写是由一个线程来完成的,但Redis的其他功能,比如持久化、异步删除、集群数据同步等,其实是由额外的线程执行的。这不是本文讨论的重点,有个印象即可


Redis为什么用单线程?

多线程的开销

通常情况下,在采用多线程后,如果没有良好的系统设计,其实是左图所展示的那样(注意纵坐标)。刚开始增加线程数时,系统吞吐率会增加,再进一步增加线程时,系统吞吐率就增长迟缓了,甚至还会出现下降的情况。
在这里插入图片描述

关键瓶颈在于: 系统中通常会存在会被多线程同时访问的共享资源,为了保证共享资源的正确性,就需要有额外的机制保证线程安全性,例如加锁,这会带来额外的开销。

比如拿最常用的List类型来举例吧,假设Redis采用多线程设计,有两个线程A和B分别对ListLPUSHLPUSH操作,为了使得每次执行都是相同的结果,即【B线程取出A线程放入的数据】就需要让这两个过程串行执行。这就是多线程编程模式面临的共享资源的并发访问控制问题

在这里插入图片描述

并发访问控制一直是多线程开发中的一个难点问题:如果只是简单地采用一个互斥锁,就会出现即使增加了线程,大部分线程也在等待获取互斥锁,并行变串行,系统吞吐率并没有随着线程的增加而增加。

同时加入并发访问控制后也会降低系统代码的可读性和可维护性,所以Redis干脆直接采用了单线程模式。

Redis使用单线程为什么还这么快?

之所以使用单线程是Redis设计者多方面衡量的结果。

  1. Redis的大部分操作在内存上完成
  2. 采用了高效的数据结构,例如哈希表和跳表
  3. 采用了多路复用机制,使其在网络IO操作中能并发处理大量的客户端请求,实现高吞吐率

既然Redis使用单线程进行IO,如果线程被阻塞了就无法进行多路复用了,所以不难想象,Redis肯定还针对网络和IO操作的潜在阻塞点进行了设计。

网络与IO操作的潜在阻塞点

在网络通信里,服务器为了处理一个Get请求,需要监听客户端请求(bind/listen),和客户端建立连接(accept),从socket中读取请求(recv),解析客户端发送请求(parse),最后给客户端返回结果(send)。

最基本的一种单线程实现是依次执行上面的操作。
在这里插入图片描述
上面标红的accept和recv操作都是潜在的阻塞点:

  • 当Redis监听到有连接请求,但却一直不能成功建立起连接时,就会阻塞在accept()函数这里,其他客户端此时也无法和Redis建立连接
  • 当Redis通过recv()从一个客户端读取数据时,如果数据一直没有到达,也会一直阻塞

基于多路复用的高性能IO模型

为了解决IO中的阻塞问题,Redis采用了Linux的IO多路复用机制,该机制允许内核中,同时存在多个监听套接字和已连接套接字(select/epoll)。

内核会一直监听这些套接字上的连接或数据请求。一旦有请求到达,就会交给Redis处理,这就实现了一个Redis线程处理多个IO流的效果。

在这里插入图片描述
此时,Redis线程就不会阻塞在某一个特定的客户端请求处理上,所以它可以同时和多个客户端连接并处理请求。

回调机制

select/epoll一旦监测到FD上有请求到达时,就会触发相应的事件被放进一个队列里,Redis线程对该事件队列不断进行处理,所以就实现了基于事件的回调。

例如,Redis会对Accept和Read事件注册acceptget回调函数。当Linux内核监听到有连接请求或读数据请求时,就会触发Accept事件和Read事件,此时,内核就会回调Redis相应的acceptget函数进行处理。

Redis的性能瓶颈点

经过上面的分析,虽然通过多路复用机制可以同时监听多个客户端的请求,但Redis仍然有一些性能瓶颈点,这也是我们平时编程需要极力避免的情况。

1. 耗时操作
任意一个请求在Redis中一旦耗时较久,都会影响整个server的性能。后面的请求都要等前面这个耗时请求处理完成,自己才能被处理到。

这一点需要我们在设计业务场景时去规避;Redis的lazy-free机制也把释放内存的耗时操作放在了异步线程中去执行了。

2. 高并发场景
并发量非常大时,单线程读写客户端IO数据存在性能瓶颈,虽然采用IO多路复用机制,但还是只能单线程依次读取客户端的数据,无法利用到CPU多核。

Redis在6.0可以利用CPU多核多线程读写客户端数据,但只是针对客户端的读写是并行的,每个命令的真正操作还是单线程。


其他Redis相关的有趣问题

借此机会也提几个和redis相关的有意思的问题。

1. 为什么要用Redis,直接访问内存不好吗?

这一条其实并没有很明确的界定,对于一些不经常变动的数据,可以直接放到内存里,不一定要放到Redis里,可以放到内存里。一致性问题:如果一个数据被修改了,数据在本地内存里的话,可能只有一台服务器上的数据被修改了。如果用Redis里面的话,我们访问Redis服务器,可以解决一致性问题。

2. 数据太多内存放不下怎么办?比如我要缓存100G的数据,怎么办?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/555474.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

线程池参数到底要怎么配?

文章目录1 线程池快速回顾2 现有设置参数的方法及不足3 如何设置核心线程数(corePoolSize)4 如何设置最大线程数(maxPoolSize)5 如何改变等待队列长度想必大家对Java里面线程池( 类)一定不陌生吧&#xff0…

oracle嵌套三层循环语句,在存储过程中执行3种oracle循环语句

http://www.cnblogs.com/coprince/p/3443219.htmlcreate or replace procedure pr_zhaozhenlong_loop/*名称:在存储过程中执行3种循环语句功能:利用循环给表中插入数据调用:begin-- Call the procedurepr_zhaozhenlong_strsql;end;创建人&…

彻底搞懂Cookie、Session、JWT和Token

文章目录引入:http是一个无状态协议?怎么解决呢?一、Cookie和Session1.1 cookie 注意事项:1.2 cookie 重要的属性1.3 session 注意事项:1.4 Cookie 和 Session 的区别:二、token(令牌&#xff0…

oracle数据库导入txt,oracle数据库导入TXT文件方法介绍

客户端连接数据库导入1. 安装有oracle客户端,配好监听。2. 以oracle数据库app用户的表user_svc_info为例CREATE TABLE USER_SVC_INFO(PHONE varchar2(20) NOT NULL,SVC_ID varchar2(32) NOT NULL,P_USERNAME varchar2(100) NULL,USER_STATUS number NOT NULL ,P_ALI…

你真的知道什么是多线程吗?为什么要学习多线程?

文章目录1、多线程的含义2、原理3、优势4、线程与进程的区别5、线程与多线程的区别6、线程调度的分类7、同步与异步8、并发与并行9、为什么要使用线程池10、线程池的好处11、线程池的分类12、意义1、多线程的含义 多线程(multithreading),是…

oracle 表关联索引优化,Oracle执行计划调优-超级大表关联超级小表的性能调优

今日客户现场出现一个查询SQL异常慢的情况。用时分钟级别。SELECT *FROM (SELECT a1.*, rownum rnFROM (SELECT openOrder2017.exchId,............openOrder2017.internalbizmark,customer.typeIdListFROM openOrder2017, customerWHERE openOrder2017.custId customer.custI…

Common Sort - 排序 - Java

文章目录排序概念稳定性(重要)应用 - 举例1.、各大商城的价格从低到高等2、中国大学排名常见的排序算法(8 种)- 总览直接插入排序模拟实现 - 插入排序稳定性分析结论希尔排序思考原理科学家的分组思维模拟实现 - 希尔排序总结选择…

linux的运行级别如何更改成6,把Linux运行级别设置为6后如何解决的经验分享

我们知道,Linux有7个运行级别,而运行级别设置为6后,会导致Linux系统刚启动完成就立刻重启,重启后又会立刻重启,如此反复,导致系统不能正常运行。本文笔者和大家分享一下误把Linux运行级别设置为6后如何解决…

flume linux 命令,Linux环境Flume安装配置及使用

# Flume监听本地Linux-hive日志文件采集到HDFS——配置文件# Name the components on this agent agent别名设置a1.sources r1a1.sinks k1a1.channels c1# Describe/configure the source 设置数据源监听本地文件配置# exec 执行一个命令的方式去查看文件 tail -F 实时查看a…

Redis五种数据结构应用场景

文章目录前言二、字符串String2.1、常用操作2.2、应用场景2.2.1、单值缓存(最常用)2.2.2、对象缓存2.2.3、分布式锁2.2.4、计数器三、哈希hash3.1、常用操作3.2、应用场景3.2.1、对象缓存3.2.2、 电商购物车四、列表list4.1、常用操作4.2、应用场景4.2.1…

linux能记录日志的终端,Linux上的日志系统

Linux上的日志系统1、syslog2、syslog-ng 下一代升级版日志系统红帽5使用syslog 6使用syslog-ngsyslog 服务syslogd : 系统,非内核产生的信息klogd : 内核,专门负责记录内核的日志信息系统启动时所输出的信息【到init启动之前的所有信息】:…

IntelliJ IDEA中的神仙插件

文章目录1. Alibaba Java Coding Guidelines2.GsonFormat3.A8Translation4.Maven Helper5.Free Mybatis plugin6.Grep Console7.Lombok8.Nyan progress bar9.FindBugs-IDEA10.Key Promoter X11.JavaDoc12.ignore13.RainbowBrackets14.Activate-power-mode15.CodeGlance16.Gener…

linux 远程拒绝服务,Linux Kernel SCTP远程拒绝服务漏洞

发布日期:2011-08-30更新日期:2011-08-30受影响系统:Linux kernel 2.6.x描述:--------------------------------------------------------------------------------BUGTRAQ ID: 49373CVE ID: CVE-2011-2482Linux Kernel是Linux操…

linux 常用命令行 大全

Linux常用命令大全(非常全!!!) 最近都在和Linux打交道,感觉还不错。我觉得Linux相比windows比较麻烦的就是很多东西都要用命令来控制,当然,这也是很多人喜欢linux的原因&#xff0c…

linux运行程序+后注销,linux – 如果我启动后台进程然后注销,它会继续运行吗?...

在与同事长时间讨论之后问这个问题,我真的想在这里澄清一下.我通过添加“&”来启动后台进程到命令行或用CTRL-Z停止它并在后台用“bg”恢复它.然后我退出了.怎么了?我们很确定它应该被一个SIGHUP杀死,但这并没有发生;再次登录时,进程很愉快,并且pstree显示它被i…

SpringBoot使用Websocket

webSocket是HTML5的一种新协议,它实现了服务端与客户端的全双工通信,建立在传输层,tcp协议之上,即浏览器与服务端需要先建立tcp协议,再发送webSocket连接建立请求。webSocket的连接:客户端发送请求信息&…

linux误删文件咋恢复,恢复Linux误删文件

恢复Linux误删文件目录方法一方法二不小心执行了rm删除了某些文件,是有点倒霉。不过我一般都会设置alias rmrm -i在删除的时候需要输入Y才能真正删除,当然此时用rm -f那也会直接删除了。因此找了两种方案恢复误删的文件。方法一适用系统内置debugfs&…

Springboot整合Websocket遇到的坑_websocket session不支持序列化,无法存储至redis_Websocket相关问题总结(Session共享,用户多端登录等)

Springboot整合Websocket遇到的坑 一、使用Springboot内嵌的tomcat启动websocket 1.添加ServerEndpointExporter配置bean Configuration public class WebSocketConfig {/*** 服务器节点** 如果使用独立的servlet容器,而不是直接使用springboot的内置容器&#x…

linux 中文意思,linux 中 ~/. 是什么意思

~代表你的/home/用户明目录假设你的用户名是x,那么~/就是/home/x/.是代表此目录本身,但是一般可以不写所以cd ~/. 和cd ~ 和cd ~/效果是一样的但是.后面有东西又是另外一个问题,点在文件名头部,代表一个隐藏文件~/.local是你的主目…

图文详解mina框架

Apache Mina Server 是一个网络通信应用框架,也就是说,它主要是对基于TCP/IP、UDP/IP协议栈的通信框架(当然,也可以提供JAVA 对象的序列化服务、虚拟机管道通信服务等),Mina 可以帮助我们快速开发高性能、高…