Redis是如何实现高性能的?

Redis到底有多快?

redis到底有多快,可以通过 redis-benchmark 脚本进行基准测试。redis官方的性能基准测试报告

Redis为什么这么快?

redis之所以这么快,其实是一个综合性的结果。而能够支持其高性能的主要有以下几个点:

  • 基于内存redis的数据都保存在内存中,在接收到命令之后可以在微秒的时间单位内获取到数据,并返回给客户端。实际上在说微秒时间内获取到数据指的是请求已经到达服务端,仅仅是指命令的解析与处理可以在微秒的时间范围内完成,所以这里并不包括网络传输时间。因此,实际上在业务使用redis获取数据时,自己打日志发现redis的命令耗时更多的是毫秒范围时间,这主要是因为建立连接以及数据在网络传输占用了大部分时间。

  • *多路复用的IO模型

redis在网络层使用了基于epoll的NIO模型解决了高并发的问题。IO模型的基本理论知识

  • *丰富的数据结构

redis为了快速的根据key找到value,所以提供了一个全局的hash表来哭诉的获取到对应的value。

Redis是如何实现高性能的?

redis中的value其实有8种数据类型,但是比较常用的其实是5种(string、list、hash、set、sorted set | int、bit、[]int)。

Redis是如何实现高性能的?

对应每一种数据类型,redis的底层实现会根据当前的数据来选择不用的数据结构来进行优化,保证一些常用的操作可以在O(1)的时间内完成,但是实际上一些范围操作只能保证在O(N)以内。

Redis是如何实现高性能的?
  • *单线程执行

redis中在获取到所有客户端发来的命令请求后,都是由 一个线程来完成网络IO(协议解析)和键值对的读写,避免了在多线程下并发访问共享资源所带来的的一系列开销。

Redis的性能瓶颈常发生于哪些地方?

既然redis执行命令是单线程执行,那么很容易想到如果当执行命令的线程(主线程),被阻塞了或是执行耗时,那么在该命令之后的所有命令都必须等待当前的命令执行完成之后才会被执行。所以通常来说,redis的性能瓶颈会发生在以下几个地方:

1.大key的操作:无论是读或写,涉及到大key就必然意味着内存和性能的消耗都是较大的;

2.使用了复杂度较高的命令:只要是非O(1),其他如O(N)甚至O(logN)的操作[SORT/SUNION/ZUNIONSTORE]只要N足够大,依然会耗费大量的CPU计算时间,尤其是当宿主机有其他服务在抢资源的时候,延时更为严重;

3.大量的key集中过期:key的过期处理也是由主线程执行,所以大量的key过期时,必然导致主线程在执行过期处理完成之前,无法响应客户端的命令;

4.内存淘汰机制:内存淘汰也是由主线程自己处理的,当redis的内存被耗尽之后,会根据配置的算法【一般是lru或lfu】进行淘汰一定的key。这种情况下自然也会导致主线程无法快速响应客户端;

5.AOF的always刷盘机制:always的刷盘机制,也是有主线程完成的,由于是对磁盘的写操作,必然会对主线程产生一定的影响;

6.fork操作:fork操作是操作系统提供的一个内核API,redis在执行RDB或AOF重写时,会fork一个子线程去完成,并且使用CopyOnWrite的机制节约内存。但是fork出一个子线程的时候需要拷贝一个线程所必要的数据结构以及页表(虚拟内存与物理内存的映射)这个操作主线程必然是阻塞的。相对来说线程的数据结构是相对固定的,但是页表是和实例的大小相关的,实例内存越大,拷贝的页表的耗时也自然更大,延时自然更长;

7.redis所在实例cpu负载过高:负载过高必然导致cpu的争用,当redis的主线程抢占不到cpu执行权时,就只能自我阻塞;此外有一点需要注意的是,如果将redis的主线程与CPU进行核绑时,在fork操作时,fork出的子线程会继承父线程的核绑特性,子线程会与父线程争用同一个CPU;

8.redis的并发过高:虽然redis采用的是epoll的非阻塞IO,但本质上仍然是同步IO,读写客户端的数据只能采用单线程的机制,无法利用CPU的多核;此外,当并发过高,网卡的带宽被占光时,在客户端看来主线程也是被阻塞住了,这种场景通常发生在实例所在的服务器有其他服务消耗了大量的带宽,这种情况下只能将某些服务放到其他地方。另一种极端的情况是redis单机的实例的并发就将网卡打爆了,这种情况一般发生在机器硬件的差距上【CPU和内存都强悍,就是网卡差(可能是老机器遗留)】,这种情况可以选择换硬件、亦或是对redis进行水平拓展,如:哨兵、集群分片。

总的来说其实无非就是三个点:1.主线程等待CPU的执行、2.主线程执行单个命令耗时或是等待某个资源耗时,导致后续的命令被阻塞、3.主线程能处理,但是数据传输拉胯,导致客户端的请求进来慢或响应客户端的数据出去慢。但是CPU不够的情况下是相对少见【因为也就一个主线程可能在不间断的执行,而其他线程都是间歇性执行】,更多的是内存和网络IO上的瓶颈。

参考文章

1.极客时间专栏课-redis核心技术与实战
2.<

Original: https://www.cnblogs.com/zhenjungan/p/16492437.html
Author: zhenjungan
Title: Redis是如何实现高性能的?

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/581880/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 方法的深度理解

    权限修饰符 返回值类型 类名(行参列表 )throws 异常的类型{ //方法体 约定俗称:子类中叫重写的方法,父类中叫被重写的方法。 ①子类重写的方法名和行参列表和父类被重写的方…

    Linux 2023年6月14日
    0107
  • RAID磁盘阵列

    RAID磁盘阵列 *本章重点:了解各RAID级别的原理优缺点及常用级别实现,企业中厂商大多提供了硬RAID方案。 1、什么是RAID? “RAID”一词是由…

    Linux 2023年6月7日
    096
  • Spring Session Redis

    http://www.infoq.com/cn/articles/Next-Generation-Session-Management-with-Spring-Session Or…

    Linux 2023年5月28日
    099
  • MongoDB建立主从复制小案例(一主一从)

    1. 开启两个mongo服务器(用于一主一从, 没有加安全验证相关参数 : 可以使用mongd-help查看) mongod –bind_ip IP –po…

    Linux 2023年6月6日
    0105
  • linux配置yum源的三种方法

    镜像下载、域名解析、时间同步请点击阿里云开源镜像站 linux配置yum源的三种方法: 1.配置网络yum源 2.通过上传镜像文件配置本地yum源 3.通过连接存储或本地镜像文件配…

    Linux 2023年5月27日
    092
  • Linux下 lsof 命令详解

    lsof 是 List Open File 的缩写, 它主要用来获取被进程打开文件的信息,我们都知道,在Linux中,一切皆文件,lsof命令可以查看所有已经打开了的文件,比如: …

    Linux 2023年6月13日
    0110
  • 深入理解java泛型

    什么是Java泛型 泛型的使用 泛型类 泛型接口 泛型方法 泛型的底层实现机制 ArrayList源码解析 什么是泛型擦除 泛型的边界 ?:无界通配符 extends 上边界通配符…

    Linux 2023年6月6日
    0135
  • docker 安装redis

    1: 搜索镜像, docker search redis2:&#xA0;<strong>docker pull redis:6.0.6</strong&g…

    Linux 2023年5月28日
    0100
  • RPA微信机器人汇总

    bash;gutter:true; 一、微信广告PDF对账单数据提取机器人 【机器人详情】 微信广告对账结算单为PDF文件,从每一期对账单文件中提取结算数据,统计成excel表格,…

    Linux 2023年6月7日
    0131
  • ASP.NET Web API实现POST报文的构造与推送

    毕设和OAuth协议相关,而要理解OAuth协议就必须理解HTTP GET/POST方法。因此研究了一下如何使用Web API或MVC构造POST报文并实现客户端与服务器端的交互。…

    Linux 2023年6月13日
    0102
  • 线程池如何保证核心线程一直存活

    转载请注明出处: 查看 ThreadPoolExecutor 类中的 getTask 方法,这个方法可以保持核心线程在没有任务的时候也可以一直处于存活状态 核心在于 workQue…

    Linux 2023年6月14日
    0164
  • Pod控制器类型

    Pod是kubernetes的最小管理单元,在kubernetes中,按照pod的创建方式可以将其分为两类: 自主式pod:kubernetes直接创建出来的Pod,这种pod删除…

    Linux 2023年6月6日
    0185
  • 回顾乐信集团工作经历

    2019年入职乐信用户增长部门,负责开发开放平台的需求和合作方技术支持。乐信金融开放平台提供了金融业务API以及配套SDK等组件,为合作商户的产品赋予分期支付和小额贷款能力,子系统…

    Linux 2023年6月6日
    098
  • [LINUX] Arch Linux 硬盘拷贝式装系统+新增 home 分区

    前言 1. 实操 1.1 整个磁盘拷贝 1.2 创建 home 分区 1.3 修改 fstab 实现自动挂载 2. 涉及到的知识点 2.1 fstab 2.2 dd 命令 2.3 …

    Linux 2023年5月27日
    0196
  • Web前端基础精品入门(HTML+CSS+JavaScript+JS)[爱前端]听课笔记2:导航条的制作——css学习仿作马蜂窝

    马蜂窝的首页是非常正能量,青春的网页,首页非常大气 logo在上一篇我们已经制作好,现在我们开始制作导航条 这个导航条字数不等,宽窄不一致,就是所有的li不一样宽,字多就宽,字少就…

    Linux 2023年6月14日
    084
  • 数据结构001–数据结构概述

    数据结构概述: 程序 = 数据结构 + 算法 算法:一些计算方法,解决问题的流程/步骤(顺序、分支、循环……),通俗的说,算法相当于逻辑,小部分已经被人们发…

    Linux 2023年6月6日
    068
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球