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

Set类型应用:去重与集合运算

引言 前面我们学习了有序的List,今天要学习无序但唯一的Set。 想象一下这些场景: 🏷️ 文章标签:“Java”、“Redis”、“数据库”,每个标签只能添加一次 👥 共同好友:你和张三有哪些共同好友? 🎲 抽奖去重:从1000个用户中随机抽10个中奖者,不能重复 📊 UV统计:今天有多少独立访客? 这些场景的共同特点是:需要去重、需要集合运算。Set正是为此而生。 一、Set的本质 1.1 什么是Set? Set是一个无序的、不重复的字符串集合: Set: {element1, element2, element3, ...} 特点: - 无序:元素没有固定顺序 - 唯一:元素不会重复 - 支持集合运算:交集、并集、差集 示例: # 添加元素 127.0.0.1:6379> SADD myset "apple" "banana" "orange" (integer) 3 # 重复添加无效 127.0.0.1:6379> SADD myset "apple" (integer) 0 # 0表示未添加(已存在) # 查看所有元素(无序) 127.0.0.1:6379> SMEMBERS myset 1) "banana" 2) "orange" 3) "apple" # 顺序可能每次都不同 1.2 Set vs List 特性 Set List 有序性 无序 有序 唯一性 元素唯一 可重复 查询元素是否存在 O(1) O(n) 按索引访问 不支持 支持 集合运算 支持 不支持 适用场景 去重、标签、关系 队列、时间线 1.3 底层实现 Set有两种底层编码: ...

2025-01-21 · maneng

如约数科科技工作室

浙ICP备2025203501号

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