Redis 多数据源配置以及序列化器的使用

Redis 多数据源配置以及序列化器的使用

多数据源配置(非集群)

pom

    <!--redis start-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>io.lettuce</groupId>
                    <artifactId>lettuce-core</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
        </dependency>

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>
        <!--redis end-->

配置文件

  redis:
    open: true  # 是否开启redis缓存  true开启   false关闭
    database: 0
    
    host: 
    port: 6379
    password:      # 密码(默认为空)
    timeout: 60000  # 连接超时时长(毫秒)
    jedis:
      pool:
        max-active: 200  # 连接池最大连接数(使用负值表示没有限制)
        max-wait: 2000     # 连接池最大阻塞等待时间(使用负值表示没有限制)
        max-idle: 20      # 连接池中的最大空闲连接
        min-idle: 5       # 连接池中的最小空闲连接
        max-total: 1024    #最大链接数

  redis2:
    host: 
    database: 0
    port: 6379
    password: 
    jedis:
      pool:
        max-active: 200  # 连接池最大连接数(使用负值表示没有限制)
        max-wait: 2000     # 连接池最大阻塞等待时间(使用负值表示没有限制)
        max-idle: 20      # 连接池中的最大空闲连接
        min-idle: 5       # 连接池中的最小空闲连接

配置类

package com.ieslab.bigscreendatasvr.config;

import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonRedisSerializer;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
import com.ieslab.common.util.StringUtils;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
import org.springframework.data.redis.core.*;
import org.springframework.data.redis.serializer.*;
import org.springframework.util.ObjectUtils;
import redis.clients.jedis.JedisPoolConfig;

import java.time.Duration;

/**
 * Redis配置
 *
 * @author
 * @email sunlightcs@gmail.com
 * @date 2017-07-70 19:22
 */
@Configuration
public class RedisConfig {
//数据源1
    @Value("${spring.redis.host}")
    private String processHost; 
    @Value("${spring.redis.port}")
    private Integer processPort;
    @Value("${spring.redis.password}")
    private String processPassword;
    @Value("${spring.redis.database}")
    private Integer processDatabase;
    
//数据源2
    @Value("${spring.redis2.host}")
    private String psgesccHost;
    @Value("${spring.redis2.port}")
    private Integer psgesccPort;
    @Value("${spring.redis2.password}")
    private String psgesccPassword;
    @Value("${spring.redis2.database}")
    private Integer psgesccDatabase;

    @Value("${spring.redis.timeout}")
    private Long timeout;
    @Value("${spring.redis.jedis.pool.max-active}")
    private Integer maxActive;
    @Value("${spring.redis.jedis.pool.max-wait}")
    private Integer maxWait;
    @Value("${spring.redis.jedis.pool.max-idle}")
    private Integer maxIdle;
    @Value("${spring.redis.jedis.pool.min-idle}")
    private Integer minIdle;
    @Value("${spring.redis.jedis.pool.max-total}")
    private Integer maxTotal;

    //配置工厂
    public RedisConnectionFactory connectionFactory(String host, int port, String password, int maxIdle, int minIdle,
                                                    int maxTotal, long maxWaitMillis, int index) {
        JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory();
        jedisConnectionFactory.setHostName(host);
        jedisConnectionFactory.setPort(port);

        if (!StringUtils.isEmpty(password)) {
            jedisConnectionFactory.setPassword(password);
        }

        if (index != 0) {
            jedisConnectionFactory.setDatabase(index);
        }

        jedisConnectionFactory.setPoolConfig(poolConfig(maxIdle, minIdle, maxTotal, maxWaitMillis, false));
        jedisConnectionFactory.afterPropertiesSet();
        return jedisConnectionFactory;
    }

    //连接池配置
    public JedisPoolConfig poolConfig(int maxIdle, int minIdle, int maxTotal, long maxWaitMillis, boolean testOnBorrow) {
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        poolConfig.setMaxIdle(maxIdle);
        poolConfig.setMinIdle(minIdle);
        poolConfig.setMaxTotal(maxTotal);
        poolConfig.setMaxWaitMillis(maxWaitMillis);
        poolConfig.setTestOnBorrow(testOnBorrow);
        return poolConfig;
    }

    @Bean(name = "stringRedisProcessTemplate")
    public StringRedisTemplate stringRedisProcessTemplate() {
        StringRedisTemplate template = new StringRedisTemplate();
        template.setConnectionFactory(
                connectionFactory(processHost, processPort, processPassword, maxIdle, minIdle, maxTotal, maxWait, processDatabase));
        //FastJsonRedisSerializer<Object> serializer = new FastJsonRedisSerializer<>(Object.class);
        FastJsonConfig fastJsonConfig = new FastJsonConfig();
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

        template.setKeySerializer(stringRedisSerializer);
        template.setValueSerializer(stringRedisSerializer);
        template.setHashKeySerializer(stringRedisSerializer);
        template.setHashValueSerializer(stringRedisSerializer);
        //template.afterPropertiesSet();
        return template;
    }

    @Bean(name = "redisProcessTemplate")
    public RedisTemplate<String, Object> redisProcessTemplate() {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(
                connectionFactory(processHost, processPort, processPassword, maxIdle, minIdle, maxTotal, maxWait, processDatabase));

        FastJsonRedisSerializer<Object> serializer = new FastJsonRedisSerializer<>(Object.class);
        FastJsonConfig fastJsonConfig = new FastJsonConfig();


        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(serializer);
        template.setHashKeySerializer(new StringRedisSerializer());
        template.setHashValueSerializer(serializer);
        template.afterPropertiesSet();
        return template;
    }

    @Bean(name = "stringRedisPsgesccTemplate")
    public StringRedisTemplate stringRedisPsgesccTemplate() {
        StringRedisTemplate template = new StringRedisTemplate();
        template.setConnectionFactory(
                connectionFactory(psgesccHost, psgesccPort, psgesccPassword, maxIdle, minIdle, maxTotal, maxWait, psgesccDatabase));
//        FastJsonRedisSerializer<Object> serializer = new FastJsonRedisSerializer<>(Object.class);
        FastJsonConfig fastJsonConfig = new FastJsonConfig();
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

        template.setKeySerializer(stringRedisSerializer);
        template.setValueSerializer(stringRedisSerializer);
        template.setHashKeySerializer(stringRedisSerializer);
        template.setHashValueSerializer(stringRedisSerializer);
        //template.afterPropertiesSet();
        return template;
    }

    @Bean(name = "redisPsgesccTemplate")
    public RedisTemplate<String, Object> redisPsgesccTemplate() {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(
                connectionFactory(psgesccHost, psgesccPort, psgesccPassword, maxIdle, minIdle, maxTotal, maxWait, psgesccDatabase));
//        FastJsonRedisSerializer<Object> serializer = new FastJsonRedisSerializer<>(Object.class);
        FastJsonConfig fastJsonConfig = new FastJsonConfig();
        StringRedisSerializer serializer = new StringRedisSerializer();
        template.setKeySerializer(serializer);
        template.setValueSerializer(serializer);
        template.setHashKeySerializer(serializer);
        template.setHashValueSerializer(serializer);

        return template;
    }


}

踩坑

数据源1的数据库存储的是json格式的 数据 数据源2 是String格式的 所以在序列化的时候出现了一些问题

首先说一下redis的序列化器

  • GenericToStringSerializer: 可以将任何对象泛化为字符串并序列化
  • Jackson2JsonRedisSerializer: 跟JacksonJsonRedisSerializer实际上是一样的
  • JacksonJsonRedisSerializer: 序列化object对象为json字符串
  • JdkSerializationRedisSerializer: 序列化java对象
  • StringRedisSerializer: 简单的字符串序列化

直接上异常 1

java.io.StreamCorruptedException: invalid stream header

相关代码(此时操作的是数据源2)

            List<String> aclineloadfactor = (List<String>)redisUtil.
            hGetAllByPipe("yourkeys:*");
 /**
     * 借助管道,实现Hash模糊匹配读取
     *
     * @param keyPattern  key模糊匹配
     * @return
     */
    public Object hGetAllByPipe(String keyPattern){
        Set<String> keys = stringRedisTemplate.keys(keyPattern);
        List<Object> list = redisTemplate2.executePipelined(new RedisCallback<Object>() {
            @Nullable
            @Override
            public Object doInRedis(RedisConnection connection) throws DataAccessException {
                connection.openPipeline();
                for (String key : keys) {
                    connection.hashCommands().hGetAll(key.getBytes());
                }
                return null;
            }
        });
        ArrayList<String> strings = new ArrayList<>();
        for (int i = 0; i < list.size(); i++) {
            Gson gson = new GsonBuilder().enableComplexMapKeySerialization().create();
            String jsonStr=gson.toJson(list.get(i));
            strings.add(jsonStr);
        }
        return strings;
    }

此时笔者用的是JdkSerializationRedisSerializer 产生这异常的原因是实体类需要实现Serializable接口 但是我要获取的是 List 不存在实体类的问题 于是换了 StringRedisSerializer 数据源2数据获取成功

异常2 直接上原始异常(操作数据源1)

[ERROR] 2021-08-05 18:09:30 [ TaskUtils$LoggingErrorHandler] : Unexpected error occurred in scheduled task
org.springframework.data.redis.serializer.SerializationException: Could not read JSON: Unexpected token (START_OBJECT), expected START_ARRAY: need JSON Array to contain As.WRAPPER_ARRAY type information for class java.lang.Object
 at [Source: (byte[])"{
"plan":["062dc47fb3ba4aca94f39f81a160ac08","0ae67f78c5074f0384af5fcc219f103f","13724ab9f7264a8bb0e54f2061fb3ede","2f393db795964a9fb02ab53e7aaac8a7","368fdb4c47ea499590ba70358cad3a1d","441fd9296c734ee79365fef6c66f2912","45a7a8e573d34e4a85f6fc8fb1d4a549","467a0f8064a3455b860d1ba1ec099f75","53fd62c1754e42bf8bb4ccf1ff9f46f6","59ea6ae5bd214896800449216d57aa70","606f0d81275b4c19b5c9d378c26d802c","8acbd09819464669800c05c28dc9049e","d8fb34d7a82940adb3ac5fb54c25cdbe","e942003839a649628839937c9c5dcaba","[truncated 1053 bytes]; line: 1, column: 1]; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Unexpected token (START_OBJECT), expected START_ARRAY: need JSON Array to contain As.WRAPPER_ARRAY type information for class java.lang.Object
 at [Source: (byte[])"{
"plan":["062dc47fb3ba4aca94f39f81a160ac08","0ae67f78c5074f0384af5fcc219f103f","13724ab9f7264a8bb0e54f2061fb3ede","2f393db795964a9fb02ab53e7aaac8a7","368fdb4c47ea499590ba70358cad3a1d","441fd9296c734ee79365fef6c66f2912","45a7a8e573d34e4a85f6fc8fb1d4a549","467a0f8064a3455b860d1ba1ec099f75","53fd62c1754e42bf8bb4ccf1ff9f46f6","59ea6ae5bd214896800449216d57aa70","606f0d81275b4c19b5c9d378c26d802c","8acbd09819464669800c05c28dc9049e","d8fb34d7a82940adb3ac5fb54c25cdbe","e942003839a649628839937c9c5dcaba","[truncated 1053 bytes]; line: 1, column: 1]
	at org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer.deserialize(Jackson2JsonRedisSerializer.java:75)
	at org.springframework.data.redis.core.AbstractOperations.deserializeValue(AbstractOperations.java:335)
	at org.springframework.data.redis.core.AbstractOperations$ValueDeserializingRedisCallback.doInRedis(AbstractOperations.java:61)
	at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:228)
	at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:188)
	at org.springframework.data.redis.core.AbstractOperations.execute(AbstractOperations.java:96)
	at org.springframework.data.redis.core.DefaultValueOperations.get(DefaultValueOperations.java:53)
	at com.ieslab.utils.RedisUtils.get(RedisUtils.java:63)
	at com.ieslab.utils.RedisUtils.get(RedisUtils.java:71)
	at com.ieslab.bigscreendatasvr.datasvr.data.JxQlcDataCache.checkOverAllData(JxQlcDataCache.java:203)
	at com.ieslab.bigscreendatasvr.datasvr.data.JxQlcDataCache.statisticsQlcData(JxQlcDataCache.java:120)
	at com.ieslab.bigscreendatasvr.datasvr.service.impl.CyclStatisticsProcessImpl.calStatisData(CyclStatisticsProcessImpl.java:44)
	at com.ieslab.bigscreendatasvr.config.TimerConfig.calStatsData(TimerConfig.java:26)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:84)
	at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
	at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:93)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
	at java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:266)
	at java.util.concurrent.FutureTask.run(FutureTask.java)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)
Caused by: com.fasterxml.jackson.databind.exc.MismatchedInputException: Unexpected token (START_OBJECT), expected START_ARRAY: need JSON Array to contain As.WRAPPER_ARRAY type information for class java.lang.Object
 at [Source: (byte[])"{
"plan":["062dc47fb3ba4aca94f39f81a160ac08","0ae67f78c5074f0384af5fcc219f103f","13724ab9f7264a8bb0e54f2061fb3ede","2f393db795964a9fb02ab53e7aaac8a7","368fdb4c47ea499590ba70358cad3a1d","441fd9296c734ee79365fef6c66f2912","45a7a8e573d34e4a85f6fc8fb1d4a549","467a0f8064a3455b860d1ba1ec099f75","53fd62c1754e42bf8bb4ccf1ff9f46f6","59ea6ae5bd214896800449216d57aa70","606f0d81275b4c19b5c9d378c26d802c","8acbd09819464669800c05c28dc9049e","d8fb34d7a82940adb3ac5fb54c25cdbe","e942003839a649628839937c9c5dcaba","[truncated 1053 bytes]; line: 1, column: 1]
	at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:59)
	at com.fasterxml.jackson.databind.DeserializationContext.wrongTokenException(DeserializationContext.java:1627)
	at com.fasterxml.jackson.databind.DeserializationContext.reportWrongTokenException(DeserializationContext.java:1377)
	at com.fasterxml.jackson.databind.jsontype.impl.AsArrayTypeDeserializer._locateTypeId(AsArrayTypeDeserializer.java:141)
	at com.fasterxml.jackson.databind.jsontype.impl.AsArrayTypeDeserializer._deserialize(AsArrayTypeDeserializer.java:96)
	at com.fasterxml.jackson.databind.jsontype.impl.AsArrayTypeDeserializer.deserializeTypedFromAny(AsArrayTypeDeserializer.java:71)
	at com.fasterxml.jackson.databind.deser.std.UntypedObjectDeserializer$Vanilla.deserializeWithType(UntypedObjectDeserializer.java:712)
	at com.fasterxml.jackson.databind.deser.impl.TypeWrappedDeserializer.deserialize(TypeWrappedDeserializer.java:68)
	at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4218)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3318)
	at org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer.deserialize(Jackson2JsonRedisSerializer.java:73)
	... 27 more

此时笔者用的是Jackson2JsonRedisSerializer 换成 FastJsonRedisSerializer 就解决了 但是具体原因未知 望熟悉这个的大佬指点一下

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值