通过redis生成分布式自增的订单编号

850 阅读1分钟

在我们电商交易系统里面经常会生成订单号,一般采用UUID直接生成字符串,理论情况下不会重复,但是还是有可能重复的,并且这种订单号可读性特别差,所以我们会选择用redis来生成订单号,具体代码如下:

1,用DateHelper生成由年月日时分秒生成14位数,再通过redis生成6位数。这种可以用BigInteger存储,理论上可以支持1秒产生100万个订单,如果实际生产会更大,可以把倍数值调大。

package com.hcmony.sword;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import java.util.Calendar;

/**
 * <h3>固定生成20位</h3>
 * 2019 1021 1730 56 000001
 * @author hcmony
 * @since V1.0.0, 2019/10/21 10:21
 */
public class RedisIdGenerator {

    private final static int DEFAULT_LEN = 5;
    private final static int DEFAULT_EXPIRE_TIME = 1000;
    private final static String DEFAULT_KEY = "com.hcmony.id";

    private final JedisPool jedisPool;
    private final int length;
    private final int expireTime;

    public RedisIdGenerator(JedisPool jedisPool) {
        this(jedisPool,DEFAULT_EXPIRE_TIME);
    }

    public RedisIdGenerator(JedisPool jedisPool,  int expireTime) {
        this(jedisPool,expireTime,DEFAULT_LEN);
    }

    public RedisIdGenerator(JedisPool jedisPool, int length, int expireTime) {
        this.jedisPool = jedisPool;
        this.length = length;
        this.expireTime = expireTime;
    }

    public String next() {
        Jedis jedis = jedisPool.getResource();
        try {
            String time = getDateTime();
            String key = DEFAULT_KEY+":"+time;
            Long value = jedis.incr(key);
            jedis.expire(key,expireTime);
            return time + StringUtils.leftPad(StringUtils.right(String.valueOf(value), length), length, '0');
        } finally {
            if (null != jedis) {
                jedis.close();
            }
        }
    }

    public static void main(String[] args) {
        System.out.println(getDateTime());
    }

    private static String getDateTime() {
        return DateFormatUtils.format(Calendar.getInstance(), "yyyyMMddHHmmss");
    }
}