Order number creation (php)

Simple order number creation (php):

      function generateOrderSn()
        {
            $yearCode = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K"];
            //Generate rule year (convert to an uppercase letter to shorten the length) + Month (convert to hexadecimal number) + day + after the current timestamp
            //Several digits + current microseconds (5 digits after the decimal point) + a two digit random year algorithm
            $year = $yearCode[date("Y") - 2018]; //Use A to indicate 2018, etc. in order to shorten the order number
            $month = strtoupper(dechex(date("m")));//hexadecimal
            $day = date("d");
            $sec = substr(time(), -5); //Take the last five digits of the timestamp, because the previous one is so large that it will not change
            [$micr, $second] = explode("", microtime());
            $microsec = substr($micr, 2, 5);//Gets the 5 digits after the decimal point of microseconds
            $rand = random_int(10, 99);
            $orderSn = $year . $month . $day . $sec . $microsec . $rand . uniqid('', true);
            return $orderSn;
        }

If duplication is not ruled out in the case of high concurrency; (there may be duplicate order numbers)

In the case of high concurrency, some mature algorithms can be used, such as:

Implementation of php snowflake algorithm : (this article is good)

Snowflake algorithm is an algorithm invented by Twitter,
The main purpose is to solve the problem of how to generate ID in distributed environment
1. The hard requirements of distributed ID generation rules: globally unique: duplicate ID numbers cannot appear. Since they are unique, this is the most basic requirement. Increasing trend: the InnoDB engine in MySQL uses clustered indexes. Most RDBMS use Btree's data structure to store index data. In the selection of primary keys, try to choose an orderly primary key to ensure writing performance. Monotonic increment: ensure that the next ID number is greater than the previous one

So I'm not afraid 😝😝😝😝😝
The core idea of Snowflake is to divide the 64bit binary number into several parts. Each part stores data with specific meaning, such as time stamp, machine ID, serial number, etc., and finally generates a globally unique ordered ID.

<?php
class SnowFlake
{
    const TWEPOCH = 1288834974657; // The time starting mark point is used as the benchmark, and the latest time of the system is generally taken (once it is determined, it cannot be changed)
 
    const WORKER_ID_BITS     = 5; // Machine identification digit
    const DATACENTER_ID_BITS = 5; // Number of data center identifiers
    const SEQUENCE_BITS      = 12; // Self increment in milliseconds
 
    private $workerId; // Work machine ID
    private $datacenterId; // Data center ID
    private $sequence; // Millisecond sequence
 
    private $maxWorkerId     = -1 ^ (-1 << self::WORKER_ID_BITS); // Machine ID Max
    private $maxDatacenterId = -1 ^ (-1 << self::DATACENTER_ID_BITS); // Maximum data center ID
 
    private $workerIdShift      = self::SEQUENCE_BITS; // Number of left shifts of machine ID
    private $datacenterIdShift  = self::SEQUENCE_BITS + self::WORKER_ID_BITS; // Data center ID shift left
    private $timestampLeftShift = self::SEQUENCE_BITS + self::WORKER_ID_BITS + self::DATACENTER_ID_BITS; // Shift left in milliseconds
    private $sequenceMask       = -1 ^ (-1 << self::SEQUENCE_BITS); // Mask of the generated sequence
 
    private $lastTimestamp = -1; // Last production id timestamp
 
    public function __construct($workerId, $datacenterId, $sequence = 0)
    {
        if ($workerId > $this->maxWorkerId || $workerId < 0) {
            throw new Exception("worker Id can't be greater than {$this->maxWorkerId} or less than 0");
        }
 
        if ($datacenterId > $this->maxDatacenterId || $datacenterId < 0) {
            throw new Exception("datacenter Id can't be greater than {$this->maxDatacenterId} or less than 0");
        }
 
        $this->workerId     = $workerId;
        $this->datacenterId = $datacenterId;
        $this->sequence     = $sequence;
    }
 
    public function nextId()
    {
        $timestamp = $this->timeGen();
 
        if ($timestamp < $this->lastTimestamp) {
            $diffTimestamp = bcsub($this->lastTimestamp, $timestamp);
            throw new Exception("Clock moved backwards.  Refusing to generate id for {$diffTimestamp} milliseconds");
        }
 
        if ($this->lastTimestamp == $timestamp) {
            $this->sequence = ($this->sequence + 1) & $this->sequenceMask;
 
            if (0 == $this->sequence) {
                $timestamp = $this->tilNextMillis($this->lastTimestamp);
            }
        } else {
            $this->sequence = 0;
        }
 
        $this->lastTimestamp = $timestamp;
 
        /*$gmpTimestamp    = gmp_init($this->leftShift(bcsub($timestamp, self::TWEPOCH), $this->timestampLeftShift));
        $gmpDatacenterId = gmp_init($this->leftShift($this->datacenterId, $this->datacenterIdShift));
        $gmpWorkerId     = gmp_init($this->leftShift($this->workerId, $this->workerIdShift));
        $gmpSequence     = gmp_init($this->sequence);
        return gmp_strval(gmp_or(gmp_or(gmp_or($gmpTimestamp, $gmpDatacenterId), $gmpWorkerId), $gmpSequence));*/
 
        return (($timestamp - self::TWEPOCH) << $this->timestampLeftShift) |
        ($this->datacenterId << $this->datacenterIdShift) |
        ($this->workerId << $this->workerIdShift) |
        $this->sequence;
    }
 
    protected function tilNextMillis($lastTimestamp)
    {
        $timestamp = $this->timeGen();
        while ($timestamp <= $lastTimestamp) {
            $timestamp = $this->timeGen();
        }
 
        return $timestamp;
    }
 
    protected function timeGen()
    {
        return floor(microtime(true) * 1000);
    }
 
    // Shift left<<
    protected function leftShift($a, $b)
    {
        return bcmul($a, bcpow(2, $b));
    }
}

Add a small point:

Hash function can also be called hash function. The function of hash function is only to pass your target key through a mapping method, or a function operation F, and finally get your target hashValue = f(key). Here, function f is called hash function / hash function.

The bottom layer of the array is hash hash;

Array: a linear table data structure that uses a continuous set of memory space to store a set of data of the same type.

Array to find duplicate and non duplicate values (small dots):

      //Use the idea of hash / bucket $res = [];
        foreach ($dataas$item) {
            if (array_key_exists($item, $res)) {
                ++$res[$item];
            } else {
                $res[$item] = 1;
            }
        }
        foreach ($resas$k => $v) {
            if ($v == 1) {
                echo $k;
            }
        }

Keywords: PHP Algorithm data structure Back-end

Added by sublimenal on Thu, 03 Mar 2022 09:21:37 +0200