Springboot RedisマルチDbスイッチングソリューション
Springboot RedisマルチDbスイッチングソリューション
1.問題の説明2.解決構想3.問題を解決する使用方法
1.問題の説明
1つのニーズは、1つのコンポーネントがredisに接続する必要があり、複数のDBの切り替えをサポートする必要があり、シーケンス化と逆シーケンスの管理が必要であり、従来のコードに影響を与えることなく、SPI形式のアクセスをサポートすることができる.
2.解決の考え方 1.複数のDBをサポートする必要がある場合、DBを切り替える際に他のスレッドに影響を与えることができず、結果として1つのスレッドが接続プールで対応するDBリンクを取得し、操作が完了するとリンクをスレッドプールに戻す. 2.このように実装には、1つのMap構造を用いるスレッドとdbIndexとの関係を記憶すべきである. 3.リンクプール を独自に実装 4.代価が大きすぎる 5.考え方を変えて複数のRedisTemplateを実現するが、RedisTemplateはリンクそのものを持たず、Factoryを1つしか持たない. 6.複数のFactoryを実現する、各Factoryに異なるdbIndexを対応させる. 7.淦 3.問題解決
Enable注記の宣言
ImportでBeanに注入
使用2.X元のLettuceリンクプールを取り出し、その中のプロファイルを取り出します.
RedisDbsTemplate Beanを生成し、小さなRedisTemplate指定名をBeanFactoryに注入します.
シーケンス化管理クラスの宣言
4.使用方法
1.問題の説明2.解決構想3.問題を解決する使用方法
1.問題の説明
1つのニーズは、1つのコンポーネントがredisに接続する必要があり、複数のDBの切り替えをサポートする必要があり、シーケンス化と逆シーケンスの管理が必要であり、従来のコードに影響を与えることなく、SPI形式のアクセスをサポートすることができる.
2.解決の考え方
Enable注記の宣言
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Import({RedisBeanAutoConfig.class})
public @interface EnableRedisDbs {
}
ImportでBeanに注入
@Slf4j
@Component
public class RedisBeanAutoConfig {
@Autowired
private RedisTemplate redisTemplate;
@Bean
@ConditionalOnMissingBean(RedisSerializerManager.class)
public RedisSerializerManager getRedisSerializerManager(){
return new RedisSerializerManager();
}
@Bean
public RedisDbsTemplate redisDbsEntity(Environment environment, RedisSerializerManager redisSerializerManager, ApplicationContext applicationContext){
LettuceConnectionFactory connectionFactory = (LettuceConnectionFactory) redisTemplate.getConnectionFactory();
return new RedisDbsTemplate(environment, connectionFactory,redisSerializerManager,applicationContext);
}
}
使用2.X元のLettuceリンクプールを取り出し、その中のプロファイルを取り出します.
@Slf4j
public class RedisDbsTemplate {
private final static Map<Integer, RedisTemplate> redisTemplateMap = new HashMap<Integer, RedisTemplate>();
private Environment environment;
private LettuceConnectionFactory connectionFactory;
private RedisSerializerManager redisSerializerManager;
private DefaultListableBeanFactory beanFactory;
public RedisDbsTemplate(Environment environment, LettuceConnectionFactory connectionFactory, RedisSerializerManager redisSerializerManager, ApplicationContext applicationContext){
this.environment=environment;
this.connectionFactory=connectionFactory;
this.redisSerializerManager=redisSerializerManager;
this.beanFactory = (DefaultListableBeanFactory) applicationContext.getAutowireCapableBeanFactory();
init();
}
private void init() {
String property = environment.getProperty("spring.redis.databases");
String beanPrefix = environment.getProperty("spring.redis.beanPrefix","redis_db_");
if (StringUtils.isEmpty(property)) {
log.warn("'spring.redis.databases' No settings");
return;
}
String[] dbs = property.split(",");
for (String db : dbs) {
int dbIndex = NumberUtils.toInt(db);
RedisTemplateBuilder redisTemplateBuilder = new RedisTemplateBuilder(dbIndex, connectionFactory,redisSerializerManager);
RedisTemplate redisTemplate = redisTemplateBuilder.builder();
redisTemplateMap.put(dbIndex,redisTemplate);
// Spring BeanFactory
this.beanFactory.registerSingleton(beanPrefix+db,redisTemplate);
}
}
public RedisTemplate getRedisTemplate(int i){
return redisTemplateMap.get(i);
}
}
RedisDbsTemplate Beanを生成し、小さなRedisTemplate指定名をBeanFactoryに注入します.
public class RedisTemplateBuilder {
private int dbIndex;
private LettuceConnectionFactory connectionFactory;
private RedisSerializerManager.RedisSerializerEntity redisSerializerEntity= RedisSerializerManager.getDefKeyValueSerializer();
public RedisTemplateBuilder(int dbIndex, LettuceConnectionFactory connectionFactory, RedisSerializerManager redisSerializerManager) {
this.dbIndex = dbIndex;
this.connectionFactory = connectionFactory;
RedisSerializerManager.RedisSerializerEntity redisSerializerEntity = redisSerializerManager.get(dbIndex);
if (redisSerializerEntity !=null) {
this.redisSerializerEntity= redisSerializerEntity;
}
}
public RedisTemplate builder() {
RedisTemplate<Serializable, Object> redisTemplate = new RedisTemplate<Serializable, Object>();
RedisConnectionFactory factory = this.getFactory(dbIndex);
redisTemplate.setConnectionFactory(factory);
redisTemplate.setKeySerializer(redisSerializerEntity.getKeySerializer());
redisTemplate.setValueSerializer(redisSerializerEntity.getValueSerializer());
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
private RedisConnectionFactory getFactory(int i) {
RedisStandaloneConfiguration standaloneConfiguration = connectionFactory.getStandaloneConfiguration();
standaloneConfiguration.setDatabase(i);
LettuceClientConfiguration clientConfiguration = connectionFactory.getClientConfiguration();
LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(standaloneConfiguration, clientConfiguration);
lettuceConnectionFactory.afterPropertiesSet();
return lettuceConnectionFactory;
}
}
シーケンス化管理クラスの宣言
public class RedisSerializerManager {
/**
*
*/
private static RedisSerializer defRedisSerializer;
/**
*
*/
private static RedisSerializerEntity defKeyValueSerializer;
static {
defRedisSerializer = new StringRedisSerializer();
defKeyValueSerializer = new RedisSerializerEntity();
defKeyValueSerializer.setKeySerializer(defRedisSerializer);
defKeyValueSerializer.setValueSerializer(defRedisSerializer);
}
private Map<Integer, RedisSerializerEntity> serializerMap = new HashMap<>();
public static RedisSerializerEntity getDefKeyValueSerializer() {
return defKeyValueSerializer;
}
public static void setDefKeyValueSerializer(RedisSerializerEntity defKeyValueSerializer) {
RedisSerializerManager.defKeyValueSerializer = defKeyValueSerializer;
}
/**
* @param dbIndex dbIndex
* @param redisSerializerEntity
*/
public void put(Integer dbIndex, RedisSerializerEntity redisSerializerEntity) {
serializerMap.put(dbIndex, redisSerializerEntity);
}
public RedisSerializerEntity get(Integer dbIndex) {
return serializerMap.get(dbIndex);
}
public static RedisSerializer getDefRedisSerializer() {
return defRedisSerializer;
}
public static void setDefRedisSerializer(RedisSerializer defRedisSerializer) {
RedisSerializerManager.defRedisSerializer = defRedisSerializer;
}
/**
* key value
*/
public static class RedisSerializerEntity {
/**
* key
*/
private RedisSerializer<?> keySerializer = defRedisSerializer;
/**
* value
*/
private RedisSerializer<?> valueSerializer = defRedisSerializer;
public RedisSerializer<?> getKeySerializer() {
return keySerializer;
}
public void setKeySerializer(RedisSerializer<?> keySerializer) {
this.keySerializer = keySerializer;
}
public RedisSerializer<?> getValueSerializer() {
return valueSerializer;
}
public void setValueSerializer(RedisSerializer<?> valueSerializer) {
this.valueSerializer = valueSerializer;
}
}
}
4.使用方法
1. @EnableRedisDbs( META-INF )
2. spring.redis.databases
db index ','
3. spring.redis.beanPrefix
redistemplate , 'redis_db_'
4. RedisDbsTemplate, getRedisTemplate(dbIndex);
5.
@Autowired
@Qualifier("redis_db_X")
private RedisTemplate redisTemplate;
X dbIndex;
6. RedisSerializerManager DB_redisTemplate