使用mysql设计一个全局订单生产计数器

2018年8月10日08:53:50

一般生产订单号的方式

1,使用时期+随机数1+随机数2

缺点,有可能在并发的时候会出现重复,解决办法就是加唯一索引,在插入数据的做查询是否已经被使用

2,使用时间+统计当前订单数,按订单数+1,很多系统使用这种

缺点,如果有需要删除数据,当然脑残的需求,但是还是会有,再次下单就会出现订单重复,这种非常不好改动

参考1:金蝶k3,会有一个全局使用的ID,通过触发器增长

参考2:经验之谈,全局计数器解决2个根本问题,订单号不重复,使用一次请求一次,返回最近的计算结果,2不会因为删除订单出现订单号重复

数据库

--计数器表
CREATE TABLE `counter` (
 `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
 `name` varchar(100) DEFAULT NULL COMMENT ‘名称‘,
 `value` bigint(20) unsigned DEFAULT ‘1‘ COMMENT ‘存储的值‘,
 `create_time` datetime NOT NULL DEFAULT ‘0000-00-00 00:00:00‘ COMMENT ‘创建时间‘,
 `update_time` datetime NOT NULL DEFAULT ‘0000-00-00 00:00:00‘ COMMENT ‘更新时间‘,
 `tag` varchar(50) DEFAULT NULL COMMENT ‘标签‘,
 `type` tinyint(1) NOT NULL DEFAULT ‘10‘ COMMENT ‘类型10采购订单20销售订单30自营物流号‘,
 PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT=‘计数器表‘;

注意我存储的 value是bigint 20,足够大

 //计数器
    public static function counter($type = null) {
        if (empty($type)) {
            throw new \Exception(‘tag标签不能为空‘);
        }
        $now = time();
        $time = date(‘Ymd‘, $now);
        $time1 = date(‘Ym‘, $now);
        $tag = self::counter_array($type);
        $name = $time . ‘_‘ . $tag;

        DB::beginTransaction();
        try {
            $Counter = Counter::where(‘name‘, $name)->lockForUpdate()->first([‘value‘, ‘id‘]);
            if (empty($Counter)) {
                //没有就插入
                $Counter = new Counter;
                $Counter->name = $name;
                $Counter->type = $type;
                $Counter->tag = $tag;
                $Counter->save();
                $Counter = Counter::where(‘name‘, $name)->first([‘value‘, ‘id‘]);
            }

            $Counter = $Counter->toArray();
            //加锁 防止生成的订单号出错,没有在name上加索引
            Counter::where(‘id‘, $Counter[‘id‘])->lockForUpdate()->first();

            if ($type == 40) {
                $new_count = (float) $Counter[‘value‘] + 1;
                Counter::where(‘name‘, $name)->update([‘value‘ => $new_count]);
                $string = $time1 . str_pad($new_count, 6, ‘0‘, STR_PAD_LEFT);
            } else {
                $new_count = (float) $Counter[‘value‘] + 3;
                Counter::where(‘name‘, $name)->update([‘value‘ => $new_count]);
                $string = $time . str_pad($new_count, 12, ‘0‘, STR_PAD_LEFT);
            }

            DB::commit();
            return $string;
        } catch (\Exception $e) {
            DB::rollBack();
            throw new \Exception($e->getMessage());
        }
    }

    //订单计数器映射数组
    public static function counter_array($type = null) {
        //采购订单号
        $array[‘10‘] = ‘sales_order_number‘;
        //销售订单号
        $array[‘20‘] = ‘purchase_order_number‘;
        //自营物流订单号
        $array[‘30‘] = ‘logistics_order_number‘;
        //入库订单号
        $array[‘40‘] = ‘inbound_order_number‘;
        //出库订单号
        $array[‘50‘] = ‘outbound_order_number‘;
        if (empty($type)) {
            return $array;
        }
        return $array[$type];
    }

解释一下为什么不适用 全局订单不是+1而是+3,防止有特殊订单需要插入,同时不让计数器的数字增长太快

还有必须加锁,虽然有事务,但是还是要加锁,订单长度自己选择填充长度,我定义的是20个长度,足够了14位长度的除以3的长度,足够了

有人会担心新能,我只能说你想多了,这点压力都扛不住,不可能,见过随时写入mysql,随时读取的操作吗?这么糙的逻辑代码mysql都能满足

原文地址:https://www.cnblogs.com/zx-admin/p/9452952.html

时间: 2024-10-09 14:46:15

使用mysql设计一个全局订单生产计数器的相关文章

设计一个BCD码计数器。

BCD码计数器的定义: 对于机器语言,机器与人不同,为了让人更好的了解机器语言的数据输出,选用4位二进制数据表示十进制里的每位数据,这便是BCD码. 以下便是BCD码与十进制对应的码表 0-----------0000----------0x0 1-----------0001----------0x1 2-----------0010----------0x2 3-----------0011----------0x3 4-----------0100----------0x4 5------

一步一步跟我学模型设计之入门级:设计一个mysql模型

欢迎试用Linker Networks(www.linkernetworks.com)的领科云,一个基于Mesos Docker的混合云平台. http://marketplace.linkernetworks.com/ 在本章节,我们在设计模型的时候,并不考虑任何的应用关系,从一个原子的应用开始. 我们就设计一个最基本的mysql模型. 为了简单期间,我们暂且不考虑从dockerfile编译成Docker镜像的过程,而是从一个已经存在的镜像开始. 第一步:在Docker Hub上查找一个Doc

深度学习:从头设计一个TensorFlow3一样的新一代深度学习系统,到底需要把握哪些要点?

深度学习工具潮流滚滚,各种工具层出不穷.也有各种文章从易用性,可移植性,灵活性和效率方面对于各个系统进行比较.这篇文章希望从系统设计上面来讲来回答这个讨论这个问题:如果想到从头设计一个TensorFlow3一样的新一代深度学习系统,到底需要把握哪些要点. 计算单元:从layer abstraction到operator 大家熟悉的第一代深度学习系统,以cuda-convnet21和caffe为代表.这些系统主要的一大特点是提出了一个以深度学习计算层次layer为基本单元的计算单位.不同的laye

设计一个 iOS 控件

代码的等级:可编译.可运行.可测试.可读.可维护.可复用 前言 一个控件从外在特征来说,主要是封装这几点: 交互方式 显示样式 数据使用 对外在特征的封装,能让我们在多种环境下达到 PM 对产品的要求,并且提到代码复用率,使维护工作保持在一个相对较小的范围内:而一个好的控件除了有对外一致的体验之外,还有其内在特征: 灵活性 低耦合 易拓展 易维护 通常特征之间需要做一些取舍,比如灵活性与耦合度,有时候接口越多越能适应各种环境,但是接口越少对外产生的依赖就越少,维护起来也更容易.通常一些前期看起来

从研发人的角度评判怎样设计一个好的DCS系统

相信从事自动化或控制系统的同仁,应该了解Distributed Control System(简称DCS)的基本功能及其在工控行业的作用.从工程应用的角度,一个完整的DCS系统主要包括三个部分:HMI人机交互层.控制站层.仪表与执行机构层. HMI主要包括工程师站.监控站.历史站等,主要在具有较高稳定的PC上安装相应的软件构成.控制站层,主要实现相应的控制算法与逻辑,并通过相应的IO卡件采集数据和发送指令.仪表与执行机构,主要由各个厂家的智能变送器.电动机等组成. 由于仪表与执行机构,厂家众多,

MySQL 设计与开发规范

1 目的 本规范的主要目的是希望规范数据库设计与开发,尽量避免由于数据库设计与开发不当而产生的麻烦:同时好的规范,在执行的时候可以培养出好的习惯,好的习惯是软件质量的很好保证. 2 适用范围 本规划的适用人员范围包括涉及数据库设计与开发的相关技术人员. 3 术语约定 本规范采用以下术语描述: ★规则:也称为强规范是编程时必须强制遵守的原则 ★建议:编程时必须加以考虑的原则 ★说明:对此规则或建议进行必要的解释 ★示例:对此规则或建议从正.反两个方面给出 4 规范及建议 4.1 书写规范 4.1.

MySQL设计之三范式

网上查找了一些资料,记录如下并加入自己的理解. 设计关系数据库时,遵从不同的规范要求,设计出合理的关系型数据库,这些不同的规范要求被称为不同的范式,各种范式呈递次规范,越高的范式数据库冗余越小.但是有些时候一昧的追求范式减少冗余,反而会降低数据读写的效率,这个时候就要反范式,利用空间来换时间. 目前关系数据库有六种范式:第一范式(1NF).第二范式(2NF).第三范式(3NF).巴斯-科德范式(BCNF).第四范式(4NF)和第五范式(5NF,又称完美范式).满足最低要求的范式是第一范式(1NF

MYSQL设计优化

本文将从各方面介绍优化mysql设计的一些方式. 1.优化sql语句 (1)定位需要优化的sql语句 1)show status统计SQL语句频率 对Myisam和Innodb存储引擎都计数的参数: SHOW STATUS可以根据需要显示session级别的统计结果和global级别的统计结果. 1.Com_select  执行select操作的次数,一次查询只累加1: 2.Com_insert 执行insert操作的次数,对于批量插入的insert操作,只累加一次: 3.Com_update

如何设计一个可用的web容器

之前在另外一个平台(http://www.jointforce.com/jfperiodical/article/1035)发表的一篇文章,现在发布到自己的博客上. 开发一个web容器涉及很多不同方面不同层面的技术,例如通信层的知识,程序语言层面的知识等等,且一个可用的web容器是一个比较庞大的系统,要说清楚需要很长的篇幅,本文旨在介绍如何设计一个web容器,只探讨实现的思路,并不涉及过多的具体实现.把它分解划分成若干模块和组件,每个组件模块负责不同的功能,下图列出一些基本的组件,并将对每个组件