问题描述

想在一个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

Spring boot 使用多个RedisTemplate的更多相关文章

  1. 【spring boot】spring boot 基于redis pipeline 管道,批量操作redis命令

    spring boot 2.x 使用RedisTemplate 操作 =================================== 1.pom.xml <!--spring2.0集成r ...

  2. SpringBoot(十一): Spring Boot集成Redis

    1.在 pom.xml 中配置相关的 jar 依赖: <!-- 加载 spring boot redis 包 --> <dependency> <groupId>o ...

  3. spring boot整合reids 然后实现缓存分页(方法之一) 以及RedisTemplate存到reids 里面get 就消失的坑

    业务需求 首页 实现缓存分页 spring boot 整合redis   (我的是2.0.3版本的) 在pom 文件写上依赖包即可 <dependency><!--依赖包--> ...

  4. 曹工说Spring Boot源码(20)-- 码网灰灰,疏而不漏,如何记录Spring RedisTemplate每次操作日志

    写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...

  5. 玩转spring boot——结合redis

    一.准备工作 下载redis的windows版zip包:https://github.com/MSOpenTech/redis/releases 运行redis-server.exe程序 出现黑色窗口 ...

  6. spring boot(三):Spring Boot中Redis的使用

    spring boot对常用的数据库支持外,对nosql 数据库也进行了封装自动化. redis介绍 Redis是目前业界使用最广泛的内存数据存储.相比memcached,Redis支持更丰富的数据结 ...

  7. Spring Boot简介

    Spring Boot简介 Spring Boot是为了简化Spring开发而生,从Spring 3.x开始,Spring社区的发展方向就是弱化xml配置文件而加大注解的戏份.最近召开的SpringO ...

  8. Spring Boot 学习笔记--整合Redis

    1.新建Spring Boot项目 添加spring-boot-starter-data-redis依赖 <dependency> <groupId>org.springfra ...

  9. Spring Boot 整合 Redis 实现缓存操作

    摘要: 原创出处 www.bysocket.com 「泥瓦匠BYSocket 」欢迎转载,保留摘要,谢谢!   『 产品没有价值,开发团队再优秀也无济于事 – <启示录> 』   本文提纲 ...

随机推荐

  1. Android热点回顾第一期

    本文由 ImportNew - 陈强 翻译自 androidweekly.如需转载本文,请先参见文章末尾处的转载要求. Importnew注:欢迎Android爱好者参与翻译文中提及的教程,请私信联系 ...

  2. 深入浅出QOS详解(转)

    QOS学习笔记 (工作时间之余,总结了这些,累的食指快脱节了,现在还在恢复中,为的就是让文章质量再提高点,希望对大家有帮助!文章太长,为方便,我附件上文章原文.) QOS,服务质量.顾名思义,就是为了 ...

  3. gulp与webpack的区别

    gulp  gulp强调的是前端开发的工作流程,我们可以通过配置一系列的task,定义task处理的事务(例如文件压缩合并.雪碧图.启动server.版本控制等),然后定义执行顺序,来让gulp执行这 ...

  4. electron打包之真的恶心

    用electron-packager进行打包 这个模块的文档写的真的垃圾 1.先看看首页的参数介绍 就是说必选参数就是源码路径和app名字和--platform还有--arch咯,而且源码路径也没说是 ...

  5. optimize PHP-FPM优化

    php-fpm进程pidpids=$(ps aux | grep ${process} | grep -v "grep" | awk '{print $2}') php-fpm 关 ...

  6. Balanced Sequence HDU - 6299(杭电多校1 B)

    题目说要n个字符串串内随意组合以后将这些串放在一起,然后求最长的括号匹配的长度,并不要求是连续的 因为不需要是连续的,所以可以先把已经匹配好的括号加入到答案里面去,先把这些删掉,以为并不影响结果,然后 ...

  7. rxjs学习笔记

    api List Rx.Observable.amb(...args) -存在竞争关系,amb里的流只能触发一个,并且忽略其他未处理的流. eq: <body> <input id= ...

  8. redux源码解析-redux的架构

    redux很小的一个框架,是从flux演变过来的,尽管只有775行,但是它的功能很重要.react要应用于生成环境必须要用flux或者redux,redux是flux的进化产物,优于flux. 而且r ...

  9. APP reset.css

    html { box-sizing: border-box; } * { user-select: none; -webkit-tap-highlight-color: rgba(255,255,25 ...

  10. ElasticSearch6.3.2------查询

    进入Kibana的控制台:http://localhost:5601/app/kibana#/dev_tools/ 先放一些测试数据进去,不想一条一条,就用bulk 注意格式 正确格式: 解释:ES期 ...