介绍
有一个接口请求必须使用唯一 ID 进行请求,而该接口所属服务部署了多个。使用 Redistemplate 生成 dubbo 服务全局唯一 key 的时候,报了错误,并且这个错误不是 100% 复现。
提示无法将 value 进行自增,value 不是整数类型。
1 | ERR value is not an integer or out of range |
代码中利用 Redistemplate 生成唯一 ID 使用的方法:
1 | @Autowired |
最终定位问题在 RedisTemplate 序列化 的问题上,程序初始化的时候没有指定 value 的序列化方式,默认序列化的 value 并非整型类型,导致获取自增唯一 ID 异常。
基本配置与使用
先以 SpringBoot 2.2.0 项目为基础,介绍 RedisTemplate 的基础用法
添加依赖
1
2
3
4<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>参数配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18# Redis数据库索引(默认为0)
spring.redis.database=0
# Redis服务器地址
spring.redis.host=localhost
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器连接密码(默认为空)
spring.redis.password=
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.jedis.pool.max-active=8
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.jedis.pool.max-wait=-1
# 连接池中的最大空闲连接
spring.redis.jedis.pool.max-idle=8
# 连接池中的最小空闲连接
spring.redis.jedis.pool.min-idle=0
# 连接超时时间(毫秒)
spring.redis.timeout=20单元测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21package com.example.demo;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.Assert;
@SpringBootTest
class DemoApplicationTests {
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Test
public void test(){
stringRedisTemplate.opsForValue().set("aaa","111");
Assert.state("111".equals(stringRedisTemplate.opsForValue().get("aaa")),"not equals");
}
}
序列化方式
RedisTemplate 可以指定 key、value 的序列化方式,默认使用 JdkSerializationRedisSerializer。如果不指定键值对的序列化方式,可能会影响程序的正常运行。
RedisTemplate 可指定的序列化方式:
JdkSerializationRedisSerializer,JDK 提供的序列化功能,需要序列化的类需要实现 Serializable 接口
StringRedisSerializer,默认使用 UTF-8 编码格式将 String 转为字节数组
Jackson2JsonRedisSerializer,使用 Jackson 将对象序列化为 JSON,初始化的时候指定对象类型
GenericToStringSerializer,使用带类型转换的方式,将 String 转为字节数组
GenericJackson2JsonRedisSerializer,使用带类型转换的方式,将对象转为 JSON
OxmSerializer,XML 序列化
ByteArrayRedisSerializer,将 Byte 数组原样保存
序列化实例
JdkSerializationRedisSerializer,默认情况下,key,value 都是以二进制形式保存,保存的键值对不再是程序中定义好的类型。
默认情况带有很多转义前缀
1 | @Test |
- StringRedisSerializer
- key、value 必须是 String 类型,否则会抛出 ClassCastException
1 | StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); |
1 | 输出字符串 |
- Jackson2JsonRedisSerializer,实体类不重写 toString 也能够获取对应属性信息
1 | @Test |
总结
使用 Redistemplate 时候,注意键值对的序列化方式
对象序列化建议使用 Jackson2JsonRedisSerializer,String 类型字符串使用 StringRedisSerializer