Springboot Redis SwitchDB + SwapDB

冷启动数据环境中,流程如下:

Start ->
    FlushDB ->
        LOAD Data from Oracle/MySQL ->
            Insert Data into Redis ->
                End

FlushDB这个时间点a,完成LOAD时间点b,完成Insert 时间点c。

也就是说在(c - a)这么长的时间内,用户是无法获取数据的,即数据空白期。

这是很影响用户体验的。

我们改善一下流程:

Start ->
    Select DB-sub ->
        FlushDB-sub ->
            LOAD Data from Oracle/MySQL ->
                Insert Data into Redis DB-sub ->
                    SwapDB main & sub ->
                        END 

这样的话,我们只在最后一个swap的过程中会有一个数据空白期,但是swap执行速度极快,也就是说,空白期几乎没有。

 

用Springboot实现,则会使用到Redis的Select以及Swapdb

SELECT int
SWAPDB int int 

pom.xml:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

配置类:

@Configuration
public class RedisConfig {
    private final LettuceConnectionFactory factory;

    public RedisConfig(LettuceConnectionFactory factory) {
        this.factory = factory;
    }

    @Bean
    public RedisTemplate<String, Object> redisTemplate() {
        factory.setShareNativeConnection(false);
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new StringRedisSerializer());
        redisTemplate.setConnectionFactory(factory);
        return redisTemplate;
    }

    @Bean
    public HashOperations<String, String, Object> hashOperations(RedisTemplate<String, Object> redisTemplate) {
        return redisTemplate.opsForHash();
    }

    @Bean
    public ValueOperations<String, String> valueOperations(RedisTemplate<String, String> redisTemplate) {
        return redisTemplate.opsForValue();
    }

    @Bean
    public ListOperations<String, Object> listOperations(RedisTemplate<String, Object> redisTemplate) {
        return redisTemplate.opsForList();
    }

    @Bean
    public SetOperations<String, Object> setOperations(RedisTemplate<String, Object> redisTemplate) {
        return redisTemplate.opsForSet();
    }

    @Bean
    public ZSetOperations<String, Object> zSetOperations(RedisTemplate<String, Object> redisTemplate) {
        return redisTemplate.opsForZSet();
    }

}

功能类:

public boolean insert() {
        stringRedisTemplate.executePipelined((RedisCallback<Object>) redisConnection -> {
            StringRedisConnection stringRedisConn = (StringRedisConnection) redisConnection;
            logger.info("[REDIS] Switching to DB[" + subDatabase + "]");
            stringRedisConn.select(subDatabase);
            stringRedisConn.flushDb();       
            /** insert */
            stringRedisConn.set(key,value); 
            return null;
        });
        return true;
    }        

swapDB 只能用Jedis实现:

    public void dbSwap() {
        Jedis jedis = new Jedis(host, port);
        jedis.auth(password);
        logger.info("[REDIS] Swapping DB[" + database + "] and DB[" + subDatabase + "]");
        jedis.swapDB(database, subDatabase);
    }

  

注意一下,为了selectdb,在配置类中

factory.setShareNativeConnection(false);
不然会切换失败


 

posted @ 2020-08-25 11:11  KoenigSEA  阅读(359)  评论(0编辑  收藏  举报
Back to HOME