思路:用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);
}
}