Redis数据类型、常用命令与Java客户端详解
前言
Redis 是一种基于内存的键值型 NoSQL 数据库。它把数据保存在 key-value 结构中,同时为 value 提供 String、Hash、List、Set、Sorted Set 等数据类型,因此既能保存简单字符串,也能处理对象属性、队列、集合关系和排行榜等数据。
一、认识 Redis
1.1 NoSQL 与关系型数据库的区别
关系型数据库以表为核心,字段、数据类型、表之间的关联关系通常需要提前定义;NoSQL 的数据结构更加灵活,不同产品可以采用键值、文档、图等不同模型。
| 对比项 | 关系型数据库 | NoSQL 数据库 |
|---|---|---|
| 数据结构 | 结构化表和字段 | 结构相对灵活 |
| 数据关联 | 通过外键或关联查询维护 | 通常由业务逻辑维护 |
| 查询方式 | SQL | 不同产品使用不同命令或接口 |
| 事务特性 | 强调 ACID | 更强调可用性和扩展性 |
| 存储方式 | 主要依赖磁盘 | 常把数据放在内存中 |
| 扩展方式 | 常见主从和垂直扩展 | 支持数据拆分和水平扩展 |
如果数据结构固定、关联复杂并且对一致性要求高,关系型数据库更合适。如果数据结构变化较多、访问量较大,或者需要较低的访问延迟,NoSQL 可以作为合适的补充。
1.2 Redis 的特点
- 采用 key-value 模型,value 支持多种数据结构。
- Redis 命令由单线程顺序执行,单条命令具有原子性。
- 数据主要存放在内存中,结合 IO 多路复用和高效编码,访问延迟较低。
- 支持数据持久化,能够在服务重启后恢复数据。
- 支持主从集群和分片集群,满足高可用和扩展需求。
- 提供多种语言的客户端,方便 Java、Python、Go 等语言接入。
二、通用命令与 Key 设计
Redis 命令按照数据类型分组。通用命令不依赖具体的数据类型,所有 Key 都可以使用。通过下面的命令可以查看通用命令帮助:
help @generic
2.1 常用通用命令
| 命令 | 作用 |
|---|---|
| keys pattern | 查找符合模式的 Key,例如 a* 表示以 a 开头的 Key |
| del key | 删除指定 Key |
| exists key | 判断 Key 是否存在 |
| expire key seconds | 为已经存在的 Key 设置有效期 |
| ttl key | 查看 Key 的剩余有效期 |
Key 到期后会被 Redis 自动删除。有效期常用于验证码、短期登录信息和临时缓存等数据。
通过 help [command] 可以查看单个命令的语法、说明和所属分组:
help keys
2.2 Key 的层级命名
Redis 的 Key 可以由多个有业务含义的单词组成,词条之间使用冒号分隔。常见格式如下:
项目名:业务名:类型:id
例如:
iheima:user:1 iheima:product:1
统一的 Key 结构能够区分不同业务,查询和删除数据时也更容易定位。String 还可以保存 JSON 字符串,例如:
set iheima:user:1 '{"id":1,"name":"Jack","age":21}'三、Redis 五种核心数据类型
3.1 String 类型
String 是 Redis 最简单的数据类型。它的 value 可以表示普通字符串、整数或浮点数,底层都以字节数组形式保存,只是编码方式不同。
| 命令 | 作用 |
|---|---|
| set、get | 写入或读取一个字符串 |
| mset、mget | 批量写入或读取多个字符串 |
| incr、incrby | 整数值递增 |
| incrbyfloat | 浮点数递增 |
| setnx | Key 不存在时才写入 |
| setex | 写入字符串并设置有效期 |
String 适合保存文本、计数器、数字和带有效期的临时数据。setnx 可以利用“Key 不存在才写入”的特性完成简单的占位操作。
3.2 Hash 类型
Hash 可以看成一个无序的 field-value 字典,结构类似 Java 中的 HashMap:一个 Redis Key 下可以保存多个字段。
| 命令 | 作用 |
|---|---|
| hset、hget | 写入或读取一个字段 |
| hmset、hmget | 批量写入或读取多个字段 |
| hgetall | 获取全部 field 和 value |
| hkeys | 获取全部 field |
| hincrby | 让指定字段按步长递增 |
| hsetnx | field 不存在时才写入 |
如果把整个对象保存成 JSON 字符串,修改其中一个属性时需要重新处理整个字符串;Hash 可以直接操作单个字段,因此适合保存用户、商品等具有多个属性的对象。
3.3 List 类型
List 可以看作一个双向链表,支持从左侧或右侧插入、删除元素。它具有以下特点:有序、允许重复、两端操作速度快、按下标查询效率相对一般。
| 命令 | 作用 |
|---|---|
| lpush、rpush | 从左侧或右侧插入元素 |
| lpop、rpop | 从左侧或右侧移除并返回元素 |
| lrange | 查询指定下标范围内的元素 |
| blpop、brpop | 没有元素时等待指定时间再返回 |
List 的正向索引从 0 开始,反向索引从 -1 开始。使用 lrange key 0 -1 可以读取整个列表。同一端进出时可以模拟栈,两端分别进出时可以模拟队列,使用阻塞弹出命令时可以模拟阻塞队列。
3.4 Set 类型
Set 是无序集合,元素不能重复。它适合判断成员是否存在,也适合计算多组数据之间的关系。
| 命令 | 作用 |
|---|---|
| sadd、srem | 添加或删除成员 |
| scard | 获取集合元素数量 |
| sismember | 判断成员是否存在 |
| smembers | 获取全部成员 |
| sinter、sdiff、sunion | 计算交集、差集和并集 |
Set 可以用于标签集合、共同关注、共同好友等场景。它的重点不在于顺序,而在于去重和集合运算。
3.5 Sorted Set 类型
Sorted Set 在 Set 的基础上增加了 score。每个 member 都有一个分数,Redis 会根据 score 对 member 进行排序,同时保证 member 不重复。底层结构涉及跳表和 Hash 表。
| 命令 | 作用 |
|---|---|
| zadd | 添加 member 和 score,已存在时更新 score |
| zrem、zscore | 删除 member 或获取 score |
| zrank、zcard | 获取排名或元素数量 |
| zcount、zincrby | 按分数统计或调整分数 |
| zrange、zrangebyscore | 按排名或分数范围查询 |
| zdiff、zinter、zunion | 计算集合差集、交集和并集 |
Sorted Set 的排名从 0 开始,默认按 score 升序排列。需要降序查询时,可以使用 rev,例如 zrevrank。Sorted Set 适合实现排行榜、热度排序和按分数范围查询。
四、Redis 的 Java 客户端
Java 中常见的 Redis 客户端有 Jedis、Lettuce 和 Redisson。
| 客户端 | 特点 |
|---|---|
| Jedis | API 与 Redis 命令对应,简单直观,但 Jedis 实例线程不安全 |
| Lettuce | 基于 Netty,线程安全,支持同步、异步和响应式编程 |
| Redisson | 提供分布式集合、锁、信号量等高级能力 |
Jedis 和 Lettuce 主要提供 Redis 命令对应的 Java API,Spring Data Redis 又对它们进行了统一封装。Redisson 更适合需要分布式锁、分布式集合等高级功能的场景。
五、Jedis 快速入门与连接池
5.1 Jedis 基本使用
引入 Jedis 依赖后,可以通过 Jedis 完成连接、认证、选择数据库和数据操作:
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.7.0</version>
</dependency>private Jedis jedis;
@BeforeEach
void setUp() {
jedis = new Jedis("127.0.0.1", 6379);
jedis.auth("******");
jedis.select(0);
}
@Test
void testString() {
String result = jedis.set("name", "虎哥");
String name = jedis.get("name");
System.out.println("result = " + result);
System.out.println("name = " + name);
}
@Test
void testHash() {
jedis.hset("user:1", "name", "Jack");
jedis.hset("user:1", "age", "21");
Map<String, String> map = jedis.hgetAll("user:1");
System.out.println(map);
}
@AfterEach
void tearDown() {
if (jedis != null) {
jedis.close();
}
}setUp 在测试开始前创建连接、完成认证并选择数据库;测试方法通过 Jedis API 执行 Redis 命令;tearDown 在测试结束后关闭连接,避免连接资源一直占用。
5.2 Jedis 连接池
Jedis 实例本身不是线程安全的。多线程环境下共享同一个 Jedis 实例存在并发风险,频繁创建和销毁连接也会增加开销,因此可以使用连接池统一管理连接:
public class JedisConnectionFactory {
private static final JedisPool jedisPool;
static {
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxTotal(8);
poolConfig.setMaxIdle(8);
poolConfig.setMinIdle(0);
poolConfig.setMaxWaitMillis(1000);
jedisPool = new JedisPool(
poolConfig, "127.0.0.1", 6379, 1000, "******");
}
public static Jedis getJedis() {
return jedisPool.getResource();
}
}连接池预先管理 Jedis 连接。业务代码通过 getResource() 获取连接,使用完毕后调用 close(),连接会回到连接池中复用。
六、Spring Data Redis 与 RedisTemplate
Spring Data Redis 是 Spring 生态中用于操作 Redis 的模块,能够整合不同 Redis 客户端,并通过 RedisTemplate 提供统一的操作入口。
6.1 引入依赖与配置连接
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>spring:
data:
redis:
host: 127.0.0.1
port: 6379
password: ******
lettuce:
pool:
max-active: 8
max-idle: 8
min-idle: 0
max-wait: 100ms6.2 RedisTemplate 的操作入口
Spring Boot 完成自动装配后,可以直接注入 RedisTemplate:
@Autowired private RedisTemplate redisTemplate;
| Java API | Redis 数据类型 |
|---|---|
opsForValue() | String |
opsForHash() | Hash |
opsForList() | List |
opsForSet() | Set |
opsForZSet() | Sorted Set |
redisTemplate | 通用命令 |
例如,使用 opsForValue() 写入和读取 String:
redisTemplate.opsForValue().set("name", "虎哥");
Object name = redisTemplate.opsForValue().get("name");
使用 opsForHash() 时,可以直接操作 Hash 的 field:
redisTemplate.opsForHash().put("user:1", "name", "Jack");
redisTemplate.opsForHash().put("user:1", "age", "21");
Object name = redisTemplate.opsForHash().get("user:1", "name");
七、Redis 对象序列化
Redis 保存的是字节数据。Java 对象写入 Redis 前需要序列化为字节或 JSON 字符串。RedisTemplate 和 StringRedisTemplate 可以采用不同的序列化策略。
7.1 自动序列化
RedisTemplate 默认采用 JDK 序列化。JDK 序列化后的数据占用空间较大,可读性也较差,因此可以自定义 RedisTemplate 的序列化器,让 Key 使用字符串序列化,让 Value 和 Hash Value 使用 JSON 序列化:
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(
RedisConnectionFactory connectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
template.setKeySerializer(RedisSerializer.string());
template.setHashKeySerializer(RedisSerializer.string());
template.setValueSerializer(RedisSerializer.json());
template.setHashValueSerializer(RedisSerializer.json());
return template;
}
}setKeySerializer 和 setHashKeySerializer 负责 Key 及 Hash field 的序列化;setValueSerializer 和 setHashValueSerializer 负责普通 Value 及 Hash Value 的序列化。使用 JSON 序列化后,Redis 中的数据更容易阅读。
7.2 手动序列化
StringRedisTemplate 是 RedisTemplate 的子类,Key 和 Value 默认采用字符串序列化。它不直接负责 Java 对象的 JSON 处理,因此可以配合 ObjectMapper 手动完成 JSON 序列化:
@Autowired
private StringRedisTemplate stringRedisTemplate;
private static final ObjectMapper mapper = new ObjectMapper();
@Test
void testSaveUser() throws JsonProcessingException {
User user = new User("虎哥", 21);
String json = mapper.writeValueAsString(user);
stringRedisTemplate.opsForValue().set("user:200", json);
}writeValueAsString 把 User 对象转换为 JSON 字符串,StringRedisTemplate 负责保存字符串。手动方式保存的数据格式直接,内存占用相对可控,但序列化代码需要由业务方维护。
7.3 两种序列化方式的区别
| 方式 | 优点 | 需要承担的工作 |
|---|---|---|
| RedisTemplate 自动 JSON 序列化 | 使用方便,读写对象时代码更少 | 配置序列化器,并接受类型信息带来的额外数据 |
| StringRedisTemplate 手动 JSON 序列化 | 数据格式直接,便于控制内容和空间 | 手动调用 ObjectMapper 完成序列化 |
如果更关注开发便利性,可以配置 RedisTemplate 自动序列化;如果更关注数据格式和内存控制,可以使用 StringRedisTemplate 手动处理 JSON。
八、总结
Redis 的学习主线可以归纳为:先理解 key-value 模型,再通过 String、Hash、List、Set、Sorted Set 五种数据类型认识 Redis 的数据组织方式,最后使用 Jedis 或 Spring Data Redis 接入 Java 项目。
在 Spring 项目中,RedisTemplate 负责统一操作入口,序列化方式决定 Java 对象如何落到 Redis。自动 JSON 序列化更省代码,StringRedisTemplate 配合 ObjectMapper 手动序列化更容易控制数据格式和内存占用。
到此这篇关于Redis数据类型、常用命令与Java客户端详解的文章就介绍到这了,更多相关Redis数据类型与常用命令内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
IDEA导入Springboot项目,注解和pom文件不识别的解决
这篇文章主要介绍了IDEA导入Springboot项目,注解和pom文件不识别的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教2023-04-04
MyBatis-Plus整合金仓数据库KingbaseES的实战指南
随着数字中国建设的深入推进,国产数据库在关键业务系统中扮演着越来越重要的角色,本文将通过一个电商系统的实战案例,深入探讨MyBatis-Plus整合KingbaseES的详细步骤吧2025-10-10


最新评论