保姆级Java项目根据年月日生成有序自增编号

技术:采用的是redis的自增生成有序编号

补零方法


    /**
     * 生成编号
     * @param type 编号开头
     * @param number 编号
     * @return
     */
    private  String getCode(String type, String number) {
        String date = DateUtil.format(new Date(), "yyyyMMdd");
        StringBuffer buffer = new StringBuffer();
        buffer.append(type)
                .append(date);
        for (int i = number.length(); i < 6; i++) {
            buffer.append("0");
        }
        buffer.append(number);
        return buffer.toString();
    }
    /**
     * 自增编号
     * @param key 编号开头
     * @return
     */
    public String getOrderCode(String key) {
        //如果值存在,直接自增返回        @第一个if
        if (RedisUtils.hasKey(key)) {
            return getCode(key, RedisUtils.incr(key).toString());
        }
        //拿不到值,说明可能到了零点,自增值失效,需要重新set 一个0进去
        //需要考虑分布式和本地并发问题,分布式通过redssion lock解决
        //本地并发可以通过lock 和 tryLock两种方案,lock是把while(true)放里面,本方案采用tryLock
        //while(true)里面两个分支,第一个分支是拿到锁,进去后需要考虑,执行成功后,临界区的线程进来所以需要先判空
        //第二个分支是拿不到锁,判断一下是否已经被拿到锁的线程set值成功,如果成功,直接返回
        boolean lock = RedisUtils.getLock(BmsConstant.CODE_LOCK_KEY + key, key, BmsConstant.INTEGER_ONE);
        try {
            while (true) {
                //拿到锁就初始化值和失效时间,没拿到锁就继续获取key的值
                if (lock) { // @第二个if
                    if (RedisUtils.hasKey(key)) {  // @第三个if
                        RedisUtils.set(key, 0, getNowToNextDayMilliseconds(), TimeUnit.MILLISECONDS);
                    }
                    return getCode(key, RedisUtils.incr(key).toString());
                } else {
                    if (RedisUtils.hasKey(key)) {// @第四个if
                        return getCode(key, RedisUtils.incr(key).toString());
                    }
                }
            }
        } catch (Exception e) {
            throw new RuntimeException();
        } finally {
            RedisUtils.releaseLock(BmsConstant.CODE_LOCK_KEY + key, key);
        }
    }
    /**
     * 今日剩余时间计算
     * @return
     */
    public Long getNowToNextDayMilliseconds() {
        //获取当前时间
        Calendar calendar = Calendar.getInstance();
        //当前天+1
        calendar.add(Calendar.DAY_OF_YEAR, 1);
        //将时分秒毫秒都设为0
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        //减去当前时间获取插值
        return (calendar.getTimeInMillis() - System.currentTimeMillis());
    }
RedisUtils工具类
@UtilityClass
public class RedisUtils {

    private static final Long SUCCESS = 1L;

     /**
     * 判断key是否存在
     *
     * @param key 键
     * @return true 存在 false不存在
     */
    public boolean hasKey(String key) {
        RedisTemplate<Object, Object> redisTemplate = SpringContextHolder.getBean(RedisTemplate.class);
        return Optional.ofNullable(redisTemplate).map(template -> template.hasKey(key)).orElse(false);
    }

    /**
     * 普通自增
     * @param key 键
     * @return 值
     */
    public Long incr(String key){
        RedisTemplate redisTemplate = SpringContextHolder.getBean(RedisTemplate.class);
        return redisTemplate.opsForValue().increment(key);
    }

    /**
     * 普通缓存放入并设置时间
     *
     * @param key      键
     * @param value    值
     * @param time     时间
     * @param timeUnit 类型
     * @return true成功 false 失败
     */
    public <T> boolean set(String key, T value, long time, TimeUnit timeUnit) {
        RedisTemplate<String, T> redisTemplate = SpringContextHolder.getBean(RedisTemplate.class);
        Optional.ofNullable(redisTemplate).map(template -> {
            if (time > 0) {
                template.opsForValue().set(key, value, time, timeUnit);
            } else {
                template.opsForValue().set(key, value);
            }
            return true;
        });
        return true;
    }

    /**
     * 获取锁
     *
     * @param lockKey         锁key
     * @param value           value
     * @param expireTime:单位-秒
     * @return boolean
     */
    public boolean getLock(String lockKey, String value, int expireTime) {
        RedisTemplate<Object, Object> redisTemplate = SpringContextHolder.getBean(RedisTemplate.class);
        return Optional.ofNullable(redisTemplate)
                .map(template -> template.opsForValue().setIfAbsent(lockKey, value, expireTime, TimeUnit.SECONDS))
                .orElse(false);
    }

    /**
     * 释放锁
     *
     * @param lockKey 锁key
     * @param value   value
     * @return boolean
     */
    public boolean releaseLock(String lockKey, String value) {
        RedisTemplate<Object, Object> redisTemplate = SpringContextHolder.getBean(RedisTemplate.class);
        String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
        RedisScript<Long> redisScript = new DefaultRedisScript<>(script, Long.class);
        return Optional.ofNullable(redisTemplate.execute(redisScript, Collections.singletonList(lockKey), value))
                .map(Convert::toLong)
                .filter(SUCCESS::equals)
                .isPresent();
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
public synchronized String nextId() { long timestamp = timeGen(); //获取当前毫秒数 //如果服务器时间有问题(时钟后退) 报错。 if (timestamp < lastTimestamp) { throw new RuntimeException(String.format( "Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp)); } //如果上次生成时间和当前时间相同,在同一毫秒内 if (lastTimestamp == timestamp) { //sequence自增,因为sequence只有12bit,所以和sequenceMask相与一下,去掉高位 sequence = (sequence + 1) & sequenceMask; //判断是否溢出,也就是每毫秒内超过4095,当为4096时,与sequenceMask相与,sequence就等于0 if (sequence == 0) { timestamp = tilNextMillis(lastTimestamp); //自旋等待到下一毫秒 } } else { sequence = 0L; //如果和上次生成时间不同,重置sequence,就是下一毫秒开始,sequence计数重新从0开始累加 } lastTimestamp = timestamp; long suffix = (datacenterId << datacenterIdShift) | (workerId << workerIdShift) | sequence; String datePrefix = DateFormatUtils.format(timestamp, "yyyyMMddHHMMssSSS"); return datePrefix + suffix; } protected long tilNextMillis(long lastTimestamp) { long timestamp = timeGen(); while (timestamp <= lastTimestamp) { timestamp = timeGen(); } return timestamp; } protected long timeGen() { return System.currentTimeMillis(); } private byte getLastIP(){ byte lastip = 0; try{ InetAddress ip = InetAddress.getLocalHost(); byte[] ipByte = ip.getAddress(); lastip = ipByte[ipByte.length - 1]; } catch (UnknownHostException e) { e.printStackTrace(); } return lastip; }
对于Spring Cloud项目的部署,可以采用以下步骤: 1. 准备环境:首先确保服务器上已经安装了Java运行环境和相关依赖。可以使用Docker容器化技术来快速搭建开发环境。 2. 编译打包:将Spring Cloud项目编译打包成可执行的jar包或war包。可以使用Maven或Gradle进行构建。 3. 配置文件:根据项目需要,编写相应的配置文件,比如application.properties或application.yml,配置数据库连接、端口号等信息。 4. 启动服务:使用命令行或脚本来启动Spring Cloud服务。可以使用nohup命令将服务放在后台运行。 5. 健康检查:确保服务正常运行后,可以使用健康检查工具(如Actuator)来监控服务状态。 6. 负载均衡:如果需要进行负载均衡,可以使用Nginx等反向代理工具来实现。 7. 日志管理:配置日志系统,记录和管理项目的日志信息。可以使用ELK(Elasticsearch + Logstash + Kibana)等工具进行日志集中管理和分析。 8. 监控与调优:使用监控工具(如Prometheus、Grafana)来收集和展示系统运行指标,并进行性能调优和故障排查。 9. 安全加固:根据实际需求,配置相关的安全策略,如防火墙、SSL证书等,保障系统的安全性。 10. 自动化部署:可以使用CI/CD工具(如Jenkins、GitLab CI/CD)实现自动化部署,提高部署效率和稳定性。 以上是一个简要的部署步骤,根据具体项目和环境的不同,可能会有一些细节上的差异。希望对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值