java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Redis数据类型与常用命令

Redis数据类型、常用命令与Java客户端详解

作者:程序猿乐锅

Redis是一种基于内存的键值型NoSQL数据库,这篇文章给大家介绍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 设计

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浮点数递增
setnxKey 不存在时才写入
setex写入字符串并设置有效期

String 适合保存文本、计数器、数字和带有效期的临时数据。setnx 可以利用“Key 不存在才写入”的特性完成简单的占位操作。

3.2 Hash 类型

Hash 可以看成一个无序的 field-value 字典,结构类似 Java 中的 HashMap:一个 Redis Key 下可以保存多个字段。

命令作用
hset、hget写入或读取一个字段
hmset、hmget批量写入或读取多个字段
hgetall获取全部 field 和 value
hkeys获取全部 field
hincrby让指定字段按步长递增
hsetnxfield 不存在时才写入

如果把整个对象保存成 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。

客户端特点
JedisAPI 与 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: 100ms

6.2 RedisTemplate 的操作入口

Spring Boot 完成自动装配后,可以直接注入 RedisTemplate:

@Autowired
private RedisTemplate redisTemplate;
Java APIRedis 数据类型
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;
    }
}

setKeySerializersetHashKeySerializer 负责 Key 及 Hash field 的序列化;setValueSerializersetHashValueSerializer 负责普通 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数据类型与常用命令内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文