问题描述

想在一个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. 滚动ListView时图像顺序混乱

    本文选自StackOverflow(简称:SOF)精选问答汇总系列文章之一,本系列文章将为读者分享国外最优质的精彩问与答,供读者学习和了解国外最新技术.本文将为读者讲解滚动ListView时图像顺序混 ...

  2. 「HNOI2016」树 解题报告

    「HNOI2016」树 事毒瘤题... 我一开始以为每次把大树的子树再接给大树,然后死活不知道咋做,心想怕不是个神仙题哦 然后看题解后才发现是把模板树的子树给大树,虽然思维上难度没啥了,但是还是很难写 ...

  3. poj 3080 Blue Jeans (暴力枚举子串+kmp)

    Description The Genographic Project is a research partnership between IBM and The National Geographi ...

  4. Oracle数据库中遇到的坑

    最近在帮别人忙写程序,用的是Oracle数据库,写一篇文章来说说在Oracle中遇到的一些坑: 1. PL/SQL develop的坑: 由于在这里工作环境是内网完全,无奈只能使用PL/SQL 工具, ...

  5. VMware加载vmdk文件

    VMware软件文件菜单选择---映射虚拟磁盘选项,如图1所示

  6. bcftools或vcftools提取指定区段的vcf文件(extract specified position )

    下载安装bcftools 见如下命令: bcftools filter 1000Genomes.vcf.gz --regions 9:4700000-4800000 > 4700000-4800 ...

  7. 构造代码块、this关键字、静态变量、静态代码块、主函数

    一.构造代码块: 作用:给对象进行初始化. 特点:对象一经运行就执行(与变量声明时赋初值同级别,此处注意 非法前向引用) 优先于构造函数的执行. 与构造函数的区别: 构造代码块是给所有对象统一初始化. ...

  8. hystrix实战总结;

    HystrixCircuitBreaker 有三种状态 : 断路器默认是20个请求失败才打开短路器,可以进行配置: CLOSED :关闭 OPEN :打开 HALF_OPEN :半开 1.接口正确,接 ...

  9. 以太网 ------ Auto-Negotiation(自动协商)

    说起自动协商(Auto-negotiation),我想很多人都不会陌生.当你把你PC机器上的网卡通过一段双绞线连接到某个交换机的某个端口的时候,如果你的网卡和交换机都支持自动协商功能的话,一件有趣的事 ...

  10. qml: C++调用qml函数

    C++调用qml函数,是通过下面的函数实现的: bool QMetaObject::invokeMethod(QObject *obj, const char *member, Qt::Connect ...