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)

大家都在看

  • Vue3

    setup 函数时,它将接受两个参数:(props、context(包含attrs、slots、emit)) setup函数是处于 生命周期函数 beforeCreate 和 Cr…

    Linux 2023年6月13日
    083
  • Linux 配置Maven(避免踩坑篇)

    前言:请各大网友尊重本人原创知识分享,谨记本人博客: 南国以南i 二、下载好的maven安装包放在磁盘的 /usr/local/ 目录下,如下图: 三、解压该压缩文件 tar -z…

    Linux 2023年6月14日
    0100
  • mysql二进制安装脚本部署

    mysql二进制安装脚本部署 mysql二进制安装脚本部署 单实例 使用函数的单实例 使用函数的单实例或者多实例 单实例 [root@localhost ~]# mkdir mys…

    Linux 2023年6月6日
    0110
  • 使用docker 5分钟搭建一个博客(mysql+WordPress)

    一.系统环境 二.前言 三.搭建博客 3.1 创建wordpress和mysql容器 3.2 在wordpress界面设置个人博客信息 3.3 WordPress容器创建命令的简化…

    Linux 2023年6月7日
    096
  • WEB自动化-04-Cypress 测试用例编写和组织

    4 测试用例编写和组织 4.1 用例结构 Cypress是建立在 Mocha和 Chai之上,因此同时支持Chai的 BDD和 TDD两种风格。如果你熟悉JavaScript风格的…

    Linux 2023年6月7日
    0105
  • http代理连接

    基于Linux服务器的http代理连接 1. 准备工作 &#x76EE;&#x6807;&#x670D;&#x52A1;&#x5668; &…

    Linux 2023年5月27日
    099
  • NO.4 计算机组成原理-笔记

    404. 抱歉,您访问的资源不存在。 可能是网址有误,或者对应的内容被删除,或者处于私有状态。 代码改变世界,联系邮箱 contact@cnblogs.com 园子的商业化努力-困…

    Linux 2023年6月7日
    086
  • GDT表实现

    GDT是保护模式下的内存段登记表。 段界限计算 段界限用 20 个二进制位来表示。只不过此段界限只是个单位量,它的单位要么是字节,要么是 4K,这是由描述符中的G位来指 定的。由于…

    Linux 2023年6月7日
    080
  • 批量新建域用

    前几个章节我们讲到Windows Server 2016-图形化新建域用户(一),本章节我们简单讲解下如何通过命令批量创建域用户,以便高效完成日常工作中实际批量创建用户需求,内容涉…

    Linux 2023年6月13日
    089
  • shell编程-杨辉三角简单实现

    shell编程-杨辉三角问题: 概述:中国古代数学家在数学的许多重要领域中处于遥遥领先的地位。中国古代数学史曾经有自己光辉灿烂的篇章,而杨辉三角的发现就是十分精彩的一页。杨辉三角形…

    Linux 2023年6月7日
    0104
  • 微信开发之微信分享 + php

    html DOCTYPE html> <html> <head> <meta http-equiv="content-type&quo…

    Linux 2023年6月7日
    099
  • 十、进程管理

    什么是进程?进程(Process)是一个程序在其自身的虚拟地址空间的一次执行活动。之所以要创建进程,就是为了使多个程序可以并发的执行,从而提高系统的资源利用率和吞吐量。简单来说进程…

    Linux 2023年6月7日
    0137
  • anaconda创建虚拟环境

    anaconda创建虚拟环境 1·查看当前存在的虚拟环境 conda env list 或者 conda info -e 2·创建虚拟环境,环境名重要 conda create -…

    Linux 2023年6月14日
    095
  • SpringBoot + Vue + ElementUI 实现后台管理系统模板 — 后端篇(三): 整合阿里云 OSS 服务 — 上传、下载文件、图片

    (1) 相关博文地址: SpringBoot + Vue + ElementUI 实现后台管理系统模板 — 前端篇(一):搭建基本环境:https://www.cnblogs.c…

    Linux 2023年6月11日
    078
  • 排序算法

    内部排序 这里先介绍一个概念,算法稳定性 算法稳定性 — 假设在数列中存在a[i]=a[j],若在排序之前,a[i]在a[j]前面;并且排序之后,a[i]仍然在a[j]…

    Linux 2023年6月6日
    0128
  • Linux系统安装Mysql8.0流程与遇到的问题

    安装MySQL版本为:8.0.16 1、首次安装,下载命令: wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8….

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