当前位置: 首页 > news >正文

Spring Boot(二十一):RedisTemplate的String和Hash类型操作

RedisTemplate和StringRedisTemplate的系列文章详见:

Spring Boot(十七):集成和使用Redis

Spring Boot(十八):RedisTemplate和StringRedisTemplate

Spring Boot(十九):StringRedisTemplate的常用方法和注意事项

Spring Boot(二十):RedisTemplate的序列化

RedisTemplate支持Redis提供的所有数据类型(包括String、Hash、List、Set和ZSet等),并提供灵活的配置选项和事务支持,方便开发者与Redis交互。

String类型操作

如果键和值都是String类型,推荐使用StringRedisTemplate来操作,StringRedisTemplate的各种方法,详见Spring Boot(十九),下面我们来简单介绍两个Spring Boot(十九)中没有涉及的方法

​1、opsForValue().increment​

方法签名:

Long increment(K key):默认加1,返回递增后的新值,可直接用于业务判断

Long increment(K key, long num):如果num为正数,则值加num,如果num为负数,则值减num,返回递增后的新值,可直接用于业务判断

示例:

try {
    stringRedisTemplate.opsForValue().set("name:number", "12345");
    log.info("name:number, {}", stringRedisTemplate.opsForValue().get("name:number"));
    Long num = stringRedisTemplate.opsForValue().increment("name:number");
    log.info("name:number increment加1, {}", num);
    num = stringRedisTemplate.opsForValue().increment("name:number", 10);
    log.info("name:number increment加10, {}", num);
    num = stringRedisTemplate.opsForValue().increment("name:number", -10);
    log.info("name:number increment减10, {}", num);
} catch (Exception e) {
    log.info("name:number increment error, {}", e.toString());
} 

2、opsForValue().decrement

方法签名:

Long decrement(K key):默认减1,返回递减后的新值,可直接用于业务判断

Long decrement(K key, long num):如果num为正数,则值减num,如果num为负数,则值加num,返回递减后的新值,可直接用于业务判断

3、使用场景

increment的使用场景:

1)独立计数器:用于统计访问量、点赞数、下载量等

2)限流:限制接口的访问频率,如每秒最多允许访问100次

3)唯一ID生成:生成全局唯一的递增ID

4)分布式计数器:跟踪分布式系统中待处理任务的数量

decrement的使用场景:

1)库存管理:用于减少商品库存

2)名额限制:优惠券剩余数量、报名人数统计

3)余额减少:在金融系统中减少账户余额

4)限流:减少允许的访问次数

5)分布式计数器:跟踪分布式系统中待处理任务的数量

4、注意

1)值的类型必须为整数

使用increment或decrement方法时,如值为整数类型(如String类型的"123"),则会正常的增减,若值为字符串(比如"value"),则会报如下错误:

org.springframework.data.redis.RedisSystemException: Error in execution; nested exception is io.lettuce.core.RedisCommandExecutionException: ERR value is not an integer or out of range

2)序列化问题

如果使用的是RedisTemplate,需要确保值的序列化器为StringRedisSerializer,在Spring Boot(二十)中我们把RedisTemplate的值的序列化方式改​为了Jackson2JsonRedisSerializer,​所以如果直接使用redisTemplate.opsForValue().increment会报错,因为这时值为Json格式,值不能直接自增或自减,报错如下:

org.springframework.data.redis.RedisSystemException: Error in execution; nested exception is io.lettuce.core.RedisCommandExecutionException: ERR value is not an integer or out of range 

3)初始值

执行increment和decrement时,如果键不存在,Redis会将其值初始化为0,然后执行自增/自减操作

4)原子性

increment和decrement操作是原子性的,保证在高并发场景下的数据一致性

Hash类型操作

RedisTemplate对Redis中的Hash类型提供了多种操作方法,​通过opsForHash(),​可以进行Hash的增删查操作。

1、基本操作

Hash类型适合存储多字段对象或需要频繁更新部分字段的数据,下面我们通过用户信息存储来说明一下Hash类型的操作:

// 存储用户信息
redisTemplate.opsForHash().put("user:1001", "name", "Alice");
redisTemplate.opsForHash().put("user:1001", "age", "29");
redisTemplate.opsForHash().put("user:1001", "email", "alice@test.com");

// 获取单个字段
String name = redisTemplate.opsForHash().get("user:1001", "name").toString();
log.info("user:1001 name, {}", name);

// 获取所有字段
Map<String, Object> user = redisTemplate.opsForHash().entries("user:1001");
user.forEach((key, value) -> {
    log.info("key:{}, value:{}", key, value.toString());
});

还可以使用另外一种方式存储用户信息:

Map<String, String> userMap = new HashMap<>();
userMap.put("name", "Rabbit");
userMap.put("age", "3");
userMap.put("email", "rabbit@test.com");
redisTemplate.opsForHash().putAll("user:1002", userMap);

使用Hash类型,更新某属性的值时非常方便:

// 更新年龄
redisTemplate.opsForHash().put("user:1001", "age", "30");
int age = Integer.parseInt(redisTemplate.opsForHash().get("user:1001", "age").toString());
log.info("user:1001 age, {}", age);

删除某个属性:

// 删除用户的某个属性
redisTemplate.opsForHash().delete("user:1001", "email");

2、适用场景

Hash类型适合存储多字段对象或需要频繁更新部分字段的数据,包括但不限于以下场景:

1)用户信息存储

存储用户详细信息,如姓名、年龄、邮箱等

2)购物车管理

电商系统中,用Hash存储用户购物车中的商品及其数量

3)配置管理

集中管理应用配置参数,

4)统计字段聚合

用户行为的多维度统计,如点赞数、收藏数等

5)对象缓存

缓存数据库查询结果(如商品详情、订单信息等),减少数据库压力

6)分布式Session存储

在集群环境中,用Hash存储用户会话信息(如登录状态、权限)

3、注意

1)避免将Hash用于字段数量巨大(如百万级)的场景,可能引发性能问题

相关文章:

  • 基于XGBoost的异烟酸生产收率预测:冠军解决方案解析
  • 七大寻址方式
  • ubuntu 系统安装Mysql
  • 【代码安全】spotbugs编写自定义规则(一) 快速开始
  • 【数据可视化艺术·实战篇】视频AI+人流可视化:如何让数据“动”起来?
  • 每日OJ_牛客_ruby和薯条_排序+二分/滑动窗口_C++_Java
  • vue2 el-element中el-select选中值,数据已经改变但选择框中不显示值,需要其他输入框输入值才显示这个选择框才会显示刚才选中的值。
  • C语言中常用的调试宏和函数总结(__LINE__、__FUNCTION__)
  • Swift的学习笔记(一)
  • 学生考勤管理系统(jsp+ssh+mysql5.x)含文档
  • 【清华大学】DeepSeek与AI幻觉
  • AIGC-文生图与图生图
  • Vision Mamba修改为自己的目标检测数据集
  • linux多线(进)程编程——(2)身外化身fork()
  • 概率论与数理统计核心知识点与公式总结(就业版)
  • C++进阶——异常
  • 计算机组成原理-系统总线
  • Hibernate(JPA) 和 MyBatis 的对比
  • Java基础关键_036_Stream
  • 使用Python实现矢量路径的压缩、解压与可视化
  • 内蒙古赤峰市城建集团董事长孙广通拟任旗县区党委书记
  • 以色列总理:以哈谈判内容包括“结束战争的框架”
  • 女子应聘文员被说“太丑”?官方回应:有关部门启动核查处置
  • 陈刚:推动良好政治生态和美好自然生态共生共优相得益彰
  • 广西壮族自治区党委常委会:坚决拥护党中央对蓝天立进行审查调查的决定
  • 俄乌代表团抵达谈判会场