【redis】redis自增序列以及服务重启后自增序列失效问题解决

思路:用RedisAtomicLong获取自增数,然而在redis服务关闭重启后,自增序列又会从之前的数据开始计算,导致自增数重复,这和我之前写的一篇文章:redis重启后 删除的key值又恢复了情况 非常像,其实是文件还没开始新一步持久化,因为redis默认RDB 方式, 我们需要开启AOF方式,找到redis的配置文件:redsi.windows.conf

几个主要参数介绍:

<!-- redis3.x中 默认是no 表示不开启aof 我们需要改成yes -->
appendonly no

<!-- redis3.x中 默认是everysec 表示每秒同步一次 这个需要根据实际场景, always 表示每次修改都同步-->
<!-- 试想一下 如果redis服务被kill了 那么连接的时候自然是会超时, 从服务被kill到starup这段时间 1秒内是不可能完成的,也就是说 基于这种情况 everysec每秒同步一次是足够了 因为暂时没遇到redis服务还能连接 但是报错导致崩了情况 所以暂时不考虑always这种牺牲性能的方式  -->
appendfsync everysec

配置类

import com.alibaba.fastjson.support.spring.FastJsonRedisSerializer;

import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
@EnableCaching
@AutoConfigureBefore(RedisAutoConfiguration.class)
public class RedisTemplateConfiguration {
    
    
    private final RedisConnectionFactory redisConnectionFactory;

    @Bean
    public RedisTemplate<String,Object> redisTemplate() {
    
    
        RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        // value值的序列化采用fastJsonRedisSerializer
        FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer(Object.class);
        redisTemplate.setValueSerializer(fastJsonRedisSerializer);
        redisTemplate.setHashValueSerializer(fastJsonRedisSerializer);
        return redisTemplate;
    }
}

附上一个常用工具类 (获取自增方法也在里面)

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.concurrent.TimeUnit;

@Component
public class RedisUtil {
    
    
    @Autowired
    public RedisTemplate redisTemplate;
    /** 添加缓存 **/
    //添加缓存对象
    public boolean set(String key, Object value) {
    
    
        try {
    
    
            redisTemplate.opsForValue().set(key, value);
            return true;
        } catch (Exception e) {
    
    
            return false;
        }

    }
    //添加缓存对象和有效时间
    public boolean set(String key,
                       Object value,
                       Integer timeout,
                       TimeUnit timeUnit) {
    
    
        try {
    
    
            redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
            return true;
        } catch (Exception e) {
    
    
            return false;
        }
    }

    //缓存List数据
    public boolean lSet(String key, Object value) {
    
    
        try {
    
    
            redisTemplate.opsForList().rightPushAll(key, value);
            return true;
        } catch (Exception e) {
    
    
            e.printStackTrace();
            return false;
        }
    }

    //缓存List数据 添加有效期
    public boolean lSet(String key, Object value, long time, TimeUnit timeUnit) {
    
    
        try {
    
    
            redisTemplate.opsForList().rightPushAll(key, value, time, timeUnit);
            return true;
        } catch (Exception e) {
    
    
            e.printStackTrace();
            return false;
        }
    }

    //键值递增
    public long increment(String key, long delta) {
    
    
        if (delta < 0) {
    
    
            throw new RuntimeException("递增因子必须大于0");
        }
        return redisTemplate.opsForValue().increment(key, delta);
    }

    /** 获取缓存 **/
    //根据key获取缓存
    public Object get(String key) {
    
    
        return key == null ? null : redisTemplate.opsForValue().get(key);
    }
    //根据key获取list缓存
    public List<Object> lGet(String key, long start, long end) {
    
    
        try {
    
    
            return redisTemplate.opsForList().range(key, start, end);
        } catch (Exception e) {
    
    
            e.printStackTrace();
            return null;
        }
    }
    //获取list缓存的长度
    public long lGetListSize(String key) {
    
    
        try {
    
    
            return redisTemplate.opsForList().size(key);
        } catch (Exception e) {
    
    
            e.printStackTrace();
            return 0;
        }
    }

    //通过下标获取list中的值
    public Object lGetIndex(String key, long index) {
    
    
        try {
    
    
            return redisTemplate.opsForList().index(key, index);
        } catch (Exception e) {
    
    
            e.printStackTrace();
            return null;
        }
    }
    //根据key获取过期时间
    public long getExpire(String key) {
    
    
        return redisTemplate.getExpire(key, TimeUnit.SECONDS);
    }

    /** 清除缓存 **/
    public boolean delete(final String key) {
    
    
        return redisTemplate.delete(key);
    }


    public Long getIncrementNum(String key) {
    
    
        // 不存在准备创建 键值对
        RedisAtomicLong entityIdCounter = new RedisAtomicLong(key,    redisTemplate.getConnectionFactory());
        Long counter = entityIdCounter.incrementAndGet();
        // 初始设置过期时间
        if ((null == counter || counter.longValue() == 1)) {
    
    
            // 单位天
            entityIdCounter.expire(1, TimeUnit.DAYS);
        }
        return counter;
    }
}

Controller测试(注意不要用@Test测试)

@RestController
@RequestMapping("/redis")
public class Test1Controller {
    
    
    @Autowired
    private RedisUtil redisUtil;

@GetMapping
    public void getAutoFlowCodeTest() {
    
    
        String currentDate = new SimpleDateFormat("yyyyMMdd").format(new Date());
        Long num = redisUtil.getIncrementNum("each_day_num_"+currentDate);
        String flowCode = RedisSequenceUtils.getSequence(num);

        System.out.println(flowCode);
    }

}

Guess you like

Origin blog.csdn.net/qq_36268103/article/details/115672622