相关链接:
- 超详细Redis下载安装图文教程(Win和Linux版)-CSDN博客
- Redis 命令 | 菜鸟教程 (runoob.com)
- Commands | Docs (Redis官方文档)
- Redis 16 个常见使用场景_redis用途-CSDN博客
- AnotherRedisDesktopManager-Redis图形化工具
- 在 Spring Boot 中整合、使用 Redis - spring 中文网 (springdoc.cn)
- SpringDataRedis的RedisTemplate常用方法总结(参考官方文档2.6.2)CSDN博客
- Redis入门到实战教程_哔哩哔哩_bilibili
一、基础知识
1. 简介
Redis(Remote Dictionary Server)是一个开源的高性能键值存储数据库。它是使用C语言编写的,支持多种类型的数据结构,如字符串、哈希、列表、集合、有序集合等。Redis将数据存储在内存中,因此其拥有极快的读写速度和极低的延迟,这使得它成为处理高并发请求的理想选择,被广泛用于缓存、消息队列、实时分析、会话存储等场景。Redis支持数据持久化,可以配置为在内存中处理数据同时定期或根据条件将数据保存到磁盘,确保数据的安全性。此外,它还支持主从复制和哨兵系统,以提供高可用性和自动故障转移。
2. 常见数据类型
2.1 String(字符串):
字符串是最基本的数据类型,其值的类型又细分为整数(int)、浮点数(float)、普通字符串(string),前两种类型可以进行自增、自减操作。在Redis中,字符串类型的值最大可以存储512MB。
其常见使用场景有:
- 缓存文本数据、JSON数据、图片、音频、视频、压缩文件等二进制数据;
- 实现计数功能
- 实现限流功能
- 实现全局ID功能
- 实现分布式锁
- 在分布式系统中实现数据共享
2.2 Hash(哈希):
也称为散列,其值是一个无需字典(键值对集合),其中每个键都对应一个值,类似Java中的HashMap
。
其常见使用场景有:
- 存放对象、结构体的信息;
- 缓存数据库表的信息
2.3 List(列表):
列表是一个有序的字符串列表,其中每个元素都是一个字符串,根据元素插入的顺序排序,类似Java中的LinkedList
。在Redis中,列表类型的值可以进行头部、尾部的插入和删除操作,还可以根据索引获取元素。
其常见使用场景有:
- 实现消息队列、任务队列;
- 实现秒杀、抢购功能;
- 实现时间轴功能;
- 实现显示最新的项目列表功能
2.4 Set(无序集合):
无序集合是一个无序的字符串集合,其中每个元素都是唯一的,不能重复,类似Java中的HashSet
。在Redis中,无序集合类型的值支持添加、删除、查找等操作。
其常见使用场景有:
- 计算交集、并集、差集;
- 实现抽奖功能;
- 实现标签功能;
- 实现点赞、签到、打卡功能;
- 实现好友关系、用户关注功能
- 实现推荐模型功能
- 实现倒排索引功能
2.5 Sorted Set(有序集合):
有序集合是一个有序的字符串集合,其中每个元素都会关联一个double类型的分数(score),根据分数进行排序。在Redis中,有序集合类型的值支持添加、删除、查找、根据分数范围获取元素等操作。
其常见使用场景有:
- 实现排行榜功能;
- 实现范围查询功能;
- 实现优先级队列
2.6 其他数据类型
除了上述几个基本数据类型外,Redis还支持以下数据类型,具体实现和使用方法可自行查阅:
- 超日志(HyperLogLog):基于字符串类型实现。用于基数统计,可以估算集合中唯一元素的数量;
- 位图(Bitmaps):一种将字符串作为位数组的数据结构,适合用于处理大型的位数组;
- 地理空间(Geospatial):用于存储地理位置信息,并进行地理位置查询;
- 流(Stream):在Redis 5.0时加入,用于构建复杂的实时消息系统;
- 模块(Modules):通过模块可扩展新的数据类型和功能
3. 图形化界面
相比命令行操作,使用Redis图形化管理工具可以更方便快捷地执行Redis常用操作,同时,图形化界面的数据显示也更为直观。
常用的Redis图形化工具有:
- RedisInsight:Redis官方的图形化管理工具;
- Another Redis Desktop Manager:功能更强大且稳定的国产Redis图形化管理工具;
- Tiny RDM:轻量级的Redis图形化管理工具;
- QuickRedis
- RedisFront
二、常用命令
与SQL语句类似,Redis的命令不区分大小写,但是为了提高可读性和一致性,建议所有命令关键字大写,命令参数等其他内容小写。其他开发规范可参考阿里云Redis开发规范。
1. 通用命令:
命令 | 说明 | 备注 |
---|---|---|
KEYS patterm | 查看匹配patterm的所有key | 会遍历所有键,在数据量过多的情况下使用会影响性能,建议使用SCAN 替代此命令。patterm模式匹配的语法: * :匹配任何数量的字符,但不包括空字符;? :匹配任何单个字符;[...] :匹配方括号内的任何单个字符;[a-z] :匹配指定范围内的任何单个字符 |
SCAN cursor [MATCH pattern] [COUNT count] | 参数说明:cursor :游标,初始值为0,每次调用该命令后会自增count;MATCH pattern :可选参数,用于过滤返回的键,只返回符合给定模式的键;COUNT count :可选参数,指定每次迭代返回的键的数量,默认为10 | |
DBSIZE | 查看当前数据库的key总数 | |
DEL key [key…] | 删除指定的key | 返回成功删除的key的数量 |
EXISTS key [key…] | 判断指定key是否存在 | 返回存在的key的数量 |
TYPE key [key…] | 判断指定key的类型 | 返回类型有string 、list 、set 、zset 、hash 或 none (表示key不存在)。如果提供了多个key则返回一个数组,其中包含每个key的类型 |
RENAME old_key new_key | 重命名指定key | 当old_key 不存在或与new_key 相同则不执行操作;当new_key 已存在则用old_key 的值覆盖nwe_key 的值 |
RENAMEX old_key new_key | 重命名指定key | 当new_key 已存在则不执行操作,其他同上 |
COPY source_key dest_key [db destination_db] [REPLACE|NOP] | 将source_key的值复制到dest_key中(可跨数据库复制) | 选项的含义:REPLACE :当dest_key已经存在时,将其替换为source_key的值;NOP :当dest_key已经存在时,不执行操作(默认) |
MOVE key db | 将指定key移动到指定数据库 | |
TTL key | 查看指定key过期的秒数 | 要查看毫秒数可使用PTTL |
EXPIRE key seconds [NX|XX|GT|LT] | 设置指定key的过期时间为seconds秒 | key过期后会被自动删除。要设置毫秒数可使用PEXPRIRE 。选项的含义: NX :只有当 key 不存在时,才设置过期时间;XX :只有当 key 已经存在时,才设置过期时间;GT :只有当 key 的剩余生存时间大于给定的时间时,才设置过期时间;LT :只有当 key 的剩余生存时间小于给定的时间时,才设置过期时间 |
PERSIST key | 设置指定key永不过期 | |
FLUSHDB | 清除当前数据库的内容 |
2. 字符串类型命令:
命令 | 说明 | 备注 |
---|---|---|
SET key value | 设定指定key的值为value | 存在则覆盖值,不存在则添加 |
GET key | 获取指定key的值 | |
MSET key1 value1 key2 value2 … | 批量设置多个字符串类型的键值对的值 | 存在则覆盖值,不存在则添加 |
MGET key1 value1 key2 value2 … | 批量获取多个key的值 | |
SETNX key value | 当key的值不存在时,设定指定key的值为value | 存在则不执行操作,不存在则添加 |
SETEX key seconds value | 设置指定key的值为value,并将key的过期时间设为seconds秒 | |
INCR key | 让指定整数类型key的值自增1 | 对浮点数类型的值进行操作可以使用INCRFLOAT |
INCRBY key increment | 让指定整数类型key的值自增increment | 对浮点数类型的值进行操作可以使用INCRBYFLOAT |
DECR key | 让指定整数类型key的值自减1 | 对浮点数类型的值进行操作可以使用DECRFLOAT |
DECRBY key increment | 让指定整数类型key的值自减increment | 对浮点数类型的值进行操作可以使用INCRBYFLOAT |
STRLEN key | 获取指定key的值的长度 | |
APPEND key value | 向指定key的值的末尾追加内容 |
3. 哈希类型命令
命令 | 说明 | 备注 |
---|---|---|
HSET key field value | 将key中的字段field的值设为value | 存在则覆盖值,不存在则添加 |
HGET key field | 获取key中的字段field的值 | |
HDEL key field | 删除key中的字段field | |
HMSET key field1 value1 field2 value2 … | 向key中批量添加多个键值对 | 存在则覆盖值,不存在则添加 |
HMGET key field1 field2 … | 在key中批量获取多个字段的值 | |
HSETNX key filed value | 当field不存在时,将key中的字段field的值设为value | 存在则不执行操作,不存在则添加 |
HKETS key | 获取key中的所有字段名 | |
HVALS key | 获取key中的所有字段的值 | |
HINCRBY key field increment | 让key中的字段field的值自增increment | 对浮点数类型的值进行操作可以使用HINCRBYFLOAT 。想要实现自减可以使increment 为负数 |
4. 列表类型命令
命令 | 说明 | 备注 |
---|---|---|
LPUSH key value [value…] | 将一个或多个值插入到列表key的左侧 | |
RPUSH key value [value…] | 将一个或多个值插入到列表key的右侧 | |
LPOP key | 移除并返回列表key左侧的第一个值 | |
RPOP key | 移除并返回列表key右侧的第一个值 | |
BLPOP key [key…] timeout | 移除并返回列表key左侧的第一个值,如列表为空则等待timeout秒 | |
RLPOP key [key…] timeout | 移除并返回列表key右侧的第一个值,如列表为空则等待timeout秒 | |
LSET key index value | 将列表key中下标为index的元素值设为value | |
LLEN key | 获取列表key的长度 | |
LRANGE key start stop | 获取列表key中start到stop范围内的元素的值 | 列表的非负整数下标从0开始表示第一个元素,依次递增;负数下标从-1开始表示最后一个元素,依次递减 |
LTRIM key start stop | 保留列表key中start到stop范围内的元素,删除范围外的元素 | |
LINSERT key BEFORE|AFTER pivot value | 在列表key中的pivot元素之前或之后插入元素value | |
RPOPLPUSH source destination | 移除并返回列表source右侧的第一个值,同时将该值插入到列表destination的左侧 |
5. 无序集合类型命令
命令 | 说明 | 备注 |
---|---|---|
SADD key member [member…] | 向无序集合key中添加一个或多个成员 | 存在则覆盖值,不存在则添加 |
SREM key member [member…] | 移除无序集合key中的一个或多个成员 | |
SMEMBERS key | 获取无序集合key中的所有成员 | |
SCARD key | 获取无序集合key的成员总数 | |
SISMEMBER key member | 判断member是否是无序集合key的成员 | |
SPOP key [count] | 随机移除并返回无序集合key中的count个成员 | 如果不指定 count,则默认为1;如果指定的 count 大于集合中的元素数,则移除并返回所有成员 |
SRANDMEMBER key [count] | 随机返回无序集合key中的count个成员 | 如果不指定 count,则默认为1;如果指定的 count大于集合中的元素数,则返回所有成员 |
SMOVE source destination member | 将成员member从无序集合source移动到无序集合destination | |
SINTER key1 [key2 key3 …] | 获取所给无序集合的交集 | 交集即在所有给定集合中都存在的成员 |
SUNION key1 [key2 key3 …] | 获取所给无序集合的并集 | 并集即在所有给定集合中存在的成员 |
SDIFF key1 [key2 key3 …] | 获取所给无序集合的差集 | 差集即只在第一个集合中存在,而不在后续集合中的成员 |
SINTERSTORE destination key1 [key2 key3 …] | 获取所给无序集合的交集,结果存储在无序集合destination中 | |
SUNIONSTORE destination key1 [key2 key3 …] | 获取所给无序集合的并集,结果存储在无序集合destination中 | |
SDIFFSTORE destination key1 [key2 key3 …] | 获取所给无序集合的差集,结果存储在无序集合destination中 | |
SSCAN key cursor [MATCH pattern] [COUNT count] | 迭代地返回无序集合key中的成员 | 参数说明:cursor :游标,初始值为0,每次调用该命令后会自增count;MATCH pattern :可选参数,用于过滤返回的键,只返回符合给定模式的键;COUNT count :可选参数,指定每次迭代返回的键的数量,默认为10 |
6. 有序集合类型命令
命令 | 说明 | 备注 |
---|---|---|
ZADD key score member [score member…] | 向有序集合key中添加一个或多个成员,并指定分数 | 存在则覆盖值,不存在则添加 |
ZREM key member [member…] | 移除有序集合key中的一个或多个成员 | |
ZCARD key | 获取有序集合key的成员总数 | |
ZSCORE key member | 获取有序集合key中成员member的分数 | |
ZCOUNT key min max | 获取有序集合key中分数在min和max之间的成员数 | |
ZINCRBY key increment member | 有序集合key中成员member的分数增加 increment | |
ZRANGE key min max [WITHSCORES] | 获取有序集合key中min到max范围内的成员 | 加上WITHSCORES 选项可同时成员的获取分数 |
ZREVRANGE key min max [WITHSCORES] [LIMIT offset count] | 获取有序集合key中start到stop范围内的成员,按分数从大到小排序 | 参数说明:WITHSCORES :可同时获取成员的分数;LIMIT offset count :表示从第offset个成员开始,最多返回count个元素。offset的值从0开始。想在不知道有序集合的最低和最高分数的情况下获取所有成员,可将 min 和max 写成-inf 和+inf 。按分数从小到大排序可使用命令 ZRANGEBYSCORE |
ZRANK key member | 获取成员member在有序集合key中的排名,按分数从小到大排序 | 按分数从小到大排序可使用命令ZREVRANK |
ZPOPMAX key [count] | 移除并返回有序集合key 中分数最高的count个成员 | 移除并返回有序集合key中分数最低的count个成员可使用命令ZPOPMIN |
三、在Java中操作Redis
1. Redis的Java客户端
Redis的Java客户端是一组用于在Java程序中与Redis数据库进行交互的库和工具,它们提供了一套API,使得开发者可以在Java程序中执行Redis命令,除此之外这些客户端还可以处理连接管理、序列化、以及与Redis服务器的异步通信,从而使得在Java应用程序中集成和使用Redis变得简单和高效。
常用的Redis的Java客户端有:
- Jedis:以Redis命令作为方法名称,学习成本低。支持Redis的基本功能,但是Jedis是线程不安全的,多线程环境下需要基于连接池来使用;
- Lettuce:基于Netty实现,支持同步、异步和响应式编程方式,并且是线程安全的。除了支持Redis的基本功能,还支持哨兵模式、集群模式和管道模式;
- Redisson:是一个基于Redis实现的分布式、可伸缩的Java数据结构集合。除了支持Redis的基本功能,还提供了许多分布式数据结构和对以及一些额外的高级功能(如分布式锁、事务、事件发布等)简化了分布式应用的开发
如果想在Java项目中单独使用这些客户端,可以在项目中导入对应的依赖并配置客户端以连接到Redis服务。之后便可以在代码中调用客户端提供的API直接在项目中与Redis数据库进行交互,具体使用方法可自行查阅。
2. Spring Data Redis
Spring Data是Spring中的数据操作模块,用于在项目中提供对各种数据库的集成和操作支持,其中提供对Redis的集成和操作支持的模块就叫Spring Data Redis。它对Jedis和Lettuce进行了封装,提供了一套统一的API以及其他一系列功能,进一步简化了配置,提高了开发效率。
相比单独使用传统的Redis的Java客户端,Spring Data Redis的优点有:
- 底层可以切换使用不同的Redis的Java客户端,并简化了配置和连接Redis服务的过程;
- 与Spring框架紧密集成,可以无缝地使用Spring的依赖注入、配置管理、事务处理等特性;
- 提供了
RedisTemplate
和StringRedisTemplate
类对底层客户端的API进行封装,降低了操作的复杂性,使得代码更加简洁和易于维护; - 可以灵活配置键和值的序列化和反序列化方式,以适应不同的数据存储需求;
- 支持发布-订阅模式、哨兵模式、集群模式、连接池管理等功能
2.1 引入并配置Spring Data Redis
以使用了Spring Boot(版本为2.0及以上)的项目为例,要在项目中引入并配置Spring Data Redis通常分为以下几个步骤:
第一步:导入Spring Data Redis的依赖
如果你使用的是Maven作为构建工具,则在pom.xml
文件中添加如下依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
如果你使用的是Gradle作为构建工具,则在build.gradle
文件中添加如下依赖
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
第二步,配置并连接Redis服务
如果你使用的是application.yaml
作为配置文件,则可以在文件中配置如下常用的基本属性
spring:
data:
redis:
# 连接地址
host: "127.0.0.1"
# 端口
port: 6379
# 数据库
database: 0
# 用户名,如果有
# username:
# 密码,如果有
# password:
# 连接超时
connect-timeout: 5s
# 读超时
timeout: 5s
# Lettuce 客户端的配置
lettuce:
# 连接池配置
pool:
# 最小空闲连接
min-idle: 0
# 最大空闲连接
max-idle: 8
# 最大活跃连接
max-active: 8
# 从连接池获取连接 最大超时时间,小于等于0则表示不会超时
max-wait: -1ms
如果你使用的是application.properties
作为配置文件,则可以将上面的配置内容改成如下格式
spring.data.redis.host=127.0.0.1
spring.data.redis.port=6379
spring.data.redis.database=0
# spring.data.redis.username=
# spring.data.redis.password=
spring.data.redis.connect-timeout=5s
spring.data.redis.timeout=5s
# Lettuce 客户端的配置
spring.data.redis.lettuce.pool.min-idle=0
spring.data.redis.lettuce.pool.max-idle=8
spring.data.redis.lettuce.pool.max-active=8
spring.data.redis.lettuce.pool.max-wait=-1ms
第三步:创建Spring Data Redis的配置类
如果你想进一步配置Spring Data Redis,比如自定义序列化和反序列化方式,配置连接工厂、连接池、哨兵和集群,可以创建配置类并在其中定义各种配置,如果没有以上需求则可以跳过这一步。下面提供一个简单的Redis配置类的示例
@Configuration
public class RedisConfig {
// 定义Redis连接工厂,这里使用Lettuce作为客户端
@Bean
public RedisConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory();
}
// 配置RedisTemplate
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
// 设置key和value的序列化方式
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new JdkSerializationRedisSerializer());
// 设置hash key 和 hash value 序列化方式
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(new JdkSerializationRedisSerializer());
// 设置其他内容...
// 初始化RedisTemplate
template.afterPropertiesSet();
return template;
}
// 配置StringRedisTemplate
@Bean
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory factory) {
StringRedisTemplate template = new StringRedisTemplate();
template.setConnectionFactory(factory);
template.afterPropertiesSet();
return template;
}
}
2.2 常用API
RedisTemplate
是Spring Data Redis的核心类,提供了一套API用于操作Redis中的各种数据类型,支持自定义序列化和反序列化。StringRedisTemplate
继承自RedisTemplate
,专门用于处理字符串键值对,使用内置的字符串序列化器,适合不需要复杂序列化的场景。
RedisTemplate
将不同数据类型的操作方法封装到了各自的操作接口中,这些操作接口有:
操作接口 | 返回值类型 | 说明 |
---|---|---|
redisTemplate | 执行通用操作 | |
redisTemplate.opsForValue() | ValueOperations | 操作字符串类型数据 |
redisTemplate.opsForHash() | HashOperations | 操作哈希类型数据 |
redisTemplate.opsForList() | ListOperations | 操作列表类型数据 |
redisTemplate.opsForSet() | SetOperations | 操作无序列表类型数据 |
redisTemplate.opsForZSet() | ZSetOperations | 操作有序列表类型数据 |
通过这些操作接口便可以调用对应数据类型的操作,如redisTemplate.opsForValue().set("key", "example value")
就是将一个键为key
和值为example value
的键值对设置到Redis数据库中。下面提供一个RedisTemplate
的使用示例:
@Service
public class RedisService {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
// 测试字符串类型的操作
public void testString() {
// 设置字符串类型的值
String key = "testStringKey";
String value = "Hello, Redis!";
setValue(key, value);
// 获取字符串类型的值
String retrievedValue = (String) getValue(key);
System.out.println("Retrieved Value: " + retrievedValue);
// 递增字符串类型的值(将字符串视为数字)
Long incrementedValue = increment(key);
System.out.println("Incremented Value: " + incrementedValue);
}
// 测试哈希类型的操作
public void testHash() {
// 设置哈希键值对
String hashKey = "testHashKey";
String field = "field1";
String hashValue = "HashValue1";
redisTemplate.opsForHash().put(hashKey, field, hashValue);
// 获取哈希键的某个字段值
String retrievedHashValue = (String) redisTemplate.opsForHash().get(hashKey, field);
System.out.println("Retrieved Hash Value: " + retrievedHashValue);
// 递增哈希键的某个字段值(将字段值视为数字)
Long incrementedHashValue = redisTemplate.opsForHash().increment(hashKey, field, 1L);
System.out.println("Incremented Hash Value: " + incrementedHashValue);
}
// 测试列表类型的操作
public void testList() {
// 将元素添加到列表中
String listKey = "testListKey";
String listValue = "ListElement1";
redisTemplate.opsForList().rightPush(listKey, listValue);
// 获取列表中的所有元素
List<Object> listValues = redisTemplate.opsForList().range(listKey, 0, -1);
System.out.println("List Values: " + listValues);
}
// 测试集合类型的操作
public void testSet() {
// 将元素添加到集合中
String setKey = "testSetKey";
String setValue = "SetValue1";
redisTemplate.opsForSet().add(setKey, setValue);
// 获取集合中的所有元素
Set<Object> setValues = redisTemplate.opsForSet().members(setKey);
System.out.println("Set Values: " + setValues);
}
// 测试有序集合类型的操作
public void testZSet() {
// 将元素添加到有序集合中
String zsetKey = "testZSetKey";
String zsetValue = "ZSetValue1";
Double score = 1.0;
redisTemplate.opsForZSet().add(zsetKey, zsetValue, score);
// 获取有序集合中的所有元素
Set<Object> zsetValues = redisTemplate.opsForZSet().range(zsetKey, 0, -1);
System.out.println("ZSet Values: " + zsetValues);
}
// 测试过期时间的设置
public void testExpire() {
// 设置键的过期时间
String expireKey = "testExpireKey";
setValue(expireKey, "ExpireValue");
boolean expired = expire(expireKey, 10, TimeUnit.SECONDS);
System.out.println("Key Expired: " + expired);
}
}
Spring Data Redis其他常用的方法和操作可参考文章开头的参考链接,或自行查阅其他相关文章或教程。