在平常的开发过程中,我们经常会用到缓存的技术。比如,验证码60秒后过期、计数器的实现、商品信息存储在缓存中快速展示等。那么,项目中经常会使用到的便是 redis 缓存。redis 在内存中操作,读写快。Redis 常用的数据类型有五种,String、List、Hash、Set、Sorted Set。那么,今天我们总结下项目中引入 Redis 及常见数据类型操作。
一:概述
Redis 基于内存的数据结构存储系统,主要用于缓存、分布式锁等场景。数据结构丰富:Redis 支持多种数据结构,常用的如字符串(String)、列表(List)、哈希(Hash)、集合(Set)、有序集合(Sorted Set)等。可以支持不同业务场景的使用。
Redis 将数据存储在内存中,读写快。内存的高速访问特性使得 Redis 可以在短时间内处理大量的请求,适用于对性能要求极高的场景,如实时数据处理、缓存等。Redis 也提供了持久化机制,如 RDB(Redis Database)快照和 AOF(Append Only File)日志,能够将内存中的数据定期或实时地保存到磁盘上,以防止数据丢失。
Redis 的命令具有原子性,即一个命令要么完全执行,要么完全不执行,不会出现部分执行的情况。这保证了数据的一致性和完整性。
二:引入依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId><version>2.1.5.RELEASE</version> <!-- 版本与 Spring Boot 保持一致 -->
</dependency>
注意:引入 Redis 的版本与 Springboot 版本保持一致。
三:redis 连接信息配置
1:如果 Spring boot 2.x 版本,那么在 application.yml 中配置 redis 连接信息如下:
spring:redis:# 连接地址host: 127.0.0.1# 端口port: 6379# 数据库database: 0# 用户名# username: username# 密码password: passrord# 连接超时# connect-timeout: 5s# 读超时# timeout: 30
2:如果 Spring boot 3.x 版本,那么在 application.yml 中配置 redis 连接信息如下:
spring:data:redis:# 连接地址host: 127.0.0.1# 端口port: 6379# 数据库database: 0# 用户名# username: username# 密码password: passrord# 连接超时# connect-timeout: 5s# 读超时# timeout: 30
注意:Spring Boot 3.x 对配置属性进行了更严格的规范化,将数据相关的配置统一到 spring.data 命名空间下,提高一致性和可维护性。
四:五种常用数据类型
1:字符串 String
应用场景:验证码、计数器、分布式锁,最大可存储 512 m。
代码示例:
// 操作字符串
// 不设置过期时间
stringRedisTemplate.opsForValue().set("11", "蜜薯");
// 设置过期时间为 10 秒钟
stringRedisTemplate.opsForValue().set("12", "马铃薯", Duration.ofSeconds(10));
// 设置过期时间为 10 秒钟
stringRedisTemplate.opsForValue().set("13", "红薯", 10, TimeUnit.SECONDS);
// 获取值
String value11 = stringRedisTemplate.opsForValue().get("11");
log.info("value11={}", JSONUtil.toJsonStr(value11));
2:列表 List
应用场景:有序元素集合 用户搜索近十条历史记录、最新消息展示
代码示例:
// 有序元素集合 用户搜索近十条历史记录、最新消息展示
// 操作 list
List<SysDictData> dictDataList = new ArrayList<>();
for (int i = 0; i < 10; i++) {SysDictData dictData = new SysDictData();dictData.setDictCode(Long.valueOf(i));dictData.setDictLabel("字典" + i);dictDataList.add(dictData);
}
// 将 list 对象转为 String
// 不设置过期时间
stringRedisTemplate.opsForValue().set("dictListString", JSONUtil.toJsonStr(dictDataList));
// 设置过期时间
stringRedisTemplate.opsForValue().set("dictListString", JSONUtil.toJsonStr(dictDataList), 10, TimeUnit.MINUTES);
String dictListString = stringRedisTemplate.opsForValue().get("dictListString");
List<SysDictData> dictDataListRedis = JSONUtil.toList(dictListString, SysDictData.class);
log.info("dictDataListRedis={}", JSONUtil.toJsonStr(dictDataListRedis));stringRedisTemplate.opsForList().leftPush("dictList", "字典1");
stringRedisTemplate.opsForList().leftPush("dictList", "字典2");
stringRedisTemplate.opsForList().leftPush("dictList", "字典3");
stringRedisTemplate.opsForList().leftPush("dictList", "字典4");stringRedisTemplate.opsForList().rightPush("dictList", "字典5");
// 取出 list 中所有的值
List<String> dictListValueAll = stringRedisTemplate.opsForList().range("dictList", 0, -1);
log.info("dictListValueAll={}", JSONUtil.toJsonStr(dictListValueAll));
// 取出 list 中前三条数据
List<String> dictListValueThree = stringRedisTemplate.opsForList().range("dictList", 0, 2);
log.info("dictListValueThree={}", JSONUtil.toJsonStr(dictListValueThree));
3:哈希 Hash
应用场景:field-value 映射表,适合存储对象,用户属性信息、商品信息
代码示例:
// 添加 111 用户
stringRedisTemplate.opsForHash().put("111", "name", "张三");
stringRedisTemplate.opsForHash().put("111", "age", "98");
stringRedisTemplate.opsForHash().put("111", "phone", "123456789");
stringRedisTemplate.opsForHash().put("111", "address", "西安");
// 添加 222 用户
stringRedisTemplate.opsForHash().put("222", "name", "李四");
stringRedisTemplate.opsForHash().put("222", "age", "88");
stringRedisTemplate.opsForHash().put("222", "phone", "123456789");
stringRedisTemplate.opsForHash().put("222", "address", "宝鸡");
// 获取全部元素
Map<Object, Object> scoresMap = stringRedisTemplate.opsForHash().entries("scores");
log.info("scoresMap={}", JSONUtil.toJsonStr(scoresMap));
// 获取某个 key 的值
Object scoresSingleMap = stringRedisTemplate.opsForHash().get("scores", "112");
log.info("scoresSingleMap={}", JSONUtil.toJsonStr(scoresSingleMap));
4:集合 Set
应用场景:无序、元素不可重复 抽奖系统、计数器
代码示例:
stringRedisTemplate.opsForSet().add("cities", "11", "12", "13", "14", "15", "16");
// 获取到所有值 适合数据量小
Set<String> setCitiesAll = stringRedisTemplate.opsForSet().members("cities");
log.info("setCitiesAll={}", JSONUtil.toJsonStr(setCitiesAll));
5:有序集合 Sorted Set
应用场景:带分数的 set,分数可以重复,元素唯一 排行榜、范围查询
代码示例:
stringRedisTemplate.opsForZSet().add("studentIds", "111", 1);
stringRedisTemplate.opsForZSet().add("studentIds", "112", 2);
stringRedisTemplate.opsForZSet().add("studentIds", "113", 3);
stringRedisTemplate.opsForZSet().add("studentIds", "114", 4);
stringRedisTemplate.opsForZSet().add("studentIds", "115", 5);
stringRedisTemplate.opsForZSet().add("studentIds", "116", 6);
// 数据量小,全部获取
Set set = stringRedisTemplate.opsForZSet().range("studentIds", 0, -1);
log.info("studentIds set={}", JSONUtil.toJsonStr(set));
如果数据量大,则分页获取:
// 获取数据总条数
Long totalSize = stringRedisTemplate.opsForZSet().size("studentIds");
// 分页获取key中的数据
Set<String> studentIdsSet = new HashSet<>();
// 每页获取的记录数
int pageSize = 2;
// 计算总页数
int totalPages = (int) Math.ceil(totalSize / (double) pageSize);
for (int page = 0; page < totalPages; page++) {// 每次获取数据开始的位置long start = (long) page * pageSize;// 每次获取数据结束的位置long end = start + pageSize - 1;// 获取数据Set<ZSetOperations.TypedTuple<String>> setData = stringRedisTemplate.opsForZSet().rangeWithScores("studentIds", start, end);if (CollUtil.isNotEmpty(setData)) {// 将数据进行转换Set<String> cacheData = setData.stream().map(item -> {String value = JSONObject.parseObject(item.getValue(), String.class);return value;}).filter(Objects::nonNull).collect(Collectors.toSet());studentIdsSet.addAll(cacheData);}
}
五:总结
以上为项目中引入 Redis 的基本步骤,以及常见五种数据类型的应用场景及操作方法。
Redis 广泛应用于缓存、消息队列、实时分析、分布式锁等场景。它支持多种数据结构(如 String、List、Hash、Set、Sorted Set等),并提供了持久化、高可用、集群、事务、Lua 脚本、发布/订阅等。
Redis 数据存储在内存中,读写速度快,适用于高并发低延迟场景。同时,它支持 RDB(快照)和 AOF(日志追加)持久化,确保数据安全。