zoukankan      html  css  js  c++  java
  • Spring boot 使用多个RedisTemplate

    问题描述

    想在一个JAVA Class 向同一个Redis实例的不同 dbindex 写入数据,非常类似于StackOverflowe上的[How can select dbIndex when I use RedisTemplate in Spring-Data-Redis?。在这篇文章中描述了如何使用Spring boot访问Redis,在创建JedisConnectionFactory的时候指定dbindex:

    JedisConnectionFactory factory = new JedisConnectionFactory();
    ...
    factory.setDatabase(databaseId);//set dbindex
    

    因此,大概思路是配置2个RedisTemplate,其中一个RedisTemplate负责访问dbindex=1的数据库;另一个RedisTemplate负责访问dbindex=3的数据库。

    根据这篇文章,因此通过 @Bean(name=) 生成多个RedisTemplate。但是由于生成RedisTemplate需要传入JedisConnectionFactory实例,而我们是在JedisConnectionFactory中指定了访问Redis的哪个数据库(dbindex)。因此,就在创建JedisConnectionFactory实例的时候,使用 @Scope(scopeName = "prototype") 注解,这样的话Jedis连接工厂就不再是单例模式了。因此,就有两个JedisConnectionFactory实例,每个实例通过jedisConnectionFactory.setDatabase()设置不同的dbindex。这种方式可能非常愚蠢,会引起严重的性能问题。

    下面,来看看具体是怎么配置的:

        @Scope(scopeName = "prototype")
        public JedisConnectionFactory jedisConnectionFactory() {
    
    	JedisPoolConfig config = getRedisConfig();
    	JedisConnectionFactory factory = new JedisConnectionFactory(config);
    	factory.setUsePool(true);
    	factory.setHostName(host);
    	factory.setPort(port);
    	return factory;
        }
    

    每调用一次jedisConnectionFactory() 返回一个新的JedisConnectionFactory实例。

    然后定义2个RedisTemplate Bean,jedisConnectionFactory.setDatabase() 方法分别设置不同的dbindex

     import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Scope;
    import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.data.redis.serializer.StringRedisSerializer;
    import redis.clients.jedis.JedisPoolConfig;
    import java.util.Map;
    
    /**
     * Created by Administrator on 2018/4/9.
     */
    
    @Configuration
    public class LoginMacRedisConfig {
    
        private static final Logger logger = LoggerFactory.getLogger(LoginMacRedisConfig.class);
        @Value("1")
        private int logmacDatabaseId;
    
        @Value("3")
        private int mobmaskDatabaseId;
    
    
        @Bean
        public JedisPoolConfig getRedisConfig() {
    	JedisPoolConfig config = new JedisPoolConfig();
    	config.setMaxIdle(8);
    	config.setMinIdle(0);
    	return config;
        }
    
        @Scope(scopeName = "prototype")
        public JedisConnectionFactory jedisConnectionFactory() {
    
    	JedisPoolConfig config = getRedisConfig();
    	JedisConnectionFactory factory = new JedisConnectionFactory(config);
    	factory.setUsePool(true);
    	factory.setHostName(host);
    	factory.setPort(port);
    	return factory;
        }
    
        @Bean(name = "login_mac")
        public RedisTemplate<String, Map<String, String>> logmacRedisTemplate() {
    	final RedisTemplate<String, Map<String, String>> template = new RedisTemplate<>();
    
    	JedisConnectionFactory jedisConnectionFactory = jedisConnectionFactory();
    	jedisConnectionFactory.setDatabase(logmacDatabaseId);
    	template.setConnectionFactory(jedisConnectionFactory);
    	logger.info("host:{}, port:{}, database:{}", jedisConnectionFactory.getHostName(),jedisConnectionFactory.getPort(), jedisConnectionFactory.getDatabase());
    
    	StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
    	template.setKeySerializer(stringRedisSerializer);
    	template.setHashKeySerializer(stringRedisSerializer);
    	template.setHashValueSerializer(stringRedisSerializer);
    	return template;
        }
    
        @Bean(name = "mobile_mask")
        public RedisTemplate<String, Map<String, String>> mobileMaskRedisTemplate() {
    	final RedisTemplate<String, Map<String, String>> template = new RedisTemplate<>();
    	JedisConnectionFactory jedisConnectionFactory = jedisConnectionFactory();
    	jedisConnectionFactory.setDatabase(mobmaskDatabaseId);
    	template.setConnectionFactory(jedisConnectionFactory);
    	logger.info("host:{}, port:{}, database:{}", jedisConnectionFactory.getHostName(),jedisConnectionFactory.getPort(), jedisConnectionFactory.getDatabase());
    	StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
    	template.setKeySerializer(stringRedisSerializer);
    	template.setHashKeySerializer(stringRedisSerializer);
    	template.setHashValueSerializer(stringRedisSerializer);
    	return template;
        }
    }
    
    

    最后,再写一个Service类,就可以同时注入这两个RedisTemplate,操作同一个Redis服务器上的不同的dbindex了。

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.data.redis.core.HashOperations;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.stereotype.Service;
    
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * Created by Administrator on 2018/4/10.
     */
    @Service
    public class RedisTestService {
        @Autowired
        @Qualifier("login_mac")
        private RedisTemplate<String, Map<String, String>> template1;
    
        @Autowired
        @Qualifier("mobile_mask")
        private RedisTemplate<String, Map<String, String>> template2;
    
        public void write2Redis() {
    	HashOperations<String, String, String> hashOperations = template1.opsForHash();
    	Map<String, String> values = new HashMap<>();
    	values.put("dbindex", "1");
    	hashOperations.putAll("123", values);
    
    	template2.opsForHash().put("123", "dbindex", "3");
        }
    }
    

    Application.java 启动类

    @SpringBootApplication
    public class Application implements CommandLineRunner{
        @Autowired
        private RedisTestService redisTestService;
        public static void main(String[] args) {
    	SpringApplication.run(Application.class, args);
        }
        @Override
        public void run(String... strings) throws Exception {
    	redisTestService.write2Redis();
        }
    }
    

    在redisTestService对象中:有两个RedisTemplate实例:

    两个RedisTemplate实例分别封装了两个JedisConnectionFactory:

    调试结果下:

    2018-04-10 20:18:34.754  INFO 13512 --- [           main] c.y.t.c.redis.LoginMacRedisConfig        : host:192.168.107.253, port:6379, database:1
    
    2018-04-10 20:19:06.972  INFO 13512 --- [           main] c.y.t.c.redis.LoginMacRedisConfig        : host:192.168.107.253, port:6379, database:3
    

    最终查看写入Redis结果,可以看出:dbindex 1 和 dbindex 3 都分别成功写入了数据。

    redis 192.168.107.253:6379> SELECT 1
    OK
    redis 192.168.107.253:6379[1]> KEYS *
    1) "123"
    redis 192.168.107.253:6379[1]> HGET 123 dbindex
    "1"
    redis 192.168.107.253:6379[1]> SELECT 3
    OK
    redis 192.168.107.253:6379[3]> KEYS *
    1) "123"
    redis 192.168.107.253:6379[3]> HGET 123 dbindex
    "3"
    

    额外补充

    其实要在同一个应用中访问不同的dbindex,一种方式是使用JedisPool,JedisPool创建Jedis,然后调用select方法选择dbindex。具体实现可参考这篇文章。但这样的话,就不能使用RedisTemplate的各种方便的接口读写Redis了。

        @Bean
        public JedisPool redisPoolFactory() {
            JedisPool jedisPool = new JedisPool(jedisPoolConfig(), host, port);
            Jedis jedis = jedisPool.getResource();
            jedis.select(3);
            return jedisPool;
        }
    

    其实是可以像说的:通过RedisConnectionCommand的 select 方法来选择dbindex的,但是还是同样的问题,用不了RedisTemplate。

    RedisConnection redisConnection = redisTemplate.getConnectionFactory().getConnection();
    DefaultStringRedisConnection stringRedisConnection = new   DefaultStringRedisConnection(redisConnection);
    stringRedisConnection.select(2);
    stringRedisConnection.set("test", "test");
    

    另外这里也有一篇Spring Boot Redis多实例配置,也可以参考一下。Spring Boot 兼Redis新手,只能这样了。

    原文:http://www.cnblogs.com/hapjin/p/8783084.html

  • 相关阅读:
    My97日期控件 My97 DatePicker 4.0 Prerelease 发布
    My97DatePicker提问需知,仔细阅读可以在最快的时间收到问题反馈
    My97日期控件3.0不支持IE8,4.2以上已经支持,强烈建议还在使用3.x的用户换成最新版
    My97日期控件 My97 DatePicker 4.0 Beta4 发布(候选版本)
    My97日期控件 My97 DatePicker 4.0 正式版
    坚持打造最好的日期控件,My97 DatePicker 4.7 Release
    [PYTHON] 格式化输出的几种方法 HONG
    数组反转函数 blog_zss小帅
    fastadmin 按钮状态 blog_zss小帅
    fastadmin 固定列表字段 blog_zss小帅
  • 原文地址:https://www.cnblogs.com/hapjin/p/8783084.html
Copyright © 2011-2022 走看看