浅谈Redis的数据结构

Redis简介

redis是一款非关系型数据库,是以key-value形式存储数据,其具有丰富的数据类型和广泛的用途,如缓存,分布式锁等。其优秀的性能受到了很多人的喜爱。下面我们一起讲讲redis。

Redis的数据类型

很多人选择redis的原因之一就是因为它拥有丰富的数据类型供我们使用,redis一共有九大数据类型,分别是String、List、Hash、Set、Zset、Hyperloglog、GEO、Stream、BitMap。其中String、List、Hash、Set、Zset是常用的五种数据结构。下面我们一起了解一下这些数据结构具体的内容。

String

String类型是redis比较常用的一种数据类型。他的底层主要有两种数据结构组成,分别是int和SDS(简单动态字符串)。

编码格式

int:当存储的数据类型是Long时,编码格式为int,数据存储在Object对象的ptr属性之中

embstr:当存储的类型是字符串时,且字符串的长度小于某个值时(redis2.0+时是32字节,3.0开始是39字节,5.0开始是44字节)。此时把Object对象和存储的分配在一块内存上。

raw:当存储的类型是字符串,且字符串长度不满足embstr格式的要求时使用,raw和embstr的区别就在于,raw格式把Object对象和存储的SDS数据分别分配到两块内存上。

既然有了embstr格式为什么还有raw格式呢?这是因为embstr格式是只读的,原因就在于在字符串长度发生变化时,需要重新分配内存,而此时如果是embstr格式,则需要把SDS数据部分和Object对象部分分离重新分配内存,此时实际是就变成了raw格式,因此说embstr格式是只读的。

综上所述,相信你们会有一个疑问,既然在修改时会变成raw格式,为什么还会有embstr格式?当然是因为embstr格式也有它的优点。相较于raw格式,embstr格式降低了内存的分配次数,这就使得它同样能减少内存释放的次数,这两项操作都是需要时间的,如果次数越多,显而易见会影响性能,同时由于SDS和Object对象在一块连续的内存上,能更好的利用CPU缓存的性能。

用途

String数据类型常用来缓存String+JSON格式的对象缓存、作为分布式锁的存储类型、共享session信息的存储等

List

底层数据结构
压缩列表

当元素个数少于512个,且每个元素的值都小于64字节时,会使用压缩列表的结构

双向链表

当元素个数不满足上述条件时,使用双向链表

Redis3.2之后

改用quicklist数据结构作为底层存储

用途

list结构可以用于消息队列。

通过lpush命令和rpop命令来实现消息的添加和消费,这就是保证了消息队列的保序性。

同时通过brpop命令实现了阻塞式读取消息。

生产者自行生产全局唯一id来保证消息的唯一性。

最后通过brpoplpush命令来保证消息队列的可靠性,实际就是把读取消息后,又把消息存到了另一个list中来备份。

但是它也有一个缺点,就是无法实现消费者组。他不支持多个消费者消费同一条消息,

Hash

底层数结构

压缩列表

当元素个数小于512个,单个元素值小于64字节时,使用压缩列表

哈希表

当不满足上面的条件时,就会使用哈希表

Redis7.0之后

redis7.0之后由listpack取代了压缩列表。之所以改用时压缩列表本身记录了前一个元素的长度,导致其有了连锁更新的问题,而listpack数据结构则在压缩列表的基础上做了改进,取消了记录前一个元素的长度,转而记录本元素的长度,来解决连锁更新问题。

用途

hash结构可以作为购物车等频繁更新的数据的底层数据结构

Set

无序的键值对集合

底层数据结构
整数集合

当元素个数小于512个时,使用整数集合

哈希表

当不满足上述条件时,使用哈希表

用途

Set数据结构可以用来做数据的无序去重、仅限一次的点赞、共同关注、抽奖等

Zset

有序的键值对集合,设计上比Set多了一个score属性来排序

底层数据结构
压缩列表

当元素个数小于128个且单个元素小于64字节时,使用压缩列表。Redis7.0之后废弃不用,改用listpack数据结构。

跳表

不满足上述条件时,使用跳表。

用途

Zset可以实现排行榜、电话谱的排序等操作。

Bitmap

位图,类似于一种二进制的数组。

底层是String类型。

可以用来实现签到、判断用户的登录态等功能。

Hyperloglog

统计集合中不重复的元素个数,也就是基数统计。他能用极小的内存运算大量的数据,每个hyperloglog键只有12kb,但却能计算最多2^64个基数,但是不够精确是基于概率完成的。

主要用来做百万级网页的UV计数

GEO

设计用来地图的经纬度记录。对其进行区间划分,来实现搜索附近的操作。底层的话采用了set类型,经纬度通过geohash编码转化为sorted set 的元素权重分数。主要应用于打车软件。

Stream

前面我们说过,list数据类型可以做为消息队列的数据结构,但是其不能实现消费者组,因此,redis专门设计了stream数据类型来实现消费者组。可以创建消费组,指定读取位置。

消息保序性通过XADD和XREAD命令实现。同时XREAD的block属性可以用来实现阻塞式读取。

XADD命令会自动生成全局唯一ID来保证全局唯一性。

消息的可靠性则通过stream自动使用内部队列PENDING LIST留存每个消费者拉取的数据,直到消费者使用XACK命令告诉streams消息已消费完成。同时在服务宕机时,通过XPENDING命令查看已读取但未确认消费的消息。

总结

redis凭借丰富的数据类型获得了许多人的青睐,以上就是redis的几种数据类型,感谢大家的观看。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值