What is the order number per hour?

// 
$ymdh = date("Y/m/d H");

// 
$findOrderSoFar = mysqli_fetch_array($pdo->query(
    "SELECT count(public_order_id) as num FROM `order_record`
    WHERE FROM_UNIXTIME(add_time, "%Y/%m/%d %H") = "{$ymdh}" "
));

//  $i 
$i = $findOrderSoFar["num"];

// 
$findOrderSoFar["num"] == 0 ? $i = 1 : $i = $findOrderSoFar["num"];

// 
while ($row = mysqli_fetch_array($sql)) {

    // 
    $_SESSION["public_order_id"] = substr(date("YmdH", time()), -8).str_pad($i, 4, "0" ,STR_PAD_LEFT);
    
    // ...
    $i PP;
}

this is what I do now, but I still repeat the serial number
that is, it still happens when different users place orders at the same time.
my logic is dead.
the order number format will be:
YYMMDDHH0001
YYMMDDHH0002...
but in the next hour, it will change back to YYMMDDHH0001

.
Jun.24,2022

To avoid ID duplication, you can use Redis to build a distributed ID generator, using the incr command, where all ID is generated.

https://codeshelper.com/a/11...


query the maximum order number and save the newly generated order number to the database. There are three approaches to
1. When querying the order number, use select for update, lock the table, then query the maximum order number, generate a new order number, save, and commit the transaction.
advantages: simple, sequential thinking
disadvantages: poor performance
2. Create a separate order number sequence table, simply click three fields id, key, val,step. Insert a record
insert into t (key,val,step) values ('orderNo',1,1);
then generate a new order number update t set val=val+step where key='orderNo';
at this time, do not commit the transaction. After select val from where key='orderNo';
checks in the same transaction, commit the transaction, and val is the new order number.
advantage: good performance
disadvantage: out of order thinking, need to create a new table.
3. Use redis, as mentioned above, using redis's incr command, because it is an atomic operation and ensures the uniqueness of the order number.
advantage: fastest
disadvantage: need to deploy redis service, program needs to add libraries to access redis, need to be familiar with redis command


I'll post a code that generates the order number on our production environment to show the landlord. We can change it according to this mode

.
    /**
     * 
     */
    public static function generateOutTradeNo($paidScene = Constant::PAID_SCENE_SEMINAR_ORDER){
        $prefix = date('YmdHis');
        $paidSceneMap = self::getPaidSceneMapping();
        $scene = formatArrValue($paidSceneMap,$paidScene,'0001');
        $suffix = generateRandomNum(10);
        return $prefix.$scene.$suffix;
    }
    
    /**
     * map
     */
    public static function getPaidSceneMapping(){
        return [
            Constant::PAID_SCENE_SEMINAR_ORDER => '0001',
            Constant::PAID_SCENE_SHOP_GOODS_ORDER => '0002'
        ];
    }
    
    /**
     * : 
     * : String
     */
    function generateRandomNum($len=8){
    
        $minArr = [];
        $maxArr = [];
        for($i=0;$i<$len;$iPP){
            $min = $i == $len -1 ? 1 : 0;
            array_push($minArr,$min);
            $max = 9;
            array_push($maxArr,$max);
        }
        $minLimit = implode('',$minArr);
        $maxLimit = implode('',$maxArr);
        $num = mt_rand($minLimit,$maxLimit);
        return $num;
    }
    

order number is set to unique index
so only insert data fails and there is no duplicate order number

there are various processing methods after failed to insert data, such as retry 3 times, if not, the order creation failure will be returned


suggestion:
use redis to manage the generated order number, read the current order number from memory, add 1 to memory after reading, and then deal with subsequent logic, which can avoid collision for a long time

.
Menu