IT序号网

订单号重复Bug

flyfish 2022年04月20日 程序员 201 0

解决思路:

  • 使用UUID(在第一次生成订单号时初始化一个)

  • 使用redis记录一个增长ID

  • 使用数据库表维护一个增长ID

  • 应用所在的网络IP

  • 应用所在的端口号

  • 使用第三方算法(雪花算法等等)

  • 使用进程ID(某种程度下是一个可行的方案)

代码片段

import org.apache.commons.lang3.RandomUtils; 
 
import java.net.InetAddress; 
import java.time.LocalDateTime; 
import java.time.ZoneId; 
import java.time.format.DateTimeFormatter; 
import java.util.ArrayList; 
import java.util.Collections; 
import java.util.List; 
import java.util.concurrent.atomic.AtomicInteger; 
import java.util.stream.Collectors; 
import java.util.stream.IntStream; 
 
public class OrderGen2Test { 
 
    /** 订单号生成 **/ 
    private static ZoneId ZONE_ID = ZoneId.of("Asia/Shanghai"); 
    private static final AtomicInteger SEQ = new AtomicInteger(1000); 
    private static final DateTimeFormatter DF_FMT_PREFIX = DateTimeFormatter.ofPattern("yyMMddHHmmssSS"); 
    public static String generateOrderNo(){ 
        LocalDateTime dataTime = LocalDateTime.now(ZONE_ID); 
        if(SEQ.intValue()>9990){ 
            SEQ.getAndSet(1000); 
        } 
        return  dataTime.format(DF_FMT_PREFIX)+ getLocalIpSuffix()+SEQ.getAndIncrement(); 
    } 
 
    private volatile static String IP_SUFFIX = null; 
    private static String getLocalIpSuffix (){ 
        if(null != IP_SUFFIX){ 
            return IP_SUFFIX; 
        } 
        try { 
            synchronized (OrderGen2Test.class){ 
                if(null != IP_SUFFIX){ 
                    return IP_SUFFIX; 
                } 
                InetAddress addr = InetAddress.getLocalHost(); 
                //  172.17.0.4  172.17.0.199 , 
                String hostAddress = addr.getHostAddress(); 
                if (null != hostAddress && hostAddress.length() > 4) { 
                    String ipSuffix = hostAddress.trim().split("\\.")[3]; 
                    if (ipSuffix.length() == 2) { 
                        IP_SUFFIX = ipSuffix; 
                        return IP_SUFFIX; 
                    } 
                    ipSuffix = "0" + ipSuffix; 
                    IP_SUFFIX = ipSuffix.substring(ipSuffix.length() - 2); 
                    return IP_SUFFIX; 
                } 
                IP_SUFFIX = RandomUtils.nextInt(10, 20) + ""; 
                return IP_SUFFIX; 
            } 
        }catch (Exception e){ 
            System.out.println("获取IP失败:"+e.getMessage()); 
            IP_SUFFIX =  RandomUtils.nextInt(10,20)+""; 
            return IP_SUFFIX; 
        } 
    } 
 
 
    public static void main(String[] args) { 
        List<String> orderNos = Collections.synchronizedList(new ArrayList<String>()); 
        IntStream.range(0,8000).parallel().forEach(i->{ 
            orderNos.add(generateOrderNo()); 
        }); 
 
        List<String> filterOrderNos = orderNos.stream().distinct().collect(Collectors.toList()); 
 
        System.out.println("订单样例:"+ orderNos.get(22)); 
        System.out.println("生成订单数:"+orderNos.size()); 
        System.out.println("过滤重复后订单数:"+filterOrderNos.size()); 
        System.out.println("重复订单数:"+(orderNos.size()-filterOrderNos.size())); 
    } 
} 
 

评论关闭
IT序号网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!

java接口和抽象类的异同,什么时候该用接口什么时候该用抽象类