redis中5种基本数据类型对应的底层数据结构以及使用场景

324 阅读7分钟

数据结构

数据结构总览表 image.png

image.png

 字符串(String)

  • 简单动态字符串(SDS) :这是 Redis 对字符串的底层实现,与 C 语言传统字符串不同。SDS 结构体记录了字符串的长度、分配空间等信息,具有以下优势:

    • 二进制安全:可以存储任意二进制数据,如图片、音频等,而不仅限于文本。
    • 获取长度时间复杂度为 (O(1)):C 语言字符串获取长度需遍历,而 SDS 直接读取记录的长度信息。
    • 避免缓冲区溢出:在修改字符串时,SDS 会先检查空间是否足够,不足时自动扩展。

2. 哈希(Hash)

  • 压缩列表(ziplist) :当哈希对象保存的键值对数量较少,且键和值的长度都较短时使用。它是一种紧凑的内存数据结构,将多个键值对依次存储在连续的内存块中,节省内存,但查找效率相对较低。
  • 哈希表(hashtable) :也叫字典,是 Redis 哈希类型的主要底层结构之一。当哈希对象中的键值对数量较多,或者键和值的长度较长时,Redis 会使用哈希表。它通过哈希函数将键映射到数组的某个位置,若发生哈希冲突,则使用链表将冲突的元素连接起来,查找、插入和删除操作的平均时间复杂度为 (O(1))。

3. 列表(List)

  • 压缩列表(ziplist) :当列表元素较少且元素长度较短时采用,将元素紧凑存储在连续内存中,节省内存空间。
  • 双向链表(linkedlist) :当列表元素数量较多或元素长度较长时使用。双向链表的每个节点包含指向前一个节点和后一个节点的指针,便于在列表两端进行快速的插入和删除操作,时间复杂度为 (O(1)),但随机访问效率较低。
  • 快速列表(quicklist) :Redis 3.2 版本引入,结合了压缩列表和双向链表的优点。它将双向链表按段切分,每一段使用压缩列表存储数据,既保留了双向链表的快速插入和删除特性,又通过压缩列表节省了内存。

4. 集合(Set)

  • 整数数组(intset) :当集合中的所有元素都是整数值,且元素数量较少时使用。整数集合是一个有序的、无重复元素的整数数组,会根据元素大小自动调整存储类型,以节省内存。
  • 哈希表(hashtable) :当集合中的元素包含非整数值,或者元素数量较多时使用。哈希表通过哈希函数将元素映射到数组的某个位置,能快速判断元素是否存在于集合中,插入、删除和查找操作的平均时间复杂度为 (O(1))。

5. 有序集合(Sorted Set)

  • 压缩列表(ziplist) :当有序集合的元素数量较少,且元素的成员和分值都较短时使用。在压缩列表中,元素的成员和分值依次存储,且按分值从小到大排序。
  • 跳跃表(skiplist)  和 哈希表(hashtable) :当有序集合的元素数量较多,或者元素的成员和分值较长时,Redis 同时使用这两种结构。跳跃表是一种有序的数据结构,通过在每个节点中维护多个指向其他节点的指针,在查找元素时可跳过部分节点,提高查找效率;哈希表用于快速查找元素的分值,使获取元素分值的时间复杂度为 (O(1))。

使用场景

字符串(String)

使用场景

  • 缓存:将数据库查询结果、页面片段等数据缓存为字符串,减少数据库访问压力,提高系统响应速度。例如,缓存热门文章的内容。
  • 计数器:利用字符串的原子性自增、自减操作实现计数功能,如网站的访问量统计、文章的点赞数等。
  • 分布式锁:通过设置一个特定的字符串键值对来实现分布式锁,保证在分布式环境下同一时间只有一个客户端可以执行某段代码。

常用命令

收起

plaintext

# 设置键值对
SET key value
# 获取键对应的值
GET key
# 原子性自增 1
INCR key
# 原子性自减 1
DECR key
# 原子性增加指定数值
INCRBY key increment
# 原子性减少指定数值
DECRBY key decrement

2. 哈希(Hash)

使用场景

  • 对象存储:可以将一个对象的各个属性存储为哈希表的字段和值,方便对对象的属性进行单独操作。例如,存储用户信息,每个用户的 ID 作为键,用户的姓名、年龄、邮箱等属性作为字段和值。
  • 存储配置信息:将系统的配置信息以哈希表的形式存储,便于修改和获取。

常用命令

收起

plaintext

# 设置哈希表中指定字段的值
HSET key field value
# 获取哈希表中指定字段的值
HGET key field
# 获取哈希表中所有的字段和值
HGETALL key
# 检查哈希表中是否存在指定字段
HEXISTS key field
# 删除哈希表中指定的字段
HDEL key field [field ...]

3. 列表(List)

使用场景

  • 消息队列:利用列表的 LPUSH 和 RPOP 或 RPUSH 和 LPOP 操作实现简单的消息队列,用于异步任务处理、系统间的消息传递等。
  • 最新消息列表:可以将最新的消息依次添加到列表的头部,实现类似微博、朋友圈等的最新消息展示。

常用命令

收起

plaintext

# 将一个或多个值插入到列表的头部
LPUSH key value [value ...]
# 将一个或多个值插入到列表的尾部
RPUSH key value [value ...]
# 移除并返回列表的头部元素
LPOP key
# 移除并返回列表的尾部元素
RPOP key
# 获取列表指定范围内的元素
LRANGE key start stop

4. 集合(Set)

使用场景

  • 去重:集合中的元素是唯一的,可以用于对数据进行去重处理。例如,统计网站的独立访客数。
  • 交集、并集、差集运算:可以利用集合的这些运算来实现如共同好友、推荐系统等功能。例如,计算两个用户的共同好友。
  • 随机选取元素:可以从集合中随机选取元素,用于抽奖、随机推荐等场景。
  • 微博微信关注模型

常用命令

收起

plaintext

# 向集合中添加一个或多个元素
SADD key member [member ...]
# 移除集合中一个或多个元素
SREM key member [member ...]
# 获取集合中的所有元素
SMEMBERS key
# 检查元素是否存在于集合中
SISMEMBER key member
# 计算多个集合的交集
SINTER key [key ...]
# 计算多个集合的并集
SUNION key [key ...]
# 计算多个集合的差集
SDIFF key [key ...]
# 随机获取集合中的一个元素
SRANDMEMBER key

5. 有序集合(Sorted Set)

使用场景

  • 排行榜:根据元素的分值进行排序,可以方便地实现各种排行榜功能,如游戏的玩家积分排行榜、文章的热度排行榜等。
  • 时间序列数据:可以将时间作为分值,将事件或数据作为成员,实现按时间排序的存储和查询。

常用命令

收起

plaintext

# 向有序集合中添加一个或多个元素,并指定分值
ZADD key score member [score member ...]
# 获取有序集合中指定成员的分值
ZSCORE key member
# 获取有序集合中指定范围内的元素(按分值从小到大排序)
ZRANGE key start stop [WITHSCORES]
# 获取有序集合中指定范围内的元素(按分值从大到小排序)
ZREVRANGE key start stop [WITHSCORES]
# 获取有序集合中指定分值范围内的元素数量
ZCOUNT key min max
# 移除有序集合中指定的元素
ZREM key member [member ...]