Redis五大数据结构:从场景到实现

一、引子:为什么Redis需要五大数据结构? 很多人的疑问:Memcached只有String一种数据结构,Redis为什么需要五种? 核心答案:不同的业务场景需要不同的数据结构。 1.1 如果只有String会怎样? 假设我们要实现一个排行榜功能,只有String的话: // ❌ 方案1:用String存储整个排行榜(JSON序列化) // 问题:每次更新一个用户分数,需要序列化/反序列化整个排行榜 public void updateScore(Long userId, int score) { // 1. 读取整个排行榜(反序列化) String json = redisTemplate.opsForValue().get("rank:list"); List<User> rankList = JSON.parseArray(json, User.class); // 10000个用户 // 2. 更新一个用户的分数 for (User user : rankList) { if (user.getId().equals(userId)) { user.setScore(score); break; } } // 3. 重新排序 rankList.sort((a, b) -> b.getScore() - a.getScore()); // 4. 写入Redis(序列化) String newJson = JSON.toJSONString(rankList); redisTemplate.opsForValue().set("rank:list", newJson); } // 性能问题: // - 读取:反序列化10000个用户,耗时100ms // - 排序:O(NlogN) = 10000*log(10000) ≈ 130000次比较 // - 写入:序列化10000个用户,耗时100ms // 总耗时:200ms+(单次更新) // ✅ 方案2:使用Redis ZSet(有序集合) // 优势:Redis内部维护排序,O(logN)复杂度 public void updateScore(Long userId, int score) { redisTemplate.opsForZSet().add("rank:zset", userId.toString(), score); } // 性能提升: // - 写入:O(logN) = log(10000) ≈ 13次比较 // - 总耗时:1ms // 性能提升:200倍 核心洞察: ...

2025-11-03 · maneng

Redis五大数据结构:从场景到实现

一、引子:为什么Redis需要五大数据结构? 很多人的疑问:Memcached只有String一种数据结构,Redis为什么需要五种? 核心答案:不同的业务场景需要不同的数据结构。 1.1 如果只有String会怎样? 假设我们要实现一个排行榜功能,只有String的话: // ❌ 方案1:用String存储整个排行榜(JSON序列化) // 问题:每次更新一个用户分数,需要序列化/反序列化整个排行榜 public void updateScore(Long userId, int score) { // 1. 读取整个排行榜(反序列化) String json = redisTemplate.opsForValue().get("rank:list"); List<User> rankList = JSON.parseArray(json, User.class); // 10000个用户 // 2. 更新一个用户的分数 for (User user : rankList) { if (user.getId().equals(userId)) { user.setScore(score); break; } } // 3. 重新排序 rankList.sort((a, b) -> b.getScore() - a.getScore()); // 4. 写入Redis(序列化) String newJson = JSON.toJSONString(rankList); redisTemplate.opsForValue().set("rank:list", newJson); } // 性能问题: // - 读取:反序列化10000个用户,耗时100ms // - 排序:O(NlogN) = 10000*log(10000) ≈ 130000次比较 // - 写入:序列化10000个用户,耗时100ms // 总耗时:200ms+(单次更新) // ✅ 方案2:使用Redis ZSet(有序集合) // 优势:Redis内部维护排序,O(logN)复杂度 public void updateScore(Long userId, int score) { redisTemplate.opsForZSet().add("rank:zset", userId.toString(), score); } // 性能提升: // - 写入:O(logN) = log(10000) ≈ 13次比较 // - 总耗时:1ms // 性能提升:200倍 核心洞察: ...

2025-11-03 · maneng

List类型详解:从队列到时间线

引言 在前面我们学习了String和Hash,它们都是"单值"类型。今天我们要学习第一个"集合"类型:List。 List最大的特点是:有序、可重复、双端操作。 想象一下这些场景: 📝 微信朋友圈:按时间倒序展示,最新的在最前面 📮 消息队列:先进先出(FIFO),生产者推送,消费者弹出 📰 最新文章列表:保留最新的100篇,自动淘汰旧的 ⏱️ 操作日志:记录用户最近的操作历史 这些场景的共同特点是:需要保持顺序,支持两端操作。List正是为此而生。 一、List的本质 1.1 什么是List? List是一个双向链表(Doubly Linked List): head tail ↓ ↓ [A] ⇄ [B] ⇄ [C] ⇄ [D] ⇄ [E] ↑ ↑ 左端(head) 右端(tail) LPUSH/LPOP RPUSH/RPOP 特点: ✅ 有序:元素按插入顺序排列 ✅ 可重复:允许重复元素 ✅ 双端操作:可以从左端或右端插入/弹出 ✅ 索引访问:支持按索引读取(但不推荐频繁使用) 1.2 List vs 数组 特性 List(链表) 数组 按索引访问 O(n) O(1) 头尾插入/删除 O(1) O(n) 中间插入/删除 O(n) O(n) 内存占用 较高(指针) 较低 适用场景 队列、栈 随机访问 结论:List适合队列操作,不适合频繁随机访问。 1.3 底层实现 Redis 3.2之前: ...

2025-01-21 · maneng

如约数科科技工作室

浙ICP备2025203501号

👀 本站总访问量 ...| 👤 访客数 ...| 📅 今日访问 ...