用过redis哪些数据类型?Redis String 类型的底层实现是什么?
Redis 数据类型有哪些?
详细可以查看:数据类型及其应用场景
基本数据类型:
- String:最常用的一种数据类型,String类型的值可以是字符串、数字或者二进制,但值最大不能超过512MB。一般用于 缓存和计数器
- Hash:Hash 是一个键值对集合。存储商品的各个属性
- Set:无序去重的集合。Set 提供了交集、并集等方法,对于实现共同好友、共同关注等功能特别方便。
- List:有序可重复的集合,底层是依赖双向链表实现的。用于消息队列
- SortedSet:有序Set。内部维护了一个
score的参数来实现。适用于排行榜和带权重的消息队列等场景。
特殊的数据类型:
- Bitmap:位图,可以认为是一个以位为单位数组,数组中的每个单元只能存0或者1,数组的下标在 Bitmap 中叫做偏移量。Bitmap的长度与集合中元素个数无关,而是与基数的上限有关。
- Hyperloglog。HyperLogLog 是用来做基数统计的算法,其优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定的、并且是很小的。典型的使用场景是统计独立访客。
- Geospatial :主要用于存储地理位置信息,并对存储的信息进行操作,适用场景如定位、附近的人等。
- Stream :一种日志数据结构,适合于存储时间序列数据或消息流。支持高效的消息生产和消费模式,具有持久性和序列化特性。
SortedSet和List异同点?
相同点:
- 都是有序的;
- 都可以获得某个范围内的元素。
不同点:
- 列表基于链表实现,获取两端元素速度快,访问中间元素速度慢;
- 有序集合基于散列表和跳跃表实现,访问中间元素时间复杂度是OlogN;
- 列表不能简单的调整某个元素的位置,有序列表可以(更改元素的分数);
- 有序集合更耗内存。
Redis 怎么实现消息队列?
BLPOP queue 0 //0表示不限制等待时间
BLPOP和LPOP命令相似,唯一的区别就是当列表没有元素时BLPOP命令会一直阻塞连接,直到有新元素加入。
redis可以通过pub/sub主题订阅模式实现一个生产者,多个消费者,当然也存在一定的缺点,当消费者下线时,生产的消息会丢失。
PUBLISH channel1 hi
SUBSCRIBE channel1
UNSUBSCRIBE channel1 //退订通过SUBSCRIBE命令订阅的频道。
PSUBSCRIBE channel?*按照规则订阅。
PUNSUBSCRIBE channel?*退订通过PSUBSCRIBE命令按照某种规则订阅的频道。其中订阅规则要进行严格的字符串匹配,PUNSUBSCRIBE *无法退订channel?*规则。
如何在 Redis 中实现队列和栈数据结构?
可以通过 List 类型 来实现 队列 和 栈
实现队列(FIFO):队列是一种 先进先出(FIFO)的数据结构。在Redis中,可以使用 PUSH 和 RPOP命令组合来实现队列。LPUSH 向列表的左侧推入元素,而 RPOP从列表的右侧弹出元素,这样可以保证最先进入的元素最先被弹出
实现栈(LIFO):栈是一种 后进先出(LIFO)的数据结构。在Redis 中,可以使用 LPUSH和 LPoP命令组合来实现栈。LPUSH 向列表的左侧推入元素,而 LPoP从列表的左侧弹出元素,这样可以保证最后进入的元素最先被弹出。
Redis 怎么实现延时队列
使用sortedset,拿时间戳作为score,消息内容作为key,调用zadd来生产消息,消费者用zrangebyscore指令获取N秒之前的数据轮询进行处理。
如何使用 Redis 快速实现排行榜?
使用 Redis 实现排行榜的方式主要利用 Sorted Set(有序集合),它可以高效地存储、更新、以及获取排名数据。实现排行榜的主要步骤:
- 使用 Sorted Set 存储分数和成员:使用 Redis 的 ADD命令,将用户和对应的分数添加到有序集合中。例如:add leaderboard 1000 user1,将用户 user1 的分数设置为 1000。
- 获取排名:使用 ZRANK命令获取某个用户的排名。例如:zrank leaderboard user1,返回用户user1 的排名(从0开始)。
- 获取前 N 名:使用 ZREVRANGE 命令获取分数最高的前N名。例如:REVRANGE leaderboard 0 9 WITHSCORES ,获取排行榜前 10 名用户及其分数。
- 更新分数:如果用户的分数需要更新,可以使用 ZINCRBY 命令对其分数进行加减操作。例如:ZINCRBY leaderboard 500 user1,将用户 user1 的分数增加 500。
如何使用 Redis 快速实现布隆过滤器?
可以通过使用 位图(Bitmap)或使用 Redis 模块 RedisBloom。
- 使用位图实现布隆过滤器:使用 Redis 的位图结构 SETBIT 和 GETBIT 操作来实现布隆过滤器。位图本质上是一个比特数组,用于标识元素是否存在对于给定的数据,通过多个 哈希函数 计算位置索引,将位图中的相应位置设置为 1,表示该元素可能存在。
- 使用 RedisBloom 模块:Redis 提供了一个官方模块 RedisBloom,封装了哈希函数、位图大小等操作,可以直接用于创建和管理布隆过滤器。使用 BF.ADD 来向布隆过滤器添加元素,使用 BF.EXISTS 来检查某个元素是否可能存在,
如何使用 Redis 统计大量用户唯一访问量(UV)?
Redis 中 HyperLogLog 结构,可以快速实现网页UV、PV 等统计场景。它是一种基数估算算法的概率性数据结构,可以用极少的内存统计海量用户唯一访问量的近似值。
Set 也可以实现,用于精确统计唯一用户访问量,但是但当用户数非常大时,内存开销较高。
Redis 中的 Geo 数据结构是什么?
Redis中的 Geo(Geoloaton的简写形式,代表地理坐标) 数据结构主要用于地理位置信息的存储,通过这个结构,可以方便地进行地理位置的存储、检索、以及计算地理距离等课作,GeO 数据结内存层使用了 Sorted set, 并结合了Geohash 编码算法来对地理位置进行处理。
Redis String 类型的底层实现是什么?(SDS)
Redis 中的 Sting 类型底层实现主要基于 SDS(Simple Dynamic string 简单动态字符串)结构,并结合 int、embstr、raw 等不同的编码方式进行优化存储。
详情请看这篇文章:Redis是如何高效存储与访问数据?
Redis 中的 Ziplist 和 Quicklist 数据结构的特点是什么?
Ziplist:
- 简单、紧凑、连续存储,适用于小数据量场景,但对大量数据或频繁的修改操作不太友好。
- 适合小数据量场景,例如短列表、小哈希表等,因为它的内存紧凑,可以大幅减少内存使用
Quicklist:
- 通过将链表和 Ziplist 结合,既实现了链表的灵活操作,又能节省内存,在 Redis 3.2 之后成为 List 的默认实现。
- Quicklist是为了替代纯而设计的,适用于需要频繁对列表进行插入、删除、查找等提作的场景,并目数据量可能较大,它在存储多个元素时,既保留了链表的灵活性,又具备压缩列表的内存优势
Redis Zset 的实现原理是什么?
Redis 中的Zset(有序集合,Sorted set)是一种由 跳表 (Skip List)和哈希表 (Hash Table)组成的数据结构,Zset 结合了集合 (Set)的特性和排序功能,能够存储具有唯一性的成员,并根据成员的分数 (score) 进行排序
ZSet 的实现由两个核心数据结构组成:
- 跳表(Skip List):用于存储数据的排序和快速查找。
- 哈希表(Hash Table):用于存储成员与其分数的映射,提供快速查找
当 Zset 元素数量较少时,Redis 会使用压缩列表(Zip List)来节省内存
- 即元素个数≤ zset-max-ziplist-entries(默认 128)
- 元素成员名和分值的长度 ≤ zset-max-ziplist-value(默认 64 字节)
如果任何一个条件不满足,Zset 将使用 跳表 +哈希表 作为底层实现,
Redis 的有序集合底层为什么要用跳表,而不用平衡树、红黑树或者 B+树?
这道面试题很多大厂比较喜欢问,难度还是有点大的。
平衡树 vs 跳表:平衡树的插入、删除和查询的时间复杂度和跳表一样都是 O(log n)。对于范围查询来说,平衡树也可以通过中序遍历的方式达到和跳表一样的效果。但是它的每一次插入或者删除操作都需要保证整颗树左右节点的绝对平衡,只要不平衡就要通过旋转操作来保持平衡,这个过程是比较耗时的。跳表诞生的初衷就是为了克服平衡树的一些缺点。跳表使用概率平衡而不是严格强制的平衡,因此,跳表中的插入和删除算法比平衡树的等效算法简单得多,速度也快得多。
红黑树 vs 跳表:相比较于红黑树来说,跳表的实现也更简单一些,不需要通过旋转和染色(红黑变换)来保证黑平衡。并且,按照区间来查找数据这个操作,红黑树的效率没有跳表高。
B+树 vs 跳表:B+树更适合作为数据库和文件系统中常用的索引结构之一,它的核心思想是通过尽可能少的 IO 定位到尽可能多的索引来获得查询数据。对于 Redis 这种内存数据库来说,它对这些并不感冒,因为 Redis 作为内存数据库它不可能存储大量的数据,所以对于索引不需要通过 B+树这种方式进行维护,只需按照概率进行随机维护即可,节约内存。而且使用跳表实现 zset 时相较前者来说更简单一些,在进行插入时只需通过索引将数据插入到链表中合适的位置再随机维护一定高度的索引即可,也不需要像 B+树那样插入时发现失衡时还需要对节点分裂与合并。
Redis 中跳表的实现原理是什么?
跳表主要是通过多层链表来实现,底层链表保存所有元素,而每一层链表都是下一层的子集。
插入时,首先从最高层开始查找插入位置,然后随机决定新节点的层数,最后在相应的层中插入节点并更新指针
删除时,同样从最高层开始查找要删除的节点,并在各层中更新指针,以保持跳表的结构。
查找时,从最高层开始,逐层向下,直到找到目标元素或确定元素不存在。查找效率高,时间复杂度为 O(logn)

Redis中的跳表是两步两步跳的吗?
如果采用新增节点或者删除节点时,来调整跳表节点以维持比例2:1的方法的话,显然是会带来额外开销的。
跳表在创建节点时候,会生成范围为[0-1]的一个随机数,如果这个随机数小于 0.25(相当于概率 25%),那么层数就增加 1 层,然后继续生成下一个随机数,直到随机数的结果大于 0.25 结束,最终确定该节点的层数。因为随机数取值在[0,0.25)范围内概率不会超过25%,所以这也说明了增加一层的概率不会超过25%。这样的话,当插入一个新结点时,只需修改前后结点的指针,而其它结点的层数就不需要随之改变了,这样就降低插入操作的复杂度。
// #define ZSKIPLIST_P 0.25
int zslRandomLevel(void) {
static const int threshold = ZSKIPLIST_P*RAND_MAX;
int level = 1; //初始化为一级索引
while (random() < threshold)
level += 1;//随机数小于 0.25就增加一层
//如果level 没有超过最大层数就返回,否则就返回最大层数
return (level<ZSKIPLIST_MAXLEVEL) ? level : ZSKIPLIST_MAXLEVEL;
}
Redis遇到哈希冲突怎么办?
当有两个或以上数量的键被分配到了哈希表数组的同一个索引上面时, 我们称这些键发生了冲突(collision)。
关于解决hash冲突问题可以看这篇文章:解决哈希冲突的三种方法
而redis是先通过拉链法解决,再通过rehash来解决hash冲突问题的,即再hash法,只不过redis的hash使渐进式hash
rehash原理?
渐进式 rehash 步骤如下:
- 先给
哈希表 2分配空间; - 在 rehash 进行期间,每次哈希表元素进行新增、删除、查找或者更新操作时,Redis 除了会执行对应的操作之外,还会顺序将
哈希表 1中索引位置上的所有 key-value 迁移到哈希表 2上; - 随着处理客户端发起的哈希表操作请求数量越多,最终在某个时间点会把
哈希表 1的所有 key-value 迁移到哈希表 2,从而完成 rehash 操作。
这样就把一次性大量数据迁移工作的开销,分摊到了多次处理请求的过程中,避免了一次性 rehash 的耗时操作。
在进行渐进式 rehash 的过程中,会有两个哈希表,所以在渐进式 rehash 进行期间,哈希表元素的删除、查找、更新等操作都会在这两个哈希表进行。比如,在渐进式 rehash 进行期间,查找一个 key 的值的话,先会在哈希表 1里面进行查找,如果没找到,就会继续到哈希表 2 里面进行找到。新增一个 key-value 时,会被保存到哈希表 2里面,而哈希表 1则不再进行任何添加操作,这样保证了哈希表 1的 key-value 数量只会减少,随着 rehash 操作的完成,最终哈希表 1就会变成空表。
rehash的触发条件?
负载因子 = 哈希表已保存节点数量/哈希表大小
触发 rehash 操作的条件,主要有两个:
- 当负载因子大于等于 1 ,并且 Redis 没有在执行 bgsave 命令或者 bgrewiteaof 命令,也就是没有执行 RDB 快照或没有进行 AOF 重写的时候,就会进行 rehash 操作。
- 当负载因子大于等于 5 时,此时说明哈希冲突非常严重了,不管有没有有在执行 RDB 快照或 AOF 重写,都会强制进行 rehash 操作
一个REDIS实例最多能存放多少KEYS
redis 的每个实例最多可以存放约 2^32 - 1 个keys,即大约 42 亿个keys。这是由 Redis 内部使用的哈希表实现决定的,它使用 32 位有符号整数作为索引。Redis 使用的哈希函数和负载因子等因素也会影响实际可存放键的数量。
需要注意的是,尽管 Redis 允许存储数量庞大的键,但在实践中,存储过多的键可能会导致性能下降和内存消耗增加。因此,在设计应用程序时,需要根据实际需求和硬件资源来合理规划键的数量,避免过度使用 Redis 实例造成负担。如果需要存储更多的键值对,可以考虑使用 Redis 集群或分片技术,以扩展整体存储容量。
用过redis哪些数据类型?Redis String 类型的底层实现是什么?的更多相关文章
- redis 五大数据类型之string篇
一: 1:string(字符串) string是redis最基本的类型,你可以理解成与Memcached一模一样的类型,一个key对应一个value. string类型是二进制安全的.意思是redis ...
- ***Redis hash是一个string类型的field和value的映射表.它的添加、删除操作都是O(1)(平均)。hash特别适合用于存储对象
http://redis.readthedocs.org/en/latest/hash/hset.html HSET HSET key field value (存一个对象的时候key存) 将哈希 ...
- Redis的数据类型以及各类型的操作
讲完安装和配置,接下来就是所有数据库的重头戏,数据结构和常用操作的增删改查了 redis是key-value的数据结构,每条数据都是⼀个键值对 键的类型是字符串 注意:键不能重复 值的类型分为五种: ...
- Redis hash 是一个 string 类型的 field 和 value 的映射表.它的添加、删除操作都是 O(1)(平均)。
2.3 hashes 类型及操作 Redis hash 是一个 string 类型的 field 和 value 的映射表.它的添加.删除操作都是 O(1)(平均).hash 特别适合用于存储对象.相 ...
- go中基本数据类型转换为string类型的方法
代码 // 基本数据类型转换为string类型 package main import ( "fmt" "strconv" ) func main() { // ...
- Redis学习笔记(三)-数据类型之string类型
string是redis最基本的类型,而且string类型是二进制安全的.意思是redis的string可以包含任何数据.比如jpg图片或者序列化的对象.从内部实现来看其实string可以看作byte ...
- Redis基本数据类型以及String(一)
前言: Redis也有自己的数据类型,包含string,list,hash,set,sorted set.下面就对每种数据类型原理以及操作做一个详细的介绍. Redis是面向编程的语言 ...
- Redis的数据类型之String
Redis主要支持的数据类型有5种:String ,Hash ,List ,Set ,和 Sorted Set. Redis数据类型String string类型在redis中是最常见的类型,valu ...
- 专题二:redis的数据类型之string
一.redis的数据存储格式 redis本身是一个Map,其中所有的数据都是采用 "key:value"的方式进行存储的. 我们说的数据类型是数据存储的类型,也就是对应下图的val ...
- redis中关于使用string类型还是hash类型
前篇:最近在做一个将redis中大数据量进行合并缩减优化的工作,其中一项按月将数据进行合并.将一个月的数据放入一个key-value键值对中. 例:p2d20180901-3.p2d20180902- ...
随机推荐
- 记一道有趣的交互题 noi.ac #2035歪比巴卜
记一道有趣的交互题 noi.ac #2035歪比巴卜 Problem Alice手上有两个\(\le n\)且不同的正整数\(x,y\),Bob手上有一个正整数\(z\),已经确认是\(x\)或\(y ...
- MYSQL优化学习总结
mysql学习小结---索引的使用及优化 1. 索引那些事 1.1 复合索引 复合索引是指:包含一个或者多个列的索引.但复合索引的触发是有条件的. 假设我们现在有一个复合索引a,a中包含了三个列(id ...
- C++面试题:虚函数表(vtable)的底层实现机制与应用解析
一.问题描述 请描述C++虚函数表的实现原理,并解释以下问题: 虚函数表在内存中的存储位置及布局结构 多继承场景下虚函数表的组织形式 虚函数调用时的动态绑定过程 虚析构函数与虚函数表的关系 二.核 ...
- 抖音主播选品到复盘:8款增长工具提升直播ROI
随着短视频和直播电商的快速崛起,抖音直播成为品牌和主播们争相布局的风口.想要在激烈的直播竞争中脱颖而出,主播不仅需要精准选品,更要借助多样的增长工具,提升直播的观众转化和最终ROI(投资回报率).本文 ...
- PHP中关于static的使用方法
本文由 ChatMoney团队出品 PHP,作为一种面向对象的编程语言,为开发者提供了丰富的特性和功能,助力构建高效的应用程序.其中,static关键字在类和方法中的应用尤为重要,它提供了一种独特的变 ...
- 企业如何通过数据资产化,激活“数据要素x”,乘出新质生产力
放眼全球,数据作为一种新兴生产要素,在全球经贸活动中扮演着至关重要的角色,驱动着数字经济的蓬勃兴起.据前瞻预测,至2025年,全球数据流动对整体经济增长的贡献预估将达到惊人的11万亿美元. 近几年国家 ...
- SpringBoot3集成多款主流大模型
集成:DeepSeek,豆包,混元,通义千问. 一.简介 2025年7月份,开始转型独立开发者. 第一款尝试的产品自然是AI方向,此前不具备专业的产品经验,所以只能更多的依赖大模型的能力. 年初Dee ...
- 借助HarmonyOS SDK,《NBA巅峰对决》实现“分钟级启动”到“秒级进场”
<NBA巅峰对决>是由望尘科技推出的国内首个真实还原5V5王朝模式的操作篮球手游,提供流畅操作手感和真实篮球赛场体验.丰富的玩法在为玩家带来高质游戏体验的同时,间接带来了启动流程冗长的问题 ...
- 如何把数据库中的多个关联字段快速生成思维导图(excel如何将内容快速生成思维导图)
本次记录绝对干货 一:要求 今天遇到的需求,又是一件费力的活,要求如下:数据库中有三个字段,分别是一级分类,二级分类,三级分类,三个字段是级别关系,三级分类一共有上百个,现要求用思维导图的方式展示出来 ...
- react开发组件并发包到npm
Toast组件 import ReactDomCli from 'react-dom/client'; import './style.css' import React from 'react'; ...