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


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

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

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

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

    如有不妥,欢迎指正!
  • 相关阅读:
    手动添加 memcached.jar包
    easyui返回数据类型
    负载均衡
    nginx负载均衡
    nginx配置文件详解
    Js操作Select大全(取值、设置选中)
    jQuery select的操作代码
    jQuery对Select操作大集合
    PHP+AJAX无刷新返回天气预报
    一个好用的PHP验证码类
  • 原文地址:https://www.cnblogs.com/tc520/p/10457977.html
Copyright © 2020-2023  润新知