美团面试原题:深入理解Redis五种基本数据结构及其在实际开发中的应用,助你轻松应对面试挑战

Redis的五种基本数据结构(String、List、Hash、Set、Sorted Set)在面试中是经常被询问的话题。本文将帮助你回顾这些结构,并加深对它们的理解。

此外,还有几种特殊的数据结构(HyperLogLogs、Bitmap、Geospatial、Stream)也非常重要,我们将留待下次讨论。

图片

对于Redis的详细数据结构介绍,可以参考Redis官方网站:

随着Redis新版本的发布,未来可能会有新数据结构的推出,查阅Redis官网的相关介绍是获取最新信息的最佳途径。

图片

String(字符串)

概述

String是Redis中最基本且最常用的数据结构。它是一个二进制安全的数据结构,能够存储任何数据类型,如字符串、整数、浮点数、图片(例如图片的base64编码或路径)以及序列化后的对象。

尽管Redis是用C语言编写的,但它采用了一种名为简单动态字符串(Simple Dynamic String,SDS)的字符串表示方式。与C语言的原生字符串相比,Redis的SDS不仅可以存储文本数据,还能处理二进制数据,并且获取字符串长度的复杂度为O(1)(C字符串为O(N))。此外,Redis的SDS API设计确保了安全性,避免了缓冲区溢出的问题。

常用命令

命令描述
SET key value设置指定key的值
SETNX key value仅当key不存在时设置key的值
GET key获取指定key的值
MSET key1 value1 key2 value2 …同时设置多个指定key的值
MGET key1 key2 ...获取多个指定key的值
STRLEN key返回key所储存字符串值的长度
INCR key将key中存储的数字值加一
DECR key将key中存储的数字值减一
EXISTS key检查指定key是否存在
DEL key(通用)删除指定的key
EXPIRE key seconds(通用)设置key的过期时间

更多Redis String命令和详细使用指南,请查看Redis官网

基本操作示例

> SET key value  
OK  
> GET key  
"value"  
> EXISTS key  
(integer) 1  
> STRLEN key  
(integer) 5  
> DEL key  
(integer) 1  
> GET key  
(nil)  

应用场景

存储常规数据的场合

  • 示例:缓存session、token、图片地址、序列化后的对象(相对Hash存储更节省内存)。
  • 相关命令:SETGET

计数功能

  • 示例:用户单位时间的请求数(简单限流)、页面单位时间的访问数。
  • 相关命令:SETGETINCRDECR

分布式锁

利用SETNX key value命令可以实现一个简单的分布式锁(不过存在一些缺陷,因此通常不建议这样实现)。

List(列表)

概述

Redis的List是链表数据结构的实现。虽然许多高级编程语言内置了链表的实现,如Java中的LinkedList,但C语言并没有,因此Redis实现了自己的链表结构。Redis的List采用双向链表的方式,使得反向查找和遍历更加便利,但也带来了额外的内存开销。

图片

常用命令

命令描述
RPUSH key value1 value2 ...在指定列表的尾部添加一个或多个元素
LPUSH key value1 value2 ...在指定列表的头部添加一个或多个元素
LSET key index value设置指定列表索引的位置的值
LPOP key移除并获取指定列表的第一个元素
RPOP key移除并获取指定列表的最后一个元素
LLEN key获取列表元素的数量
LRANGE key start end获取列表中指定范围的元素

更多Redis List命令及详细使用指南,请查看Redis官网

基本操作示例

通过RPUSH/LPOPLPUSH/RPOP实现队列:

> RPUSH myList value1  
(integer) 1  
> RPUSH myList value2 value3  
(integer) 3  
> LPOP myList  
"value1"  
> LRANGE myList 0 1  
1) "value2"  
2) "value3"  

应用场景

信息流展示

  • 示例:最新文章、动态更新。
  • 相关命令:LPUSHLRANGE

消息队列

尽管Redis List可用于实现消息队列,但功能较为简单且存在缺陷,不建议使用。相较之下,Redis 5.0新加入的Stream结构更适合用于这种场景。

Hash(哈希)

概述

Redis中的Hash是一个String类型的field-value(键值对)映射表,尤其适用于存储对象,在后续操作中可以直接修改对象某些字段的值。Hash类似于JDK1.8之前的HashMap,但Redis的Hash经过了多次优化,性能表现更好。

图片

常用命令

命令描述
HSET key field value设置指定哈希表中指定字段的值
HSETNX key field value仅在字段不存在时设置其值
HMSET key field1 value1 field2 value2 ...同时设置多个field-value对
HGET key field获取指定哈希表中指定字段的值
HMGET key field1 field2 ...获取指定字段的值
HGETALL key获取指定哈希表中所有键值对
HEXISTS key field检查指定字段是否存在
HDEL key field1 field2 ...删除一个或多个字段
HLEN key获取字段数量

更多Redis Hash命令和详细使用指南,请查看Redis官网

基本操作示例

> HMSET userInfoKey name "guide" description "dev" age "24"  
OK  
> HEXISTS userInfoKey name  
(integer) 1  
> HGET userInfoKey name  
"guide"  
> HGET userInfoKey age  
"24"  
> HGETALL userInfoKey  
1) "name"  
2) "guide"  
3) "description"  
4) "dev"  
5) "age"  
6) "24"  
> HSET userInfoKey name "GuideGeGe"  
> HGET userInfoKey name  
"GuideGeGe"  

应用场景

对象数据存储

  • 示例:用户信息、商品信息、文章信息、购物车信息。
  • 相关命令:HSETHMSETHGETHMGET

Set(集合)

概述

Redis中的Set是一种无序集合,集合中的元素是唯一的,类似Java中的HashSet。当需要存储列表数据且不希望有重复数据时,Set是一个理想选择。Set提供了判断元素是否存在的接口,这是List无法提供的特性。

通过Set可以轻松实现交集、并集和差集等操作。例如,可以将用户的所有关注者和粉丝存储在不同集合中,轻松获取共同关注和共同粉丝。

图片

常用命令

命令描述
SADD key member1 member2 ...向指定集合添加一个或多个元素
SMEMBERS key获取集合中的所有元素
SCARD key获取集合的元素数量
SISMEMBER key member判断元素是否在集合中
SINTER key1 key2 ...获取集合的交集
SUNION key1 key2 ...获取集合的并集
SDIFF key1 key2 ...获取集合的差集
SPOP key count随机移除并获取集合中的元素
SRANDMEMBER key count随机获取集合中指定数量的元素

更多Redis Set命令和详细使用指南,请查看Redis官网

基本操作示例

> SADD mySet value1 value2  
(integer) 2  
> SADD mySet value1  
(integer) 0  
> SMEMBERS mySet  
1) "value1"  
2) "value2"  
> SCARD mySet  
(integer) 2  
> SISMEMBER mySet value1  
(integer) 1  

应用场景

非重复数据存放

  • 示例:网站UV统计、文章点赞、动态点赞等场景。
  • 相关命令:SCARD

图片

集合之间的交集、并集和差集

  • 示例:共同好友、共同关注、好友推荐。
  • 相关命令:SINTERSUNIONSDIFF

图片

Sorted Set(有序集合)

概述

有序集合与Set类似,但增加了一个权重参数score,使得集合中的元素能够根据score进行排序,并可以通过score的范围获取元素列表。它类似于Java中的HashMapTreeSet的结合体。

图片

常用命令

命令描述
ZADD key score1 member1 score2 member2 ...向指定有序集合添加元素
ZCARD key获取有序集合的元素数量
ZSCORE key member获取指定元素的score值
ZINTERSTORE destination numkeys key1 key2 ...求交集并存储
ZUNIONSTORE destination numkeys key1 key2 ...求并集并存储
ZDIFF destination numkeys key1 key2 ...求差集并存储
ZRANGE key start end获取指定范围的元素
ZREVRANGE key start end获取指定范围的元素(逆序)

更多Redis Sorted Set命令和详细使用指南,请查看Redis官网

基本操作示例

> ZADD myZset 2.0 value1 1.0 value2  
(integer) 2  
> ZCARD myZset  
2  
> ZSCORE myZset value1  
2.0  
> ZRANGE myZset 0 1  
1) "value2"  
2) "value1"  

应用场景

根据权重排序的随机获取场合

  • 示例:排行榜功能,如直播间礼物排行榜、游戏段位排行榜等。
  • 相关命令:ZRANGEZREVRANGEZREVRANK

图片

需要存储优先级或重要程度的场景

  • 示例:优先级任务队列。
  • 相关命令:ZRANGEZREVRANGEZREVRANK

参考资料

[1] Redis Data Structures: https://redis.com/redis-enterprise/data-structures/

[2] Redis Data Types Tutorial: https://redis.io/docs/manual/data-types/data-types-tutorial/