zoukankan      html  css  js  c++  java
  • 分布式系统电商订单号的最佳生成方式

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

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

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

    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数据需要载入硬盘,防丢失(其实也不算缺点)

    如有不妥,欢迎指正!
  • 相关阅读:
    原型链与析构函数
    django篇-路由系统介绍
    mvc与mtv
    模板初探
    安装和创建django项目
    一分钟学会定时删除日志的 Shell 脚本
    svn其中一种备份方式svnsync
    mysql企业实战(二)之主从复制,读写分离,双主,以及高可用
    mysql企业实战(一)
    nginx详解
  • 原文地址:https://www.cnblogs.com/tc520/p/10457977.html
Copyright © 2011-2022 走看看