Redis生成分布式环境下自增ID
1. 需求明确
我们生成的Id组成为, 时间戳+ 自增Id, 补0
例如: 今天是2020.2.28 , 补6个0 , 那么生成的id范围是20200228000001-202002289999999
2.技术选型
Redis中的RedisAtomicLong 具备原子性, 可以通过其incr方法进行递增.
2. Id生成类
EXPIRE key seconds
设置key的生存时间还剩多少秒
EXPIREAT key timestamp
设置key生存到什么时候,接受的参数是时间戳
package com.dyhospital.cloudhis.common.redis.util; 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.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.concurrent.TimeUnit; /** * Description: 分布式Id生成工厂 * User: zhouzhou * Date: 2020-02-28 * Time: 10:14 */ @Component public class IdGeneratorFactory { @Autowired RedisTemplate redisTemplate; /** * @param key * @param value * @param expireTime * @Title: set * @Description: set cache. */ public void set(String key, int value, Date expireTime) { RedisAtomicLong counter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory()); counter.set(value); counter.expireAt(expireTime); } /** * @param key * @param value * @param timeout * @param unit * @Title: set * @Description: set cache. */ public void set(String key, int value, long timeout, TimeUnit unit) { RedisAtomicLong counter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory()); counter.set(value); counter.expire(timeout, unit); } /** * @param key * @return * @Title: generate * @Description: Atomically increments by one the current value. */ public long generate(String key) { RedisAtomicLong counter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory()); return counter.incrementAndGet(); } /** * @param key * @return * @Title: generate * @Description: Atomically increments by one the current value. */ public long generate(String key, Date expireTime) { RedisAtomicLong counter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory()); counter.expireAt(expireTime); return counter.incrementAndGet(); } /** * @param key * @param increment * @return * @Title: generate * @Description: Atomically adds the given value to the current value. */ public long generate(String key, int increment) { RedisAtomicLong counter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory()); return counter.addAndGet(increment); } /** * @param key * @param increment * @param expireTime * @return * @Title: generate * @Description: Atomically adds the given value to the current value. */ public long generate(String key, int increment, Date expireTime) { RedisAtomicLong counter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory()); counter.expireAt(expireTime); return counter.addAndGet(increment); } /** * 根据业务key, 长度, 获取key, 以日期作为前缀 * * key = order, length = 5 ,当天日期2050年1月1日 * 结果: 2050010100001 * * @param key * @param length * @return */ public String generateIdByToday(String key, Integer length) { RedisAtomicLong counter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory()); long num = counter.incrementAndGet(); counter.expireAt(getTodayEndTime()); String id = getToday() + String.format("%0" + length + "d", num); return id; } /** * @Title: getTodayEndTime 获取今日最后的时间 * @Description: Get the cache expire time. * @return */ public static Date getTodayEndTime() { Calendar todayEnd = Calendar.getInstance(); todayEnd.set(Calendar.HOUR_OF_DAY, 23); todayEnd.set(Calendar.MINUTE, 59); todayEnd.set(Calendar.SECOND, 59); todayEnd.set(Calendar.MILLISECOND, 999); return todayEnd.getTime(); } /** * @Title: getTodayEndTime 今天的日期格式: 20190101 * @Description: Get the cache expire time. * @return */ public static String getToday() { SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); return sdf.format(new Date()); } }
3. 我们来测试下
// --------------------- 分布式自增Id 测试 --------------------------- @ApiOperation("根据key生成自增Id") @RequestMapping(value = "/getId/{key}", method = RequestMethod.GET) public GenericResponse getId(@PathVariable("key") String key) { logger.info("生成Id中"); long generate = idGeneratorFactory.generate(key, IdGeneratorFactory.getTodayEndTime()); return new GenericResponse<>(generate); } @ApiOperation("根据key生成自增Id,日期版") @RequestMapping(value = "/getIdByToday/{key}", method = RequestMethod.GET) public GenericResponse getIdByToday(@PathVariable("key") String key) { logger.info("生成Id中"); String id = idGeneratorFactory.generateIdByToday(key, 6); return new GenericResponse<>(id); }