redis 详解三

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);
    }
复制代码

 

 

posted @   Bonnie_ξ  阅读(368)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示