面试:Redis为什么这么快?

Redis作为高性能的内存数据存储,其速度得益于完全基于内存的读写、单线程模型以避免并发控制开销,以及使用I/O多路复用技术提高并发能力。它采用动态字符串、zipList、quicklist、skipList和intset等高效数据结构,并通过渐进式rehash解决哈希冲突,确保快速响应。此外,Redis还利用预分配空间和惰性释放策略优化内存管理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

官方数据QPS(每秒请求数量)可达到10万

1.完全基于内存

        不论读写都是在内存中完成,吊打磁盘读写,直接由CPU控制和内存对接。

2.单线程模型

        网络IO(6以后也使用多线程)和键值对指令读写是由一个线程来执行。

        持久化,数据同步,异步删除是用其他线程执行的

        为什么不使用多线程来充分利用cpu

                1.多线程需要不停的并发读写,这是特别消耗资源的

                2.如果并发读写的话,就需要保护共享资源

        好处:

                不用因为创建线程导致性能消耗

                避免上下文切换引起CPU消耗,没有多线程切换的开销

                避免了线程之间的竞争问题,比如添加锁,释放锁,死锁等 ,不需要考虑锁的问题

                代码更清晰,逻辑更简单

3.IO多路复用

        

        Redis 采用 I/O 多路复用技术,并发处理连接。采用了 epoll + 自己实现的简单的事件框架。

        epoll 中的读、写、关闭、连接都转化成了事件,然后利用 epoll 的多路复用特性,绝不在 IO 上浪费一点时间。

        Redis 线程不会阻塞在某一个特定的监听或已连接套接字上,也就是说,不会阻塞在某一个特定的客户端请求处理上。正因为此,Redis 可以同时和多个客户端连接并处理请求,从而提升并发性。

相关参考链接:

(55条消息) io多路复用的原理和实现_彻底理解 IO 多路复用实现机制_weixin_39934085的博客-优快云博客

4.底层高效的数据结构

        Redis 一共有 5 种数据类型,String、List、Hash、Set、SortedSet

不同的数据类型,底层用一种或多种不同的数据结构支撑。

动态字符串(String):

        空间预分配:不仅会分配所需要的必须空间,还会额外分配未使用空间

        惰性空间释放:SDS缩短,不回收多余的内存空间,直接用free字段记录下来,后续append

直接使用,不用在分配。

zipList(List,Hash,SortedSet):

        只有少量数据,要么是长度比较短的字符串,内存紧凑节省空间

quicklist(List,Hash,SortedSet)

        后续版本对linkedList和ziplist改造,quicklist代替了ziplist和linkedlist,将linkedlist按段儿拆分,每一段用ziplist来紧凑,多个list使用双向指针连链接。

skipList(sortSet)

        sortSet类型的排序功能就是通过跳表来实现的

        跳表是一种有序的数据结构,每个节点中维持多个指向其他节点的指针

        增加多层级索引,通过多次跳转来快速定位数据位置 

整型数组(intset)

        当一个集合只包含整数值元素,并且这个集合的元素数量不多时,Redis 就会使用整数集合作为集合键的底层实现,节省内存。

5.Redis 全局 hash 字典

        Redis 整体就是一个 哈希表来保存所有的键值对,无论数据类型是 5 种的任意一种。哈希表,本质就是一个数组,每个元素被叫做哈希桶,不管什么数据类型,每个桶里面的 entry 保存着实际具体值的指针。

        

而哈希表的时间复杂度是 O(1),只需要计算每个键的哈希值,便知道对应的哈希桶位置,定位桶里面的 entry 找到对应数据,这个也是 Redis 快的原因之一。

 hash冲突怎么办?

        Redis 通过链式哈希解决冲突:也就是同一个 桶里面的元素使用链表保存。但是当链表过长就会导致查找性能变差可能,所以 Redis 为了追求快,使用了两个全局哈希表。用于 rehash 操作,增加现有的哈希桶数量,减少哈希冲突。

开始默认使用 「hash 表 1 」保存键值对数据,「hash 表 2」 此刻没有分配空间。当数据越来越多触发 rehash 操作,则执行以下操作:

  1. 给 「hash 表 2 」分配更大的空间;
  2. 将 「hash 表 1 」的数据重新映射拷贝到 「hash 表 2」 中;
  3. 释放 「hash 表 1」 的空间。

值得注意的是,将 hash 表 1 的数据重新映射到 hash 表 2 的过程中并不是一次性的,这样会造成 Redis 阻塞,无法提供服务。

而是采用了渐进式 rehash,每次处理客户端请求的时候,先从「 hash 表 1」 中第一个索引开始,将这个位置的 所有数据拷贝到 「hash 表 2」 中,就这样将 rehash 分散到多次请求过程中,避免耗时阻塞。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值