企业网站设计与推广,电商网站变化,全国企业信息公开系统,网站及备案面试原题#xff1a;你用过Redis哪些数据结构#xff1f;#xff08;网易一面 2023#xff09;(面试题来自牛客网)
参考答案 后面有 详细答案解析#xff0c;帮助更快记忆~
参考答案共652字符#xff0c;阅读约需1分8秒#xff1b;全文共8694字符#xff0c;阅读约需…面试原题你用过Redis哪些数据结构网易一面 · 2023(面试题来自牛客网)
参考答案 后面有 详细答案解析帮助更快记忆~
参考答案共652字符阅读约需1分8秒全文共8694字符阅读约需7分14秒 参考答案
Redis是一种流行的内存数据库支持多种数据结构用于不同的用途。下面我将介绍Redis的5个基础数据结构和3个特殊数据结构
基础数据结构 String字符串 这是最基本的数据结构用于存储文本或二进制数据。它可以存储任何类型的数据比如字符串、整数、浮点数等。常用于缓存、计数器等场景。 List列表 列表是一个有序的字符串集合可以在列表的头部或尾部添加、删除元素。它支持双向的插入和删除操作可以用于实现队列、栈等数据结构。 Set集合 集合是一个无序的、不重复的字符串集合。可以进行交集、并集、差集等集合操作适用于需要快速判断某个元素是否存在的场景。 Hash哈希 哈希存储了字段与值的映射关系类似于一个关联数组。适用于存储对象的属性或者键值对。 Sorted Set有序集合 有序集合是一种在集合的基础上为每个元素关联一个分数然后根据分数对元素进行排序。适用于排行榜、范围查找等场景。
特殊数据结构 HyperLogLog HyperLogLog用于近似地计算一个集合中不重复元素的数量。它的内存占用非常小适用于需要高效计数的场景比如统计网站的UVUnique Visitors。 Bitmaps 位图是一种特殊的数据结构每个位代表一个状态。它可以用于存储某种状态的标记比如用户的签到记录、在线状态等。 GeoSpatial地理空间 Redis支持对地理位置信息的存储和查询可以用来存储地理位置坐标然后进行附近位置搜索等。
在面试中对于每种数据结构你可以结合实际项目经验提供你是如何使用这些数据结构解决问题的例子以展示你的理解和实际应用能力。 答案解析
5种基础类型
很多答案给的不全的大多只有五种这五种也是我们最了解的类型。其中一些重要的特性比如SDS等我们会在其他的文章有详细的介绍。
String类型
当在Redis中提到String类型时它实际上是一种基本的数据结构用于存储文本或二进制数据。尽管名字叫做String但它不仅仅限于存储字符串还可以存储整数和浮点数等不同类型的数据。以下是一些关于Redis中String类型的重要特点和用法 存储 Redis的String类型可以存储多种数据类型包括纯文本字符串、整数、浮点数等。存储的数据可以是字节级别的二进制数据这使得它在缓存和存储各种数据格式时非常有用。 高效操作 Redis中的String类型支持O(1)时间复杂度的基本操作如获取、设置、追加、递增、递减等。这使得它在计数器、缓存、会话管理等方面非常高效。 过期时间 你可以为存储在String类型中的数据设置过期时间。这为实现短期缓存、验证码过期等场景提供了便利。 位操作 Redis的String类型支持位级别的操作包括位与、位或、位异或等这使得它在处理位图Bitmaps等场景非常有用。 实时计算 由于String类型支持递增和递减操作你可以在Redis中执行原子性的计数操作比如计数在线用户数、点赞数等。 分布式锁 你可以使用String类型来实现分布式锁利用其设置值时的原子性和过期时间特性确保在分布式环境下的互斥操作。 应用场景 String类型在许多应用场景中都有用武之地比如缓存、计数器、排行榜、临时会话存储、消息队列等。你可以根据具体需求选择合适的数据类型。
示例代码
Tips了解即可面试不会让手撸Redis相关代码的目前各家是这样。如果遇到了就当我没说
// 存储字符串
redis.set(username, john_doe);// 存储整数
redis.set(user:1:visits, 10);// 递增操作
redis.incr(user:1:visits); // 计数增加1// 设置过期时间
redis.setex(otp:123456, 300, code123); // 5分钟内有效的验证码// 获取值
String username redis.get(username);// 判断值是否存在
boolean exists redis.exists(user:1:visits);List类型
在Redis中List列表是一种有序的数据结构它允许你存储一系列的元素并且可以按照插入顺序保持有序。List的实现方式采用了双向链表这使得它在插入、删除、查找等操作上都具有良好的性能。以下是关于Redis中List类型的重要特点和用法 有序存储 List类型中的元素按照插入顺序进行存储保持元素的有序性。这使得List适用于需要保留顺序的数据集合如消息队列、操作日志等。 支持重复元素 不同于Set类型List允许存储重复的元素。这在某些场景下是非常有用的比如记录用户的历史操作。 灵活的插入和删除 List支持在头部和尾部插入、删除元素而且这些操作的时间复杂度都是O(1)。这使得List可以模拟栈和队列等数据结构。 范围操作 你可以对List执行范围操作比如获取指定范围内的元素。这对于分页、获取最新的N条数据等场景非常有用。 阻塞操作 Redis的List还支持阻塞式的弹出操作即当List为空时阻塞等待直到有元素可用。这在实现消息队列等高级场景时很有用。 应用场景 List类型广泛应用于消息队列、操作日志、发布订阅系统、任务队列等需要有序存储的场景。
示例代码
Tips了解即可面试不会让手撸Redis相关代码的目前各家是这样。如果遇到了就当我没说
// 在列表头部插入元素
redis.lpush(messages, message1);
redis.lpush(messages, message2);// 在列表尾部插入元素
redis.rpush(messages, message3);// 获取列表长度
long length redis.llen(messages);// 获取指定范围内的元素
ListString messages redis.lrange(messages, 0, -1); // 获取全部元素// 弹出并获取列表头部元素
String firstMessage redis.lpop(messages);// 阻塞式弹出元素
ListString poppedMessage redis.blpop(30, messages); // 阻塞30秒等待元素// 删除指定数量的元素
redis.ltrim(messages, 0, 1); // 保留前两个元素删除其余元素Set类型
在Redis中Set集合是一种无序的、不允许重复元素的数据结构。它提供了高效的添加、删除、判断元素是否存在等操作同时支持集合运算如并集、交集、差集等。以下是关于Redis中Set类型的重要特点和用法 无序性 Set类型的元素是无序的与插入的顺序无关。这使得Set在判断元素是否存在、去重等操作时非常高效。 不允许重复元素 Set中不会存储重复的元素确保数据的唯一性。这使得Set适用于存储标签、用户兴趣爱好等不重复数据。 快速的添加和删除 向Set中添加元素或从Set中移除元素的时间复杂度都是O(1)这使得Set在需要动态增删元素的场景中表现出色。 集合运算 Redis的Set支持集合运算包括并集、交集、差集等操作。这使得Set可以用来解决一些复杂的数据处理需求如共同好友、数据筛选等。 应用场景 Set类型广泛应用于标签系统、社交网络中的好友关系、投票系统中的投票人、防重复提交等场景。
示例代码
Tips了解即可面试不会让手撸Redis相关代码的目前各家是这样。如果遇到了就当我没说
// 添加元素
redis.sadd(tags, java);
redis.sadd(tags, redis);
redis.sadd(tags, python);// 判断元素是否存在
boolean exists redis.sismember(tags, java); // 返回true// 获取集合中的所有元素
SetString tags redis.smembers(tags);// 移除元素
redis.srem(tags, python);// 获取集合的大小
long size redis.scard(tags);// 求两个集合的交集
SetString commonTags redis.sinter(tags1, tags2);// 求两个集合的并集
SetString allTags redis.sunion(tags1, tags2);// 求两个集合的差集
SetString differentTags redis.sdiff(tags1, tags2);Hash类型
在Redis中Hash哈希是一种用于存储字段与值之间映射关系的数据结构。Hash适用于存储对象的属性以及需要存储多个键值对的场景。以下是关于Redis中Hash类型的重要特点和用法 映射关系 Hash类型允许你在一个键下存储多个字段field和对应的值value类似于关联数组或字典。这使得Hash在存储对象的属性或键值对时非常有用。 快速访问 Hash的字段名field是唯一的这使得你可以直接通过字段名来快速访问对应的值时间复杂度是O(1)。 适用于存储对象 Hash类型特别适用于存储对象的属性。例如你可以将用户信息存储在一个以用户ID为键名的Hash中然后使用字段来存储用户名、年龄、性别等信息。 批量操作 Hash支持同时设置、获取、删除多个字段这使得在一次操作中处理多个属性或键值对非常方便。 适用于缓存 在某些情况下Hash可以用作缓存数据的数据结构将缓存键名作为Hash的键将缓存内容作为字段。 应用场景 Hash类型广泛应用于存储用户信息、缓存数据、配置项、商品属性等需要存储键值对映射关系的场景。
示例代码
// 设置Hash字段值
redis.hset(user:1, username, john_doe);
redis.hset(user:1, age, 30);// 获取Hash字段值
String username redis.hget(user:1, username);// 获取所有Hash字段和值
MapString, String userFields redis.hgetAll(user:1);// 删除Hash字段
redis.hdel(user:1, age);// 批量设置Hash字段值
MapString, String userInfo new HashMap();
userInfo.put(email, johnexample.com);
userInfo.put(city, New York);
redis.hmset(user:1, userInfo);// 获取Hash字段数量
long fieldCount redis.hlen(user:1);// 获取Hash所有字段名
SetString fields redis.hkeys(user:1);// 获取Hash所有字段值
ListString values redis.hvals(user:1);ZSet类型sorted set
这里先解释一下Sorted Set排序集合为什么被称为Zset类型这个问题在github上作者进行了解释我们常规的坐标体系是XY坐标通常我们加上一个新的维度会被称为Z三个坐标形成空间坐标系。这里的排序集合比集合多一个维度这个维度也被称为Z实际上代指Sorted所以被称为Zset。
在Redis中Sorted Set有序集合是一种特殊的数据结构它允许你存储一组元素每个元素关联一个分数score并根据分数对元素进行排序。这使得Sorted Set适用于需要排序和范围查询的场景。以下是关于Redis中Sorted Set类型的重要特点和用法 排序 Sorted Set的元素根据关联的分数进行排序使得元素可以按照一定顺序存储和检索。 不允许重复元素 Sorted Set中的元素是唯一的不允许重复。但不同元素可以有相同的分数。 分数操作 你可以为Sorted Set中的元素设置分数然后对元素的分数进行递增、递减操作。这使得Sorted Set可以用于排行榜、计数器等场景。 范围查询 Sorted Set支持按照分数范围查询元素获取某个范围内的元素。这对于获取排行榜中的前N名、获取分数在某个区间的元素等非常有用。 集合运算 Sorted Set支持交集、并集、差集等集合运算使得你可以在有序集合之间进行复杂的操作。 应用场景 Sorted Set类型广泛应用于排行榜、计数器、带权重的任务队列等需要有序存储和排序的场景。
示例代码
// 添加元素到有序集合
redis.zadd(leaderboard, 100, player1);
redis.zadd(leaderboard, 200, player2);// 获取有序集合中指定范围内的元素按分数升序
SetString topPlayers redis.zrange(leaderboard, 0, 2);// 获取有序集合中指定范围内的元素按分数降序
SetString topPlayersDesc redis.zrevrange(leaderboard, 0, 2);// 获取有序集合中指定分数范围内的元素
SetString highScorers redis.zrangeByScore(leaderboard, 150, 300);// 获取有序集合中元素的分数
Double playerScore redis.zscore(leaderboard, player1);// 增加元素的分数
redis.zincrby(leaderboard, 50, player1); // player1的分数增加50// 获取有序集合中元素的排名按分数从低到高
Long playerRank redis.zrank(leaderboard, player1);// 删除有序集合中的元素
redis.zrem(leaderboard, player2);3中拓展类型
HyperLogLog
HyperLogLog是一种概率性的数据结构用于近似地计数一个集合中不同元素的数量。它的特点是速度快占用空间小12KB。但是计算存会在误差标准误差为0.81%。它在内存占用方面非常高效适用于需要大规模、高效地进行基数估计distinct count estimation的场景。以下是关于HyperLogLog的重要特点和用法 基数估计 HyperLogLog主要用于估计一个集合中不同元素的数量也被称为基数cardinality估计。它通过使用特定的算法和数据结构能够以较小的内存占用获得接近准确的估计结果。 固定内存占用 HyperLogLog使用固定大小的内存来存储数据不随集合大小线性增长。这使得它非常适合处理大规模数据集合的基数估计需求。 概率性估计 HyperLogLog提供的估计结果是概率性的即其估计值在一定置信度下是准确的。通常情况下HyperLogLog的估计误差可以控制在2%左右。 不支持元素的添加和删除 HyperLogLog不支持添加或删除元素它仅用于计数元素的数量。如果需要动态变化的计数需要结合其他数据结构来实现。 应用场景 HyperLogLog适用于需要统计独立元素数量的场景如统计网站的独立访客数UV、统计用户兴趣标签数、统计搜索词的不同个数等。
示例代码
// 添加元素到HyperLogLog
redis.pfadd(visitors, user1);
redis.pfadd(visitors, user2);// 估计基数
long estimatedCount redis.pfcount(visitors);// 合并多个HyperLogLog
redis.pfmerge(combined_visitors, visitors1, visitors2, visitors3);需要注意的是虽然HyperLogLog在估计基数方面非常高效但它不适用于需要精确计数的场景。如果你需要准确的基数计数可能需要使用其他方法如使用Set类型进行计数但这会占用更多的内存。
Bitmaps
Bitmaps位图是一种非常紧凑的数据结构用于存储二进制位的序列其中每个位都可以是0或1。在Redis中Bitmaps被用于表示一系列状态或标记如用户的在线状态、用户的签到记录等。以下是关于Redis中Bitmaps的重要特点和用法 紧凑存储 Bitmaps以非常紧凑的方式存储数据每个位占用一个比特位bit因此在存储大规模数据时非常节省内存。 快速的位操作 Bitmaps支持位级别的操作如设置位、获取位、位与、位或、位异或等操作。这使得Bitmaps在处理状态标记等操作时非常高效。 应用于标记和计数 Bitmaps常用于标记某些状态如用户的在线状态在线为1离线为0、用户的签到记录签到为1未签到为0等。同时你可以通过位操作来进行计数比如计算一段时间内的签到次数。 非常适合大规模数据 由于紧凑的存储方式Bitmaps特别适用于处理大规模数据的状态标记和计数需求。 应用场景 Bitmaps广泛应用于在线状态的跟踪、用户签到记录、活跃用户的标记、访问控制列表ACL等场景。
示例代码
// 设置位用户签到
redis.setbit(user:123:signins, 5, 1); // 用户123在第5天签到// 获取位检查用户是否签到
boolean hasSignedIn redis.getbit(user:123:signins, 5) 1; // 用户123在第5天签到// 位操作计算连续签到次数
long consecutiveSignIns redis.bitcount(user:123:signins, 0, -1); // 计算全部位中值为1的位数// 位操作计算某段时间内的签到次数
long signInsInLastWeek redis.bitcount(user:123:signins, 0, 6); // 计算前7天内签到次数GeoSpatial
在Redis中GeoSpatial地理空间数据结构用于存储地理位置信息并支持查询附近位置、计算距离等功能。GeoSpatial数据结构是通过ZSET有序集合类型来实现的其中每个元素是一个地理位置关联一个分数score作为该位置的权重。为了能高效地对经纬度进行比较Redis 采用了业界广泛使用的 GeoHash 编码方法有关GeoHash介绍可以看我之前的文章Elasticsearch储存地理位置原理—GeoHash实现介绍_es geohash_程序员麻薯的博客-CSDN博客https://blog.csdn.net/qq_20051535/article/details/119582547以下是关于Redis中GeoSpatial的重要特点和用法 地理位置存储 GeoSpatial数据结构允许你将地理位置信息经度、纬度作为元素存储在有序集合中。 距离计算 你可以使用GeoSpatial数据结构来计算两个地理位置之间的距离以及根据距离进行查询。 查询附近位置 通过指定一个中心位置和一个半径你可以查询距离该中心位置在指定半径内的地理位置。 位置范围查询 除了半径查询还可以进行矩形范围查询查找在指定矩形区域内的地理位置。 应用场景 GeoSpatial数据结构广泛应用于地理位置服务、附近商家查询、地理位置消息推送等场景。
示例代码
// 添加地理位置
redis.geoadd(locations, 13.361389, 38.115556, Palermo);
redis.geoadd(locations, 15.087269, 37.502669, Catania);// 计算两个地理位置之间的距离单位米
double distance redis.geodist(locations, Palermo, Catania, GeoUnit.METERS);// 查询附近地理位置
ListGeoRadiusResponse nearbyLocations redis.georadius(locations, 15, 37, 200, GeoUnit.KILOMETERS);// 查询矩形范围内的地理位置
ListGeoRadiusResponse locationsInRectangle redis.georadiusByBox(locations, 13, 37, 15, 39, GeoUnit.KILOMETERS);