随笔录-- Redis 5 种基本数据类型

5 种基本数据类型概览

1)String 字符串

2)List 列表

3)Set 集合

4)Hash 散列

5)Zset 有序集合

String 字符串

适用场景:缓存、计数器、分布式锁,图片等等。

底层原理:使用 SDS (简单动态字符串)。对比 C 语言的原生字符串,Redis 可以安全保存二进制数据(比如音频、图片、视频),并且可以 O(1) 获取字符串长度。可以动态扩容,动态增加内存,避免静态数组大小限制。杜绝缓冲区溢出问题,SDS 会检查内存是否足够。减少修改字符串的内存重分配,惰性空间释放+空间预分配策略。

Redis 3.2 以前

struct sdshdr {
    // 已经适用的长度
    unsigned int len;
    // 剩余长度
    unsigned int free;
    char buf[];
};

Redis 3.2 以后(为了避免 int 浪费空间)

/* Note: sdshdr5 is never used, we just access the flags byte directly.
 * However is here to document the layout of type 5 SDS strings. */
struct __attribute__ ((__packed__)) sdshdr5 {
    unsigned char flags; /* 3 lsb of type, and 5 msb of string length */
    char buf[];
};
struct __attribute__ ((__packed__)) sdshdr8 {
    uint8_t len; /* used */
    uint8_t alloc; /* excluding the header and null terminator */
    unsigned char flags; /* 3 lsb of type, 5 unused bits */
    char buf[];
};
struct __attribute__ ((__packed__)) sdshdr16 {
    uint16_t len; /* used */
    uint16_t alloc; /* excluding the header and null terminator */
    unsigned char flags; /* 3 lsb of type, 5 unused bits */
    char buf[];
};
struct __attribute__ ((__packed__)) sdshdr32 {
    uint32_t len; /* used */
    uint32_t alloc; /* excluding the header and null terminator */
    unsigned char flags; /* 3 lsb of type, 5 unused bits */
    char buf[];
};
struct __attribute__ ((__packed__)) sdshdr64 {
    uint64_t len; /* used */
    uint64_t alloc; /* excluding the header and null terminator */
    unsigned char flags; /* 3 lsb of type, 5 unused bits */
    char buf[];
};

List 列表

适用场景:队列、栈、消息队列。

举个例子,实现用户最近浏览记录等功能,可以使用 List 来存储用户的浏览记录,并通过 lpush/ltrim 操作来实现最近浏览记录的管理。

Redis 的 List 采用双向链表支持反向查找和遍历。

Redis 3.2 以前 List 底层采用 LinkedList(双向链表)和 ZipList(压缩列表),Redis 3.2 后引入了 LinkedList 和 ZipList 的结合 QuickList。

Set 集合

适用场景:求交集,并集,适用与好友列表、投票、社交网络、网页 UV(单个IP 访问量,数据量大用 hyperLogLog)、抽奖系统、随机点名等等。

Set 特点无序,不重复。

举个例子,在社交网络平台中,用户可以添加好友、删除好友,查看好友列表等操作。这种场景下,可以使用 Redis 的 Set 集合来存储用户的好友列表。通过使用 Redis 的 Set 集合来存储用户的好友关系,可以实现快速的添加、删除好友操作,并且支持高效的好友列表查询和好友关系分析。同时,Redis 的 Set 集合还支持去重功能,保证每个用户的好友列表中不会出现重复的好友。

Set 底层实现是由哈希表或者整数集合实现的。

1)如果集合的元素都是整数,并且元素个数小于 512 (默认值,可以自定义设置),Redis 会使用**整数集合(intSet)**作为 Set 类型的底层数据结构,主要目的为了减少内存空间消耗。

2)如果集合元素不满足上述条件,Redis 使用哈希表作为 Set 类型的底层数据结构。

注意事项:大数据量下作交集、差集、并集会导致 Redis 实例阻塞,防范大  Key 问题。

如果是集群模式,建议防止主库在大数据库执行大 Key 被阻塞,选择一个从库完成聚合统计,或者把数据返回客户端,由客户端来完成聚合。

Hash 哈希

哈希由键值对组成,支持添加、删除、查找、求交集、求并集等操作。

适用场景:存储对象的多个属性信息,存储用户信息,购物车等场景。

举个例子,假设我们需要存储每个用户的姓名、年龄和邮箱地址,可以使用 Hash 数据结构来存储这些信息。在 Redis 中,可以使用一个 Hash 对象来表示每个用户的信息,其中 Hash 的键是用户的唯一标识,如用户ID,键值对则存储用户的各个字段信息。

例如

用户ID为 1 的用户信息:姓名:Alice 年龄:25 邮箱地址:alice@example.com

HSET user:1 name Alice
HSET user:1 age 25
HSET user:1 email alice@example.com

Hash 底层实现由压缩列表(ZipList 或者哈希表 Dict)实现。

当哈希类型元素小于 512 个,并且所有元素的值大小(小于64个字节),Redis 使用压缩列表作为底层数据结构。

如果不满足上述条件,采用哈希表作为底层数据结构。

Zset 有序集合

Zset 有序集合相比于 Set 多了一个排序属性 Score 分值,对于有序集合 Zset 来说,每个元素有两个值组成,一个是元素值,一个是排序值(分值)。

使用场景

1)排行榜:可以将用户的分数作为 Zset 中的分数,用户的 ID 作为成员,这样可以根据用户的分数来对用户进行排名。

2)带权重的任务调度:可以将任务的执行时间作为 Zset 中的分数,任务的 ID 作为成员,这样可以按照任务的执行时间对任务进行排序并调度执行。

3)范围查询:可以根据分数的范围来获取一定范围内的成员,如获取分数在某个区间的用户或任务。

举个例子:假设有一个学生社团组织,需要记录学生参加社团活动的积分,并根据积分对学生进行排名。可以使用 Zset 数据结构来存储学生的积分信息,学生的学号作为成员,积分作为分数。

ZADD studentscore 80 1001
ZADD studentscore 75 1002
ZADD studentscore 90 1003

获取学生积分排名

ZREVRANGE studentscore 0 -1 WITHSCORES

Zset 类型底层实现由压缩列表(ZipList)或者跳表(SkipList)

如果有序集合的元素小于 128 个,并且每个元素的值小于 64 字节,采用压缩列表作为 Zset 类型的底层数据结构。

如果不满足上述条件,采用跳表(加快查询效率)作为 Zset 类型的底层数据结构。

总结

1)String(字符串):最简单的数据类型,常用于存储文本、数字等简单数据,适用于缓存、计数器、状态标记等场景。

2)List(列表):有序的字符串元素集合,支持头部和尾部的插入、删除操作,适用于消息队列、最新消息列表等场景。

3)Set(集合):不重复的字符串元素集合,支持交集、并集、差集等操作,适用于去重、共同好友、排重等场景。

4)Hash(哈希):键值对集合,适用于存储对象属性、用户信息、配置信息等场景。

5)Zset(有序集合):每个元素都关联一个分数,支持按分数排序,适用于排行榜、带权重的任务调度、范围查询等场景。

 

1. 字符串 (String)

  • 概述:字符串是Redis中最简单的数据类型,可以存储文本或二进制数据,最大支持512MB。

  • 底层原理:Redis内部使用简单的字节数组来存储字符串数据。由于其简单性,字符串在Redis中的操作都非常高效。

  • 使用场景:适用于缓存数据、计数器、存储短小的文本等场景。

2. 列表 (List)

  • 概述:列表是一个有序的字符串集合,可以包含重复的元素。

  • 底层原理:Redis的列表底层使用双向链表实现,支持在两端插入和删除元素,因此在读写两端的操作效率较高。

  • 使用场景:适用于实现消息队列、发布订阅系统、实现简单的日志系统等场景。

3. 集合 (Set)

  • 概述:集合是一组唯一的字符串集合,不允许重复元素。

  • 底层原理:Redis的集合底层使用哈希表实现,因此添加、删除、查找元素的时间复杂度都是O(1)。

  • 使用场景:适用于实现好友关系、标签系统、数据去重等场景。

4. 哈希表 (Hash)

  • 概述:哈希表是一种键值对的集合,类似于Java中的Map,其中的值也是一个键值对。

  • 底层原理:Redis的哈希表底层使用哈希表实现,每个哈希表可以存储多个键值对,对于小哈希表,Redis会使用压缩列表来存储键值对。

  • 使用场景:适用于存储对象的属性、缓存对象等场景。

5. 有序集合 (Sorted Set)

  • 概述:有序集合是一种有序的字符串集合,每个元素都会关联一个分数,通过分数进行排序。

  • 底层原理:Redis的有序集合底层使用跳跃表和哈希表实现,其中跳跃表用于保持元素的有序性,哈希表用于维护元素与分数之间的映射关系。

  • 使用场景:适用于实现排行榜、范围查询等场景。

底层原理总结

  • Redis的基本数据类型都是在内存中存储的,因此具有高效的读写性能。

  • Redis通过使用不同的数据结构来实现不同的数据类型,以满足不同的需求。

使用场景总结

  • 字符串适用于存储简单的键值对数据、计数器等。

  • 列表适用于实现简单的消息队列、发布订阅系统等。

  • 集合适用于实现好友关系、数据去重等。

  • 哈希表适用于存储对象的属性、缓存对象等。

  • 有序集合适用于实现排行榜、范围查询等。

总的来说,Redis提供了丰富的数据类型和高效的底层实现,能够满足各种不同的应用场景需求。

  • 26
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值