业务流水号(交易号)生成方法

概述


大流量下订单号生成方法一文中介绍了如何生成不重复的订单号,主要原理是利用数据库自增ID。但是像业务流水号之类的,其实不利用数据库也是可以的,只是要保证唯一性,做起来不太好做。下文介绍一种方法来生成流水号,如果不是那种特别变态的调用量,产生重复的机会还是很少的。但是如果是那种无论如何都不能重复的,不建议用本文的方法了。


流水号生成规则


时间+四位的机器号+10位的随机数


时间的生成


时间的话,可以使用下面的方式来生成。

FastDateFormat.getInstance("yyyyMMddHHmmssSSS").format(new Date()))

使用apache的FastDateFormat线程安全的格式化时间,到毫秒。注意千万别用JAVA自带的SimpleDateFormat,不是线程安全的,如果你一定要用SimpleDateFormat的话,需要结合ThreadLocal来实现。


机器号


这个可以先用JAVA代码获取机器的MAC地址。如何获取机器的MAC地址的代码,网上大把,这里贴一个用过的。

private static String getMacAddress() throws Exception {
        Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
        while (networkInterfaces.hasMoreElements()) {
            NetworkInterface networkInterface = networkInterfaces.nextElement();
            if (null == networkInterface) {
                continue;
            }
            byte[] macBytes = networkInterface.getHardwareAddress();
            if (networkInterface.isUp() && !networkInterface.isLoopback() && null != macBytes && macBytes.length == 6) {
                StringBuilder sb = new StringBuilder();
                for (int i = 0, nLen = macBytes.length; i < nLen; i++) {
                    byte b = macBytes[i];
                    sb.append(Integer.toHexString((b & 240) >> 4));
                    sb.append(Integer.toHexString(b & 15));
                    if (i < nLen - 1) {
                        sb.append("-");
                    }
                }
                return sb.toString().toUpperCase();
            }
        }
        return null;
    }

上面的代码就获取到MAC地址,格式是:

xx-xx-xx-xx-xx-xx

得到MAC地址后,可以根据MAC地址获取它对应的CRC16校验码,可以简单的使用如下代码来获取:

private static int getCRC16Code(String macAddress) {
        if (null == macAddress) {
            return 0;
        }
        byte[] data = macAddress.getBytes(Charset.forName("utf-8"));
        CRC16 crc16 = new CRC16();
        for (byte b : data) {
            crc16.update(b);
        }
        return crc16.value;
    }

接下来可以根据这个CRC16校验码截取高四位。这个代码比较简单,就不贴了。

另外,也见过机器号是通过环境变量来读取的,把机器号配置在环境变量中,然后直接在代码里读取。也见过在配置中心配置的。


生成随机数


可以利用JAVA的AtomicInteger来生成。


总结


如果你的应用是要给对方提供流水号的,那么如果对方使用for循环并且并发调用,还是有可能生成重复的流水号的,这种情况下,最好在客户端调用的时候,在for循环里sleep 一毫秒,降低并发。

另外有个建议,如果是对方的接口要求你传入一个唯一的流水号,最好在生成的流水号上加上自己系统的名字,这样服务方也可以通过看流水号,就知道是哪个系统过来的。

猜你喜欢

转载自blog.csdn.net/linsongbin1/article/details/79495899