一、前言Redis 是一款高性能的开源键值Key-Value型内存数据库凭借读写速度快、支持高并发、数据类型丰富、功能强大等优势被广泛应用于缓存、分布式锁、限流、消息队列、排行榜、计数器等各类业务场景。与传统关系型数据库不同Redis 并非只支持简单的字符串键值对它内置了多种基础与扩展数据类型能够适配多样化的业务存储需求。其中String、Hash、List、Set、ZSet是 Redis 最核心的五种基础数据类型也是日常开发中使用频率最高的数据结构。想要用好 Redis不仅要掌握各类数据类型的使用命令更要理解其底层存储结构、设计思想、特性与适用场景。本文将全面讲解 Redis 五大基础数据类型从核心特性、底层实现、原生命令再到 Spring Boot Spring Data Redis 代码实战由浅入深进行剖析帮助大家彻底掌握 Redis 基础核心知识。二、Redis String 字符串类型String 是 Redis 中最基础、使用最广泛的数据类型也是所有 Key 默认的存储类型。Redis 中所有的键Key本质上都是 String 类型Value 同样基于字符串实现可灵活存储文本、数字、二进制数据等内容。2.1 核心特性二进制安全String 不会对存储内容做任何解析、转义、截断处理能够完整保存普通字符串、数字、JSON 字符串、图片字节流、序列化对象、音频视频二进制数据等不存在 C 语言字符串\0截断的问题。容量限制单个 String 类型的 Value 最大可存储512MB数据足以满足绝大多数业务场景。支持数字原子操作当字符串内容为整型数字时Redis 提供自增、自减等命令所有数字操作均为单命令原子性在高并发场景下无需额外加锁天然保证线程安全。2.2 底层实现SDS 简单动态字符串Redis 的 String 类型底层并不是直接使用 C 语言原生字符串而是自研了SDSSimple Dynamic String简单动态字符串这也是 Redis 高性能、二进制安全的核心原因。2.2.1 SDS 结构体分类Redis 定义了五种 SDS 结构体sdshdr5、sdshdr8、sdshdr16、sdshdr32、sdshdr64。除sdshdr5为极简结构外其余四种结构设计一致仅len和alloc字段的位宽不同8/16/32/64 位Redis 会根据字符串长度自动选择最小结构体最大化节省内存。标准 SDSsdshdr8/16/32/64内存布局len实际数据字节长度不包含末尾\0读取长度时间复杂度为 O (1)alloc已分配的内存总大小记录 buf 数组可用空间用于内存预分配优化flags占用 1 字节低 3 位标识 SDS 类型高 5 位预留未使用buf[]字符数组存储真实数据末尾主动追加\0兼容 C 语言标准库函数。极简 SDSsdshdr5仅由flags和buf组成无len和alloc字段。flags高 5 位存储字符串长度仅用于长度小于 32的内部短字符串极致压缩内存。2.2.2 SDS 对比 C 语言原生字符串C 语言字符串存在三大缺陷也是 Redis 设计 SDS 的根本原因非二进制安全以\0作为字符串结束标记若数据中包含\0会被直接截断无法存储二进制文件获取长度效率低需要遍历整个字符数组直到\0时间复杂度 O (n)内存操作低效每次修改字符串都需要手动重新分配内存频繁分配容易产生内存碎片且无空间预分配机制。针对以上问题SDS 做了全面优化依靠len字段标记数据长度不再依赖\0实现二进制安全直接读取len获取长度时间复杂度优化为 O (1)内存预分配 惰性缩容字符串扩容时额外分配空闲空间减少频繁内存重分配缩容时不立即释放多余内存留作后续复用大幅提升性能。2.3 String 三种上层编码Redis 在RedisObject层面针对 String 做了三层编码优化区分不同场景下的内存布局int 编码触发条件Value 为纯整数。底层不创建 SDS 结构直接将数字存入 RedisObject无额外内存开销。embstr 编码触发条件字符串长度≤44 字节。使用sdshdr8RedisObject 与 SDS 合并为一块连续内存仅一次内存分配指针开销小、CPU 缓存友好。该编码为只读模式一旦执行修改操作会自动转为 raw 编码。raw 编码触发条件字符串长度 44 字节、embstr 被修改、int 转为字符串。RedisObject 与 SDS 分为两块独立内存通过指针关联支持动态扩容、长字符串存储与修改操作。2.4 常用原生命令命令作用SET key value新增 / 覆盖键值对GET key根据 Key 获取 Value键不存在返回空APPEND key value向字符串尾部追加内容键不存在则等效 SETSTRLEN key获取字符串长度键不存在返回 0MSET k1 v1 k2 v2...批量设置多个键值对MGET k1 k2...批量获取多个 Key 的值2.5 Spring Boot 实战代码在 Spring Data Redis 中通过ValueOperations操作 String 类型数据RedisTemplate 会自动管理连接池无需手动关闭连接。package com.qcby.springbootTest; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.ValueOperations; import org.springframework.test.context.junit4.SpringRunner; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; SpringBootTest RunWith(SpringRunner.class) public class StringRedisTest { Autowired private RedisTemplateString, Object redisTemplate; Test public void testBaseOperate() { // 获取String类型操作工具类 ValueOperationsString, Object valueOps redisTemplate.opsForValue(); // 基础 set / get valueOps.set(name, minxr); String name (String) valueOps.get(name); System.out.println(查询结果 name); // 字符串追加 String oldValue (String) valueOps.get(name); valueOps.set(name, oldValue jintao); System.out.println(追加后 valueOps.get(name)); // 覆盖数据 valueOps.set(name, jintao); System.out.println(覆盖后 valueOps.get(name)); // 删除Key redisTemplate.delete(name); System.out.println(删除后查询 valueOps.get(name)); // 批量存储 MapString, Object multiMap new HashMap(); multiMap.put(name, minxr); multiMap.put(jarorwar, aaa); redisTemplate.opsForValue().multiSet(multiMap); // 批量获取 ListObject mgetResult redisTemplate.opsForValue() .multiGet(Arrays.asList(name, jarorwar)); System.out.println(批量查询 mgetResult); } Test public void testKeyOperate() { // 清空当前数据库 redisTemplate.getConnectionFactory().getConnection().flushDb(); System.out.println(清空数据库成功); // 判断Key是否存在 boolean exists redisTemplate.hasKey(foo); System.out.println(foo是否存在 exists); // 存储数据 redisTemplate.opsForValue().set(key, values); exists redisTemplate.hasKey(key); System.out.println(key是否存在 exists); } Test public void testStringAll() throws InterruptedException { ValueOperationsString, Object valueOps redisTemplate.opsForValue(); try { // 基础赋值取值 valueOps.set(key, Hello World!); System.out.println(valueOps.get(key)); redisTemplate.getConnectionFactory().getConnection().flushDb(); // setIfAbsent 对应 SETNX 不存在则赋值 valueOps.set(foo, bar); Boolean setNx valueOps.setIfAbsent(foo, foo not exits); System.out.println(SETNX执行结果 setNx 当前值 valueOps.get(foo)); // 覆盖数据 valueOps.set(foo, foo update); System.out.println(覆盖后 valueOps.get(foo)); // 设置过期时间2秒 valueOps.set(foo, foo not exits, 2, java.util.concurrent.TimeUnit.SECONDS); System.out.println(设置过期后 valueOps.get(foo)); Thread.sleep(3000); System.out.println(3秒后查询 valueOps.get(foo)); // getAndSet 取值并覆盖 valueOps.set(foo, foo update); Object oldVal valueOps.getAndSet(foo, foo modify); System.out.println(原值 oldVal 新值 valueOps.get(foo)); // 批量操作 MapString, Object msetMap new HashMap(); msetMap.put(mset1, mvalue1); msetMap.put(mset2, mvalue2); redisTemplate.opsForValue().multiSet(msetMap); ListObject mgetList valueOps.multiGet(Arrays.asList(mset1, mset2)); System.out.println(批量查询 mgetList); // 批量删除 Long delCount redisTemplate.delete(Arrays.asList(foo, foo1)); System.out.println(删除个数 delCount); } catch (Exception e) { e.printStackTrace(); } } }代码说明redisTemplate.opsForValue()获取 String 类型专属操作对象ValueOperationssetIfAbsent对应 RedisSETNX命令仅 Key 不存在时赋值可用于分布式锁所有方法均封装了原生 Redis 命令连接池由框架自动管理。三、Redis Hash 哈希类型3.1 应用场景引入在业务中我们经常需要存储用户、商品、订单等结构化数据。如果使用 String 存储 JSON 字符串会存在明显缺陷修改单个字段时需要全量序列化、反序列化、网络传输资源消耗大多线程并发更新时还会出现更新丢失问题。Redis Hash 类型正是为结构化对象存储设计的数据结构它是Key-Field-Value三级映射关系一个 Redis Key 下可以维护多个 Field-Value 键值对完美适配对象存储场景。3.2 核心特性结构单 Key 对应多个 FieldField 在当前 Hash 内唯一Value 基于 SDS 实现二进制安全容量单个 Hash 最大支持2^32 - 1个字段原子性单个字段的增删改查均为原子操作天然规避并发更新问题内存优势相比 JSON 字符串无多余符号冗余内存利用率更高时间复杂度单字段操作 O (1)批量字段操作 O (N)N 为操作字段数。3.3 底层实现Hash 类型采用双结构自适应切换压缩列表ziplist默认优先使用当 Hash 字段数量 ≤512 且单个 Value 长度 ≤64 字节时生效。采用连续内存存储无指针开销内存极度紧凑。哈希表hashtable当字段数或 Value 长度超过阈值自动切换为哈希表。读写效率稳定 O (1)适合大数据量、高并发场景。3.4 常用原生命令命令作用HSET key field value设置单个字段新增返回 1更新返回 0HGET key field获取单个字段值HMSET / HMGET批量设置 / 获取字段HGETALL key获取 Hash 所有字段与值HSETNX key field value字段不存在时才赋值HDEL key field删除指定字段HLEN key获取字段总数量3.5 Spring Boot 实战代码通过HashOperations操作 Hash 类型数据Test public void testHash() { // 获取Hash操作对象 HashOperationsString, String, String hashOps redisTemplate.opsForHash(); // 批量设置字段 MapString, String pairs new HashMap(); pairs.put(name, Akshi); pairs.put(age, 2); pairs.put(sex, Female); hashOps.putAll(kid, pairs); // 获取单个字段 ListString name hashOps.multiGet(kid, Collections.singletonList(name)); System.out.println(姓名 name); // 删除字段 hashOps.delete(kid, age); System.out.println(pwd字段值 hashOps.multiGet(kid, Collections.singletonList(pwd))); // 获取字段数量 System.out.println(字段总数 hashOps.size(kid)); // 获取所有字段名、字段值 System.out.println(所有字段 hashOps.keys(kid)); System.out.println(所有值 hashOps.values(kid)); // 获取完整Hash数据 MapString, String allPairs hashOps.entries(kid); System.out.println(完整数据 allPairs); // 清空数据库 redisTemplate.getConnectionFactory().getConnection().flushDb(); // 新增Hash数据 hashOps.put(hashs, entryKey, entryValue); hashOps.put(hashs, entryKey1, entryValue1); // 判断字段是否存在 System.out.println(字段是否存在 hashOps.hasKey(hashs, entryKey)); // 字段值自增 Long incr hashOps.increment(hashs, entryKey, 123L); System.out.println(自增结果 incr); }代码说明HashOperations专门用于操作 Hash 结构泛型依次对应RedisKey、Field、ValueCollections.singletonList创建不可变单元素集合常用于单字段查询increment支持字段数字自增原子性操作。四、Redis List 列表类型4.1 核心特性Redis List 是有序、可重复的字符串序列基于双向链表语义实现元素按照插入顺序排序支持正向索引、反向索引。List 的优势集中在头尾增删元素常用来实现消息队列、栈、时间线、分页列表等场景。4.2 底层实现Redis 版本不同底层结构有差异Redis 3.2 之前双结构自适应数据量小时使用ziplist压缩列表数据量超标切换为双向链表。Redis 3.2 及以上统一使用quicklist快速列表是双向链表 压缩列表的结合体。链表的每个节点都封装一个 ziplist兼顾了链表头尾操作高效、ziplist 内存紧凑两大优点是目前最优实现方案。4.3 常用原生命令表格命令作用LPUSH / RPUSH头部 / 尾部插入元素LPOP / RPOP头部 / 尾部弹出元素LLEN key获取列表长度LRANGE key start stop区间查询元素0 -1代表查询全部LREM key count value删除指定个数的指定元素LSET key index value修改指定索引元素RPOPLPUSH src dst元素从源列表尾部转移到目标列表头部4.4 Spring Boot 实战代码通过ListOperations操作 List 类型Test public void testList() { String messagesKey messages; String listsKey lists; redisTemplate.delete(messagesKey); // 尾部插入元素 redisTemplate.opsForList().rightPush(messagesKey, Hello how are you?); redisTemplate.opsForList().rightPush(messagesKey, Fine thanks.); ListObject messages redisTemplate.opsForList().range(messagesKey, 0, -1); System.out.println(消息列表 messages); // 清空数据库 redisTemplate.getConnectionFactory().getConnection().flushDb(); // 头部插入元素 redisTemplate.opsForList().leftPush(listsKey, vector); redisTemplate.opsForList().leftPush(listsKey, ArrayList); redisTemplate.opsForList().leftPush(listsKey, LinkedList); // 获取列表长度 Long length redisTemplate.opsForList().size(listsKey); System.out.println(列表长度 length); // 区间查询 ListObject rangeList redisTemplate.opsForList().range(listsKey, 0, 3); System.out.println(0-3索引元素 rangeList); // 修改指定索引元素 redisTemplate.opsForList().set(listsKey, 0, hello list!); // 根据索引查询 Object indexVal redisTemplate.opsForList().index(listsKey, 1); System.out.println(索引1元素 indexVal); // 删除元素 Long remove redisTemplate.opsForList().remove(listsKey, 1, vector); System.out.println(删除个数 remove); // 列表裁剪 redisTemplate.opsForList().trim(listsKey, 0, 1); // 头部弹出 Object pop redisTemplate.opsForList().leftPop(listsKey); System.out.println(弹出元素 pop); ListObject finalList redisTemplate.opsForList().range(listsKey, 0, -1); System.out.println(最终列表 finalList); }五、Redis Set 集合类型5.1 核心特性Redis Set 是无序、元素唯一的字符串集合天然去重同时支持交集、并集、差集等数学集合运算。适用于点赞、收藏、好友列表、黑名单、去重统计等场景。核心特点元素无序、不可重复、所有操作原子性、支持集合运算。5.2 底层实现采用双结构自适应切换整数集合intset集合元素全为 64 位整数且元素数量 ≤512 时使用。连续内存结构二分查找内存占用极低。哈希表hashtable包含非整数元素或元素数量超标时切换。元素作为哈希表 KeyValue 为空占位保证增删查 O (1)。注意intset 转 hashtable 是单向不可逆的。5.3 常用原生命令SADD添加元素、SREM删除元素、SMEMBERS获取所有元素、SISMEMBER判断元素是否存在、SINTER/SUNION/SDIFF集合交并差运算。六、Redis ZSet 有序集合类型6.1 核心特性ZSetSorted Set有序集合结合了Set 唯一性和排序能力。每个成员member关联一个浮点型分值score根据 score 自动排序是 Redis 中功能强大的排序结构常用于排行榜、延时队列、带权重的排序场景。排序规则优先按 score 升序排列score 相同时按 member 字典序排序。 时间复杂度核心操作 O (logN)范围查询 O (logN K)。6.2 常用原生命令ZADD添加元素、ZSCORE查询分值、ZRANGE/ZREVRANGE升序 / 降序查询、ZINCRBY分值自增、ZRANK/ZREVRANK查询排名。6.3 Spring Boot 实战代码Test public void sortedSet() { String hackersKey hackers; String zsetKey zset; // 添加有序集合元素 redisTemplate.opsForZSet().add(hackersKey, Alan Kay, 1940); redisTemplate.opsForZSet().add(hackersKey, Richard Stallman, 1953); redisTemplate.opsForZSet().add(hackersKey, Alan Turing, 1912); // 升序查询 SetObject ascSet redisTemplate.opsForZSet().range(hackersKey, 0, -1); System.out.println(升序排行 ascSet); // 降序查询 SetObject descSet redisTemplate.opsForZSet().reverseRange(hackersKey, 0, -1); System.out.println(降序排行 descSet); // 清空数据库 redisTemplate.getConnectionFactory().getConnection().flushDb(); // 新增元素 redisTemplate.opsForZSet().add(zsetKey, hello, 10.1); redisTemplate.opsForZSet().add(zsetKey, zset, 9.0); // 元素个数 Long count redisTemplate.opsForZSet().size(zsetKey); System.out.println(元素总数 count); // 查询分值 Double score redisTemplate.opsForZSet().score(zsetKey, zset); System.out.println(zset分值 score); }七、Redis 通用 Key 操作命令除五大数据类型专属命令外Redis 所有 Key 都支持通用操作日常使用频率极高EXPIRE key seconds设置 Key 过期时间秒TTL key查询剩余过期时间PERSIST key移除过期时间转为永久 KeyDEL key删除 KeyEXISTS key判断 Key 是否存在TYPE key查看 Key 对应的数据类型KEYS pattern通配符查询 Key生产环境慎用。通用操作实战Test public void testKeyCommon() throws InterruptedException { SetString allKeys redisTemplate.keys(*); System.out.println(所有Key allKeys); // 设置过期时间 redisTemplate.opsForValue().set(timekey, min, 10, TimeUnit.SECONDS); Long ttl redisTemplate.getExpire(timekey); System.out.println(剩余过期时间 ttl); Thread.sleep(5000); System.out.println(休眠后过期时间 redisTemplate.getExpire(timekey)); // 重命名Key if (redisTemplate.hasKey(timekey)) { redisTemplate.rename(timekey, time); } System.out.println(原Key值 redisTemplate.opsForValue().get(timekey)); System.out.println(新Key值 redisTemplate.opsForValue().get(time)); }八、五大基础数据类型总结与场景选型String最简单通用缓存普通文本、数字、计数器、简单对象Hash存储结构化对象用户、商品频繁修改单个字段的场景List有序可重复消息队列、时间线、分页、栈结构Set无序唯一去重、点赞、好友、集合运算ZSet有序唯一各类排行榜、权重排序、延时队列。五大类型底层均基于 ziplist、hashtable、quicklist、intset、SDS 等基础结构组合实现Redis 根据数据特征自动切换存储结构在内存占用和运行性能之间做到极致平衡。九、结尾Redis 五大基础数据类型是学习和使用 Redis 的基石不仅要熟练掌握命令与代码调用更要理解底层设计原理。在实际开发中根据业务场景合理选择数据类型能够大幅提升系统性能、简化代码逻辑。本文从原理、命令、实战三个维度完整讲解了五大类型可作为日常开发、面试复习的参考资料。
Redis 五大基础数据类型详解:底层原理、常用命令与 Spring Boot 实战
一、前言Redis 是一款高性能的开源键值Key-Value型内存数据库凭借读写速度快、支持高并发、数据类型丰富、功能强大等优势被广泛应用于缓存、分布式锁、限流、消息队列、排行榜、计数器等各类业务场景。与传统关系型数据库不同Redis 并非只支持简单的字符串键值对它内置了多种基础与扩展数据类型能够适配多样化的业务存储需求。其中String、Hash、List、Set、ZSet是 Redis 最核心的五种基础数据类型也是日常开发中使用频率最高的数据结构。想要用好 Redis不仅要掌握各类数据类型的使用命令更要理解其底层存储结构、设计思想、特性与适用场景。本文将全面讲解 Redis 五大基础数据类型从核心特性、底层实现、原生命令再到 Spring Boot Spring Data Redis 代码实战由浅入深进行剖析帮助大家彻底掌握 Redis 基础核心知识。二、Redis String 字符串类型String 是 Redis 中最基础、使用最广泛的数据类型也是所有 Key 默认的存储类型。Redis 中所有的键Key本质上都是 String 类型Value 同样基于字符串实现可灵活存储文本、数字、二进制数据等内容。2.1 核心特性二进制安全String 不会对存储内容做任何解析、转义、截断处理能够完整保存普通字符串、数字、JSON 字符串、图片字节流、序列化对象、音频视频二进制数据等不存在 C 语言字符串\0截断的问题。容量限制单个 String 类型的 Value 最大可存储512MB数据足以满足绝大多数业务场景。支持数字原子操作当字符串内容为整型数字时Redis 提供自增、自减等命令所有数字操作均为单命令原子性在高并发场景下无需额外加锁天然保证线程安全。2.2 底层实现SDS 简单动态字符串Redis 的 String 类型底层并不是直接使用 C 语言原生字符串而是自研了SDSSimple Dynamic String简单动态字符串这也是 Redis 高性能、二进制安全的核心原因。2.2.1 SDS 结构体分类Redis 定义了五种 SDS 结构体sdshdr5、sdshdr8、sdshdr16、sdshdr32、sdshdr64。除sdshdr5为极简结构外其余四种结构设计一致仅len和alloc字段的位宽不同8/16/32/64 位Redis 会根据字符串长度自动选择最小结构体最大化节省内存。标准 SDSsdshdr8/16/32/64内存布局len实际数据字节长度不包含末尾\0读取长度时间复杂度为 O (1)alloc已分配的内存总大小记录 buf 数组可用空间用于内存预分配优化flags占用 1 字节低 3 位标识 SDS 类型高 5 位预留未使用buf[]字符数组存储真实数据末尾主动追加\0兼容 C 语言标准库函数。极简 SDSsdshdr5仅由flags和buf组成无len和alloc字段。flags高 5 位存储字符串长度仅用于长度小于 32的内部短字符串极致压缩内存。2.2.2 SDS 对比 C 语言原生字符串C 语言字符串存在三大缺陷也是 Redis 设计 SDS 的根本原因非二进制安全以\0作为字符串结束标记若数据中包含\0会被直接截断无法存储二进制文件获取长度效率低需要遍历整个字符数组直到\0时间复杂度 O (n)内存操作低效每次修改字符串都需要手动重新分配内存频繁分配容易产生内存碎片且无空间预分配机制。针对以上问题SDS 做了全面优化依靠len字段标记数据长度不再依赖\0实现二进制安全直接读取len获取长度时间复杂度优化为 O (1)内存预分配 惰性缩容字符串扩容时额外分配空闲空间减少频繁内存重分配缩容时不立即释放多余内存留作后续复用大幅提升性能。2.3 String 三种上层编码Redis 在RedisObject层面针对 String 做了三层编码优化区分不同场景下的内存布局int 编码触发条件Value 为纯整数。底层不创建 SDS 结构直接将数字存入 RedisObject无额外内存开销。embstr 编码触发条件字符串长度≤44 字节。使用sdshdr8RedisObject 与 SDS 合并为一块连续内存仅一次内存分配指针开销小、CPU 缓存友好。该编码为只读模式一旦执行修改操作会自动转为 raw 编码。raw 编码触发条件字符串长度 44 字节、embstr 被修改、int 转为字符串。RedisObject 与 SDS 分为两块独立内存通过指针关联支持动态扩容、长字符串存储与修改操作。2.4 常用原生命令命令作用SET key value新增 / 覆盖键值对GET key根据 Key 获取 Value键不存在返回空APPEND key value向字符串尾部追加内容键不存在则等效 SETSTRLEN key获取字符串长度键不存在返回 0MSET k1 v1 k2 v2...批量设置多个键值对MGET k1 k2...批量获取多个 Key 的值2.5 Spring Boot 实战代码在 Spring Data Redis 中通过ValueOperations操作 String 类型数据RedisTemplate 会自动管理连接池无需手动关闭连接。package com.qcby.springbootTest; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.ValueOperations; import org.springframework.test.context.junit4.SpringRunner; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; SpringBootTest RunWith(SpringRunner.class) public class StringRedisTest { Autowired private RedisTemplateString, Object redisTemplate; Test public void testBaseOperate() { // 获取String类型操作工具类 ValueOperationsString, Object valueOps redisTemplate.opsForValue(); // 基础 set / get valueOps.set(name, minxr); String name (String) valueOps.get(name); System.out.println(查询结果 name); // 字符串追加 String oldValue (String) valueOps.get(name); valueOps.set(name, oldValue jintao); System.out.println(追加后 valueOps.get(name)); // 覆盖数据 valueOps.set(name, jintao); System.out.println(覆盖后 valueOps.get(name)); // 删除Key redisTemplate.delete(name); System.out.println(删除后查询 valueOps.get(name)); // 批量存储 MapString, Object multiMap new HashMap(); multiMap.put(name, minxr); multiMap.put(jarorwar, aaa); redisTemplate.opsForValue().multiSet(multiMap); // 批量获取 ListObject mgetResult redisTemplate.opsForValue() .multiGet(Arrays.asList(name, jarorwar)); System.out.println(批量查询 mgetResult); } Test public void testKeyOperate() { // 清空当前数据库 redisTemplate.getConnectionFactory().getConnection().flushDb(); System.out.println(清空数据库成功); // 判断Key是否存在 boolean exists redisTemplate.hasKey(foo); System.out.println(foo是否存在 exists); // 存储数据 redisTemplate.opsForValue().set(key, values); exists redisTemplate.hasKey(key); System.out.println(key是否存在 exists); } Test public void testStringAll() throws InterruptedException { ValueOperationsString, Object valueOps redisTemplate.opsForValue(); try { // 基础赋值取值 valueOps.set(key, Hello World!); System.out.println(valueOps.get(key)); redisTemplate.getConnectionFactory().getConnection().flushDb(); // setIfAbsent 对应 SETNX 不存在则赋值 valueOps.set(foo, bar); Boolean setNx valueOps.setIfAbsent(foo, foo not exits); System.out.println(SETNX执行结果 setNx 当前值 valueOps.get(foo)); // 覆盖数据 valueOps.set(foo, foo update); System.out.println(覆盖后 valueOps.get(foo)); // 设置过期时间2秒 valueOps.set(foo, foo not exits, 2, java.util.concurrent.TimeUnit.SECONDS); System.out.println(设置过期后 valueOps.get(foo)); Thread.sleep(3000); System.out.println(3秒后查询 valueOps.get(foo)); // getAndSet 取值并覆盖 valueOps.set(foo, foo update); Object oldVal valueOps.getAndSet(foo, foo modify); System.out.println(原值 oldVal 新值 valueOps.get(foo)); // 批量操作 MapString, Object msetMap new HashMap(); msetMap.put(mset1, mvalue1); msetMap.put(mset2, mvalue2); redisTemplate.opsForValue().multiSet(msetMap); ListObject mgetList valueOps.multiGet(Arrays.asList(mset1, mset2)); System.out.println(批量查询 mgetList); // 批量删除 Long delCount redisTemplate.delete(Arrays.asList(foo, foo1)); System.out.println(删除个数 delCount); } catch (Exception e) { e.printStackTrace(); } } }代码说明redisTemplate.opsForValue()获取 String 类型专属操作对象ValueOperationssetIfAbsent对应 RedisSETNX命令仅 Key 不存在时赋值可用于分布式锁所有方法均封装了原生 Redis 命令连接池由框架自动管理。三、Redis Hash 哈希类型3.1 应用场景引入在业务中我们经常需要存储用户、商品、订单等结构化数据。如果使用 String 存储 JSON 字符串会存在明显缺陷修改单个字段时需要全量序列化、反序列化、网络传输资源消耗大多线程并发更新时还会出现更新丢失问题。Redis Hash 类型正是为结构化对象存储设计的数据结构它是Key-Field-Value三级映射关系一个 Redis Key 下可以维护多个 Field-Value 键值对完美适配对象存储场景。3.2 核心特性结构单 Key 对应多个 FieldField 在当前 Hash 内唯一Value 基于 SDS 实现二进制安全容量单个 Hash 最大支持2^32 - 1个字段原子性单个字段的增删改查均为原子操作天然规避并发更新问题内存优势相比 JSON 字符串无多余符号冗余内存利用率更高时间复杂度单字段操作 O (1)批量字段操作 O (N)N 为操作字段数。3.3 底层实现Hash 类型采用双结构自适应切换压缩列表ziplist默认优先使用当 Hash 字段数量 ≤512 且单个 Value 长度 ≤64 字节时生效。采用连续内存存储无指针开销内存极度紧凑。哈希表hashtable当字段数或 Value 长度超过阈值自动切换为哈希表。读写效率稳定 O (1)适合大数据量、高并发场景。3.4 常用原生命令命令作用HSET key field value设置单个字段新增返回 1更新返回 0HGET key field获取单个字段值HMSET / HMGET批量设置 / 获取字段HGETALL key获取 Hash 所有字段与值HSETNX key field value字段不存在时才赋值HDEL key field删除指定字段HLEN key获取字段总数量3.5 Spring Boot 实战代码通过HashOperations操作 Hash 类型数据Test public void testHash() { // 获取Hash操作对象 HashOperationsString, String, String hashOps redisTemplate.opsForHash(); // 批量设置字段 MapString, String pairs new HashMap(); pairs.put(name, Akshi); pairs.put(age, 2); pairs.put(sex, Female); hashOps.putAll(kid, pairs); // 获取单个字段 ListString name hashOps.multiGet(kid, Collections.singletonList(name)); System.out.println(姓名 name); // 删除字段 hashOps.delete(kid, age); System.out.println(pwd字段值 hashOps.multiGet(kid, Collections.singletonList(pwd))); // 获取字段数量 System.out.println(字段总数 hashOps.size(kid)); // 获取所有字段名、字段值 System.out.println(所有字段 hashOps.keys(kid)); System.out.println(所有值 hashOps.values(kid)); // 获取完整Hash数据 MapString, String allPairs hashOps.entries(kid); System.out.println(完整数据 allPairs); // 清空数据库 redisTemplate.getConnectionFactory().getConnection().flushDb(); // 新增Hash数据 hashOps.put(hashs, entryKey, entryValue); hashOps.put(hashs, entryKey1, entryValue1); // 判断字段是否存在 System.out.println(字段是否存在 hashOps.hasKey(hashs, entryKey)); // 字段值自增 Long incr hashOps.increment(hashs, entryKey, 123L); System.out.println(自增结果 incr); }代码说明HashOperations专门用于操作 Hash 结构泛型依次对应RedisKey、Field、ValueCollections.singletonList创建不可变单元素集合常用于单字段查询increment支持字段数字自增原子性操作。四、Redis List 列表类型4.1 核心特性Redis List 是有序、可重复的字符串序列基于双向链表语义实现元素按照插入顺序排序支持正向索引、反向索引。List 的优势集中在头尾增删元素常用来实现消息队列、栈、时间线、分页列表等场景。4.2 底层实现Redis 版本不同底层结构有差异Redis 3.2 之前双结构自适应数据量小时使用ziplist压缩列表数据量超标切换为双向链表。Redis 3.2 及以上统一使用quicklist快速列表是双向链表 压缩列表的结合体。链表的每个节点都封装一个 ziplist兼顾了链表头尾操作高效、ziplist 内存紧凑两大优点是目前最优实现方案。4.3 常用原生命令表格命令作用LPUSH / RPUSH头部 / 尾部插入元素LPOP / RPOP头部 / 尾部弹出元素LLEN key获取列表长度LRANGE key start stop区间查询元素0 -1代表查询全部LREM key count value删除指定个数的指定元素LSET key index value修改指定索引元素RPOPLPUSH src dst元素从源列表尾部转移到目标列表头部4.4 Spring Boot 实战代码通过ListOperations操作 List 类型Test public void testList() { String messagesKey messages; String listsKey lists; redisTemplate.delete(messagesKey); // 尾部插入元素 redisTemplate.opsForList().rightPush(messagesKey, Hello how are you?); redisTemplate.opsForList().rightPush(messagesKey, Fine thanks.); ListObject messages redisTemplate.opsForList().range(messagesKey, 0, -1); System.out.println(消息列表 messages); // 清空数据库 redisTemplate.getConnectionFactory().getConnection().flushDb(); // 头部插入元素 redisTemplate.opsForList().leftPush(listsKey, vector); redisTemplate.opsForList().leftPush(listsKey, ArrayList); redisTemplate.opsForList().leftPush(listsKey, LinkedList); // 获取列表长度 Long length redisTemplate.opsForList().size(listsKey); System.out.println(列表长度 length); // 区间查询 ListObject rangeList redisTemplate.opsForList().range(listsKey, 0, 3); System.out.println(0-3索引元素 rangeList); // 修改指定索引元素 redisTemplate.opsForList().set(listsKey, 0, hello list!); // 根据索引查询 Object indexVal redisTemplate.opsForList().index(listsKey, 1); System.out.println(索引1元素 indexVal); // 删除元素 Long remove redisTemplate.opsForList().remove(listsKey, 1, vector); System.out.println(删除个数 remove); // 列表裁剪 redisTemplate.opsForList().trim(listsKey, 0, 1); // 头部弹出 Object pop redisTemplate.opsForList().leftPop(listsKey); System.out.println(弹出元素 pop); ListObject finalList redisTemplate.opsForList().range(listsKey, 0, -1); System.out.println(最终列表 finalList); }五、Redis Set 集合类型5.1 核心特性Redis Set 是无序、元素唯一的字符串集合天然去重同时支持交集、并集、差集等数学集合运算。适用于点赞、收藏、好友列表、黑名单、去重统计等场景。核心特点元素无序、不可重复、所有操作原子性、支持集合运算。5.2 底层实现采用双结构自适应切换整数集合intset集合元素全为 64 位整数且元素数量 ≤512 时使用。连续内存结构二分查找内存占用极低。哈希表hashtable包含非整数元素或元素数量超标时切换。元素作为哈希表 KeyValue 为空占位保证增删查 O (1)。注意intset 转 hashtable 是单向不可逆的。5.3 常用原生命令SADD添加元素、SREM删除元素、SMEMBERS获取所有元素、SISMEMBER判断元素是否存在、SINTER/SUNION/SDIFF集合交并差运算。六、Redis ZSet 有序集合类型6.1 核心特性ZSetSorted Set有序集合结合了Set 唯一性和排序能力。每个成员member关联一个浮点型分值score根据 score 自动排序是 Redis 中功能强大的排序结构常用于排行榜、延时队列、带权重的排序场景。排序规则优先按 score 升序排列score 相同时按 member 字典序排序。 时间复杂度核心操作 O (logN)范围查询 O (logN K)。6.2 常用原生命令ZADD添加元素、ZSCORE查询分值、ZRANGE/ZREVRANGE升序 / 降序查询、ZINCRBY分值自增、ZRANK/ZREVRANK查询排名。6.3 Spring Boot 实战代码Test public void sortedSet() { String hackersKey hackers; String zsetKey zset; // 添加有序集合元素 redisTemplate.opsForZSet().add(hackersKey, Alan Kay, 1940); redisTemplate.opsForZSet().add(hackersKey, Richard Stallman, 1953); redisTemplate.opsForZSet().add(hackersKey, Alan Turing, 1912); // 升序查询 SetObject ascSet redisTemplate.opsForZSet().range(hackersKey, 0, -1); System.out.println(升序排行 ascSet); // 降序查询 SetObject descSet redisTemplate.opsForZSet().reverseRange(hackersKey, 0, -1); System.out.println(降序排行 descSet); // 清空数据库 redisTemplate.getConnectionFactory().getConnection().flushDb(); // 新增元素 redisTemplate.opsForZSet().add(zsetKey, hello, 10.1); redisTemplate.opsForZSet().add(zsetKey, zset, 9.0); // 元素个数 Long count redisTemplate.opsForZSet().size(zsetKey); System.out.println(元素总数 count); // 查询分值 Double score redisTemplate.opsForZSet().score(zsetKey, zset); System.out.println(zset分值 score); }七、Redis 通用 Key 操作命令除五大数据类型专属命令外Redis 所有 Key 都支持通用操作日常使用频率极高EXPIRE key seconds设置 Key 过期时间秒TTL key查询剩余过期时间PERSIST key移除过期时间转为永久 KeyDEL key删除 KeyEXISTS key判断 Key 是否存在TYPE key查看 Key 对应的数据类型KEYS pattern通配符查询 Key生产环境慎用。通用操作实战Test public void testKeyCommon() throws InterruptedException { SetString allKeys redisTemplate.keys(*); System.out.println(所有Key allKeys); // 设置过期时间 redisTemplate.opsForValue().set(timekey, min, 10, TimeUnit.SECONDS); Long ttl redisTemplate.getExpire(timekey); System.out.println(剩余过期时间 ttl); Thread.sleep(5000); System.out.println(休眠后过期时间 redisTemplate.getExpire(timekey)); // 重命名Key if (redisTemplate.hasKey(timekey)) { redisTemplate.rename(timekey, time); } System.out.println(原Key值 redisTemplate.opsForValue().get(timekey)); System.out.println(新Key值 redisTemplate.opsForValue().get(time)); }八、五大基础数据类型总结与场景选型String最简单通用缓存普通文本、数字、计数器、简单对象Hash存储结构化对象用户、商品频繁修改单个字段的场景List有序可重复消息队列、时间线、分页、栈结构Set无序唯一去重、点赞、好友、集合运算ZSet有序唯一各类排行榜、权重排序、延时队列。五大类型底层均基于 ziplist、hashtable、quicklist、intset、SDS 等基础结构组合实现Redis 根据数据特征自动切换存储结构在内存占用和运行性能之间做到极致平衡。九、结尾Redis 五大基础数据类型是学习和使用 Redis 的基石不仅要熟练掌握命令与代码调用更要理解底层设计原理。在实际开发中根据业务场景合理选择数据类型能够大幅提升系统性能、简化代码逻辑。本文从原理、命令、实战三个维度完整讲解了五大类型可作为日常开发、面试复习的参考资料。