分布式系统电商订单号的最佳生成方式

最近在研发区块链支付系统,众所周知,有支付必有订单。今天不做支付系统的具体分析,只来谈谈目前较为热门的订单号码生成方案!

在分布式高并发情况下,订单号必须满足最重要的一个条件:唯一性,订单关系这支付明细,与支付相关的向来都是最重要的,马虎不得。

目前较为成熟的,我所知道的有两种生成方案,接下来做一下对比:

1、根据MySQL自增主键生成订单号

首先,需要创建一张满足自增条件的表,有两个字段即可,id和value,id设置为自增,类型为bigint即可

eg:在mybatis框架中

<insert id="insertAndGetId" useGeneratedKeys="true" keyProperty="id" parameterType="com.chenzhou.mybatis.User">
    insert into user(userName,password,comment)
    values(#{userName},#{password},#{comment})
</insert>

其中useGeneratedKeys="true" 的配置就表示新增后返回主键id,此时我们就可以根据主键id做订单唯一性标识,再加上时间201903010+自增主键,或其他复杂的组合方式即可

此方式的优点:关系型数据库的可靠性!

此方式的缺点:在分布式环境下,需要保证新增的操作是单线程的,需要加锁。

2、利用Redis非关系型数据库

先看代码,再解释

 public String getOrderId(String prefix) {
        //生成订单号 redis incr
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        String time = sdf.format(new Date());
        //当天流水7位
        Long tx = redisTemplate.opsForValue().increment(CommonConstants.OUR_ORDER_ID_INCREMENT_KEY, 1);
        if (tx < CommonConstants.ORDER_ID_INCREMENT_DEFAULT_VALUE) {
            //没值,自动添加
            redisTemplate.opsForValue().set(CommonConstants.OUR_ORDER_ID_INCREMENT_KEY, CommonConstants.ORDER_ID_INCREMENT_DEFAULT_VALUE);
            tx = redisTemplate.opsForValue().increment(CommonConstants.OUR_ORDER_ID_INCREMENT_KEY, 1);
        }
        //自动补0
        String end = autoAddZero(String.valueOf(tx));
        return prefix + time + end;
    }


    public String autoAddZero(String liuShuiHao) {
        Integer intHao = Integer.parseInt(liuShuiHao);
        DecimalFormat df = new DecimalFormat(CommonConstants.ORDER_ID_NUM);
        return df.format(intHao);
    }
getOrderId方法,传入参数prefix,这是订单前缀,有时候我们需要为不同种类或功能生成不一样的订单前缀以助区分,其中最主要是用到了redis的incr函数。我们都知道redis是单行程的,每次操作都不会引发脏读的问题
因此,我们可以利用redis的自增方法incr为我们的订单做唯一性处理。
tx < CommonConstants.ORDER_ID_INCREMENT_DEFAULT_VALUE 的判断是由于第一次调用是没有值的,需要设置一个初始值

autoAddZero是我写的辅助保持订单长度一致的方法,剩下的大写的都是常量,根据字面意思设置即可

此方法的优点:基于缓存策略的性能上明显提升。
此方法的缺点:redis数据需要载入硬盘,防丢失(其实也不算缺点)

如有不妥,欢迎指正!
原文地址:https://www.cnblogs.com/tc520/p/10457977.html