问题描述

想在一个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. 【Luogu3733】[HAOI2017]八纵八横(线性基,线段树分治)

    [Luogu3733][HAOI2017]八纵八横(线性基,线段树分治) 题面 洛谷 题解 看到求异或最大值显然就是线性基了,所以只需要把所有环给找出来丢进线性基里就行了. 然后线性基不资磁撤销?线段 ...

  2. SES 之全局搜索小记

    @2018-12-17 [小记] SES 使用全局搜索时,变量所在的头文件没有被检索出来,选中检索属性中的 Dependencies 就可以了

  3. 老铁,告别postman,用pycharm来调接口,顺便把接口脚本也写了

    最近,一位同事在用postman调涉及到依赖的接口的时候 postman设置了环境变量,但是老是获取不到依赖接口返回的值,至于的啥原因呢,@#¥%……&*()! 其实,用pycharm一样可以 ...

  4. UVALive - 4222

    题目链接:https://vjudge.net/contest/244167#problem/D 题目: For a dance to be proper in the Altered Culture ...

  5. OpenLayers学习笔记(六)— 拖拽叠加层overlayer

    是在官网例子基础上增加的拖拽功能 GitHub:八至 作者:狐狸家的鱼 本文链接:拖拽叠加层overlayer 全部代码 <!DOCTYPE html> <html> < ...

  6. Flask flask_script扩展库

    flask_script 1.安装:进入到虚拟环境中,pip install flask_script 2.flask_script 作用:可以通过命令行的形式来操作Flask,例如通过命令跑一个开发 ...

  7. 美丽的webpack-bundle-analyzer

    webpack-bundle-analyzer -- Webpack 插件和 CLI 实用程序,她可以将打包后的内容束展示为方便交互的直观树状图,让我们知道我们所构建包中真正引入的内容: 我们可以借助 ...

  8. Gym 101911F “Tickets”

    传送门 题意: 给你一个由六位数字组成的门票编码x,并定义F(x) = | 前三位加和 - 后三位加和|: 求出给定的门票编码 x 之前并且 F(i) < F(x) 的 i 的总个数. 题解: ...

  9. poj 2385 Apple Catching(记录结果再利用的动态规划)

    传送门 https://www.cnblogs.com/violet-acmer/p/9852294.html 题意: 有两颗苹果树,在每一时刻只有其中一棵苹果树会掉苹果,而Bessie可以在很短的时 ...

  10. c#的一些快捷键

    ctrl+c+s 外加代码 F12 转到定义 ctrl+F5调试 一些补全命令 svm Main函数的补全命令 prop 属性的补全命令