如果生成比如WX00000001并且自动递增的ID时,如果多次、多客户端同时请求,会出现重复生成的情况。
解决方案如下:
@Resource
private RedisGenerateIdUtil redisGenerateIdUtil;//生成自增id
private static final String PRODUCT_GENERATE_ID = "ID:AUTO:INCREMENT";
private Object lockObj = new Object();
String preffix = "WX";
//redis获取值
String wxIdKey = RedisKeyUtil.getWxIdKey(PRODUCT_GENERATE_ID);
Long incr = redisGenerateIdUtil.getIncr(wxIdKey);
if(incr == null){
//防止key过期出现重复数据
synchronized (lockObj) {
//查询上一个id
String id = wxMapper.selectCode();
int suffix = 00000000;
if (StringUtils.isNotEmpty(code)) {
String[] split = code.split(preffix);
String suffixStr = split[1];
Integer suffixInt = Integer.valueOf(suffixStr);
suffix = suffixInt + 1;
}
incr = new Long(suffix);
redisGenerateIdUtil.setIncr(wxIdKey, suffix);
}
}
String id = preffix + incr;
工具类内容如下
/**
* @Description redis生成分布式id,支持long型自增
*/
@Configuration
public class RedisGenerateIdUtil {
private final RedisTemplate<String, Object> redisTemplate;
@Autowired
public RedisGenerateIdUtil(RedisTemplate<String, Object> redisTemplate){
this.redisTemplate = redisTemplate;
}
/**
* redis设置初值,暂未设置过期时间
* @param key
* @param value
*/
public void setIncr(String key,int value) {
Assert.hasText(key, "a valid key name is required");
RedisAtomicLong redisAtomicLong = new RedisAtomicLong(key, redisTemplate.getConnectionFactory());
redisAtomicLong.set(value);
//redisAtomicLong.expire(timeout, TimeUnit.SECONDS);
}
/**
* redis获取值,暂未设置过期时间
* @param key
* @return
*/
public Long getIncr(String key){
Assert.hasText(key, "a valid key name is required");
RedisAtomicLong entityIdCounter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory());
Long increment = entityIdCounter.incrementAndGet();
//未设置key,默认值为0 incrementAndGet() 一次后为1
if(increment == 1){
increment = null;
}
//entityIdCounter.expire(timeout, TimeUnit.SECONDS);
return increment;
}
}