redis 为什么这么快
前言
Redis 是一个开源的内存数据结构存储,广泛用于缓存、消息队列和实时数据处理等场景。Redis 之所以能够实现高性能和低延迟,主要归功于其设计和实现中的一些关键技术和优化策略。
Redis以性能著称,很快,到底有多快呢,我们来看一下官网提供的数据:
QPS可以达到100000,是什么原因让Redis这么快?主要有以下四点:
- Redis是基于内存的数据库
- IO多路复用
- 高效的数据结构
- 单线程模型
基于内存
Redis是基于内存的数据库,这样就减少了不必要的磁盘IO操作,大大提升了读写速度,下图是各种介质的处理时间
由上图可见,内存的存取时间大约为120纳秒,而硬盘的存取时间最快也要50微秒,换算下来,内存的速度至少是硬盘的400多倍。注:1ms=1000us,1us=1000ns,ms表示毫秒,us表示微秒,ns为纳秒。
IO多路复用
在Linux系统中有五种IO模型:阻塞IO,非阻塞IO,IO复用,信号驱动IO和异步IO。Linux内核使用文件描述符(File Descriptor, FD)来标识一个文件或者其他的IO资源(比如网络套接字),这些IO模型都使用FD来读写文件。
而IO多路复用中的“多路”是指多个网络连接,“复用”是共用同一个线程。它在单个线程中监听多个IO事件的状态变化,一旦IO就绪就进行处理。当多个socket客户端与服务端连接时,Redis的IO多路复用程序将对应的FD注册到队列中,而文件事件派发器监听该队列,它根据不同的事件选择不同的处理器。
高效数据结构
Redis采用高效的数据结构来提升性能,比如动态字符串、压缩列表、跳跃表等。
动态字符串:
动态字符串(SDS,Simple Dynamic String)是Redis存储字符串的底层实现,它可以动态调整大小,高效的进行字符串的追加、删除等操作
SDS本身包含了长度信息,能够以O(1)的复杂度获取字符串的长度信息。另外,SDS的空间分配策略和惰性空间释放策略,让字符串的操作更加高效。当然,SDS需要额外的空间存储这样的信息,导致它占用的内存较大。
struct sdshdr {
long len;
long free;
char buf[];
};
buf是保存实际数据的字节数组,而len为buf的实际长度,free表示额外的可用字节大小。压缩列表:压缩列表(ziplist)是一种紧凑型的数据结构,它比较适合用来存储一些较小的元素,比如字符串、整数或者浮点数等。压缩列表由一系列的条目组成,每个条目表示一个元素,它包括以下几个部分:
Prevlen:前一个条目的长度
Entrylen:当前条目的长度
Content:元素的实际内容列表中的这些元素都是连续的,这意味着不需要额外的元数据或者指针来记录元素间的关系。与其它的数据结构相比,比如双向链表,压缩列表减少了额外的内存开支。同时,这些元素是连接存放的,所以按序号访问时,用时都是常数时间。另外,Redis会自动在压缩列表和其他数据结构之间进行切换,比如双向链表,哈希表等。切换的标准与元素的大小和个数有关。跳表:
跳表(skiplist)是一种有序的数据结构,能够进行快速查找。通过层级的链表结构,实现了元素的快速操作,包括插入、删除等。
跳表在多个层级上建立索引,可以在O(logN)的时间内完成查找。通过跳跃这些元素的上层指针,可以跳过很多元素,从而实现快速的查找、插入和删除操作。
Redis还支持三大扩展数据类型:位图Bitmaps、基数统计HyperLogLog、地理位置GEO、Streams等。
单线程
Redis是一款内存数据库,绝大部分的操作都是在内存中进行的,所以它的性能瓶颈主要是内存操作和网络通信,而不是CPU。在这样的场景下,多线程就未必比单线程要快,因为CPU在一个时间片里只能执行一个线程,线程切换的时候就需要保存当前线程的上下文,包括一些额外的线程调度、同步等操作,这样就会降低Redis性能。
Redis不是CPU密集型的系统,单个线程足以满足计算要求,这样就避免了多线程带来的性能损耗,同时也让操作更加稳定。
Redis 使用单线程来处理客户端的请求,这是因为:
- 避免锁竞争:多线程编程中常见的锁竞争问题会导致性能下降。使用单线程可以避免这一问题,从而提供更高的性能和一致性。
- 简化编程:单线程模型使得代码更简单,没有复杂的线程同步问题,更容易维护和调试。
Redis 的单线程模型是指其主要的网络 I/O 和命令执行部分是由一个单线程来处理的。但这并不意味着 Redis 完全依赖单线程来处理所有的操作。实际上,Redis 利用了多种优化技术和机制来确保高效的性能。
Redis在6.0推出了多线程,可以在高并发场景下利用CPU多核多线程读写客户端数据,进一步提升性能,当然,只是针对客户端的读写是并行的,每个命令的真正操作依旧是单线程的。
多线程的使用
虽然 Redis 的核心操作是单线程的,但它在某些场景下也利用了多线程来优化性能。例如:
- 异步 I/O 操作:
- Redis 使用非阻塞 I/O 多路复用技术(如 epoll、kqueue 等)来处理网络连接和 I/O 操作。这使得即使单线程也能够高效地处理大量并发连接。
- 持久化操作:
- Redis 提供了 RDB(快照)和 AOF(追加文件)两种持久化机制。在执行这些持久化操作时,Redis 会通过后台子进程或线程来处理,以避免阻塞主线程。
- 例如,RDB 快照的生成是在一个子进程中进行的,而 AOF 重写则可以在后台线程中进行。
- 模块扩展:
- Redis 4.0 引入了模块系统,允许开发者编写自定义的 Redis 扩展。模块可以使用多线程来实现一些复杂的计算或 I/O 操作,而不会阻塞 Redis 的主线程。
redis 为什么这么快的更多相关文章
- 为什么说Redis是单线程的以及Redis为什么这么快!
参考文章:https://blog.csdn.net/xlgen157387/article/details/79470556 redis简介 Redis是一个开源的内存中的数据结构存储系统,它可以用 ...
- 为什么说Redis是单线程的以及Redis为什么这么快!(转)
文章转自https://blog.csdn.net/chenyao1994/article/details/79491337 一.前言 近乎所有与Java相关的面试都会问到缓存的问题,基础一点的会问到 ...
- Redis为什么这么快
Redis为什么这么快 1.完全基于内存,绝大部分请求是纯粹的内存操作,非常快速.数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1): 2.数据结构简单, ...
- Redis性能解析--Redis为什么那么快?
echo编辑整理,欢迎转载,转载请声明文章来源.欢迎添加echo微信(微信号:t2421499075)交流学习. 百战不败,依不自称常胜,百败不颓,依能奋力前行.--这才是真正的堪称强大!!! Red ...
- 《为什么说Redis是单线程的以及Redis为什么这么快!》
为什么说Redis是单线程的以及Redis为什么这么快! 一.前言 近乎所有与Java相关的面试都会问到缓存的问题,基础一点的会问到什么是“二八定律”.什么是“热数据和冷数据”,复杂一点的会问到缓 ...
- [转帖]Redis性能解析--Redis为什么那么快?
Redis性能解析--Redis为什么那么快? https://www.cnblogs.com/xlecho/p/11832118.html echo编辑整理,欢迎转载,转载请声明文章来源.欢迎添加e ...
- 为什么说Redis是单线程的以及Redis为什么这么快!(转)
一.前言 近乎所有与Java相关的面试都会问到缓存的问题,基础一点的会问到什么是“二八定律”.什么是“热数据和冷数据”,复杂一点的会问到缓存雪崩.缓存穿透.缓存预热.缓存更新.缓存降级等问题,这些看似 ...
- 性能测试 | 理解单线程的Redis为何那么快?
前言 Redis是一种基于键值对(Key-Value)的NoSQL数据库,Redis的Value可以由String,hash,list,set,zset,Bitmaps,HyperLogLog等多种数 ...
- Redis 为什么这么快?
1. 纯内存操作,肯定快 数据存储在内存中,读取的时候不需要进行磁盘的 IO 2. 单线程,无锁竞争损耗 单线程保证了系统没有线程的上下文切换 使用单线程,可以避免不必要的上下文切换和竞争条件,没有多 ...
- Redis为什么这么快?
Redis为什么这么快?
随机推荐
- 一些好用的IDEA插件
彩虹括号插件 Rainbow Brackets 可以让成对的括号展示相同颜色 Free Mybatis Tool插件 去看我另一篇文章:https://www.cnblogs.com/maomao77 ...
- AEM6.5集成Redis详细步骤(附代码)
一.环境准备 Redis 安装 2.配置 Redis 远程访问 二.AEM 端配置 1.添加 Redis 客户端依赖 在 AEM 项目的pom.xml中添加: <dependency> & ...
- vue3 + springboot实现微信登录
创建VUE3项目 创建初始文件 进入项目存放位置 右键用命令行打开(终端打开) npm create vite@latest wechat-report --template vue npm:包管理需 ...
- ArkUI-X资源分类与访问
应用开发过程中,经常需要用到颜色.字体.间距.图片等资源,在不同的设备或配置中,这些资源的值可能不同. 应用资源:借助资源文件能力,开发者在应用中自定义资源,自行管理这些资源在不同的设备或配置中的表现 ...
- 使用 Spread.net将 Excel 中的文本拆分为多段
引言: 在 .NET 应用程序中处理 Excel 数据时,常常会碰到需要把文本拆分成多段的情况.例如在数据清洗.数据分析等场景下,将长文本按照特定规则拆分为多段能让数据更便于处理和分析.Spread. ...
- Elastic学习之旅 (5) 倒排索引和Analyzer分词
大家好,我是Edison. 上一篇:ES文档的CRUD操作 重要概念1:倒排索引 在学习ES时,倒排索引是一个非常重要的概念.要了解倒排索引,就得先知道什么是正排索引.举个简单的例子,书籍的目录页(从 ...
- ZKW 非递归线段树详解
在算法竞赛和高性能计算场景中,线段树(Segment Tree) 是一个必修的数据结构.它可以在 $O(\log n)$ 时间内高效地完成区间查询与修改,比如:区间求和/最大/最小值查询配合区间加法/ ...
- python 超声波通信编码技术支点
https://www.allaboutcircuits.com/technical-articles/fsk-explained-with-python/ 分析注释 VCO 主要分频率了两个区间一个 ...
- 技术纯小白零基础用Win系统搭建Claude Code教程
项目背景 听说Claude很好用,同时看见Anyrouter有免费赠送100美金额度的活动(https://anyrouter.top/register?aff=1qUq领取地址),萌生了试用的想法. ...
- ETL数据集成丨MySQL到MySQL的数据迁移实践
前言 MySQL数据迁移至另一MySQL数据库的过程,不仅是数据复制或移动的操作那么简单,它还涉及到一系列策略性考量和技术优化,旨在实现数据的高效.安全传输,以及确保目标系统的高性能运行.其深远意义在 ...