【Redis】关于redis的数据结构详解
🧠 Redis 数据结构详解
引言 🎯
嘿,老铁们!欢迎回到老曹的 Redis 课堂。上一节课我们聊了 Redis 是啥以及怎么把它搞到手,今天咱们深入挖掘一下它的内功心法 —— 数据结构!
💬 老曹吐槽:你以为 Redis 只是个简单的 KV 存储?Too young too simple!它可是藏着十八般武艺呢!
学习目标 🎯
- 掌握五大基本数据类型的操作
- 理解每种类型的适用场景
- 学会灵活运用这些数据结构解决问题
一、String(字符串) 🔤
这是最基础也是最常用的一种类型,用来存储文本或者二进制数据都可以。
基本操作
| 命令 | 功能 | 示例 |
|---|---|---|
SET key value | 设置键值对 | SET name "老曹" |
GET key | 获取指定键的值 | GET name → "老曹" |
INCR key | 自增1(仅限数字) | INCR age |
DECR key | 自减1(仅限数字) | DECR score |
APPEND key value | 追加内容到末尾 | APPEND msg "你好世界" |
应用场景
- 计数器:页面浏览次数统计
- 缓存:临时存放网页片段或API结果
- 分布式锁:利用
SETNX实现互斥访问
二、Hash(哈希表) 🗂️
相当于一个小型的对象映射关系,适合保存对象属性。
基本操作
| 命令 | 功能 | 示例 |
|---|---|---|
HSET key field value | 设置字段值 | HSET user:id1001 name "张三" |
HGET key field | 获取某个字段值 | HGET user:id1001 name → "张三" |
HMSET key field1 val1 [field2 val2 ...] | 批量设值 | HMSET user:id1001 name "李四" age 25 |
HGETALL key | 获取全部字段及其值 | HGETALL user:id1001 |
HDEL key field [field ...] | 删除一个或多个字段 | HDEL user:id1001 age |
应用场景
- 用户资料管理:每个用户ID对应一条记录
- 购物车信息:商品编号 => 数量 映射关系
- 配置项存储:系统参数集中存放便于修改
三、List(列表) 📋
双向链表结构,可以从两端插入/弹出元素。
基本操作
| 命令 | 功能 | 示例 |
|---|---|---|
LPUSH key value [value ...] | 左侧推入 | LPUSH tasks task1 task2 |
RPUSH key value [value ...] | 右侧推入 | RPUSH messages hello world |
LPOP key | 左侧弹出 | LPOP tasks |
RPOP key | 右侧弹出 | RPOP messages |
LRANGE key start stop | 查看范围内的元素 | LRANGE tasks 0 -1 |
应用场景
- 消息队列:生产者消费者模式经典实现
- 最新N条记录缓存:如微博动态流展示
- 任务调度系统:待处理作业排队等候执行
四、Set(无序集合) 🔘
不允许重复成员的存在,内部采用哈希表实现去重逻辑。
基本操作
| 命令 | 功能 | 示例 |
|---|---|---|
SADD key member [member ...] | 添加成员 | SADD tags python java c++ |
SMEMBERS key | 显示所有成员 | SMEMBERS tags |
SISMEMBER key member | 判断是否包含某成员 | SISMEMBER tags python |
SREM key member [member ...] | 移除成员 | SREM tags java |
SCARD key | 返回集合大小 | SCARD tags |
应用场景
- 共同好友查找:两个用户的兴趣标签交集运算
- 抽奖活动候选池构建
- 黑名单过滤机制
五、Sorted Set(有序集合) 📊
在普通 Set 的基础上增加了权重排序功能,非常适合做排行榜之类的业务。
基本操作
| 命令 | 功能 | 示例 |
|---|---|---|
ZADD key score member [score member ...] | 添加带分数的成员 | ZADD leaderboard 100 alice 200 bob |
ZRANGE key start stop [WITHSCORES] | 正向获取排名区间 | ZRANGE leaderboard 0 9 WITHSCORES |
ZREVRANGE key start stop [WITHSCORES] | 逆向获取排名区间 | ZREVRANGE leaderboard 0 9 WITHSCORES |
ZSCORE key member | 查询特定成员得分 | ZSCORE leaderboard alice |
ZREM key member [member ...] | 删除成员 | ZREM leaderboard bob |
应用场景
- 积分排行版:游戏玩家等级榜单
- 热门文章推荐:根据点赞数倒序排列
- 地理位置服务:附近的人搜索基于距离远近排序
六、综合实战演练 🏋️♂️
让我们通过一个小例子把这些知识点串联起来吧!
假设你要开发一款在线问答社区,需要用到以下几种数据结构:
- 用户基本信息 → Hash
- 用户发表的问题列表 → List
- 问题的关注者集合 → Set
- 最受欢迎问题排行榜 → Sorted Set
具体实现代码如下(伪代码形式):
# 创建用户档案 redis.hset("user:1", mapping={"username":"Alice","email":"[email protected]"})# 发布新问题 question_id = redis.incr("global:question_id") redis.lpush(f"user:{user_id}:questions", question_id) redis.hmset(f"question:{question_id}",{"title": title,"content": content,"author_id": user_id})# 关注问题 redis.sadd(f"question:{question_id}:followers", follower_id)# 投票加分 redis.zincrby("popular_questions",1, question_id)是不是感觉思路清晰多了?
七、面试题精选 ❓
又到了激动人心的答题环节啦!准备好迎接挑战了吗?
| 序号 | 问题 | 解析 |
|---|---|---|
| 1 | Redis 中 String 类型最大能存多少数据? | 默认最大 512MB |
| 2 | Hash 和 Set 在底层分别用了什么数据结构? | Hash 用的是压缩列表或哈希表;Set 通常是整数集合或哈希表 |
| 3 | List 类型支持随机访问吗? | 不支持,只能从头尾两端操作 |
| 4 | ZSet 怎么做到既能快速查找又能维持顺序? | 跳跃表+字典双重索引结构 |
| 5 | 如果要设计一个支持撤回的消息系统你会怎么做? | 利用 List 存储历史消息,每次撤回就从右边 POP 出来即可 |
八、知识点归纳总结 📚
| 数据类型 | 时间复杂度 | 主要用途 |
|---|---|---|
| String | O(1) | 缓存、计数器 |
| Hash | O(1) | 对象存储 |
| List | O(N) for range ops | 队列、栈 |
| Set | O(1) average | 去重、集合运算 |
| Sorted Set | O(log N) | 排行榜、优先级队列 |
结语 🎉
好啦朋友们,今天我们一口气啃下了 Redis 的五大数据结构这块硬骨头。希望你们不仅能记住它们各自的特点,更重要的是能在实际项目中活学活用哟~
下期预告:我们将进入更加刺激刺激的话题 —— Redis 命令行工具与键管理,敬请期待!
拜了个拜~👋