美文网首页
Tp6 类库&雪花算法

Tp6 类库&雪花算法

作者: HueyYao | 来源:发表于2020-11-28 22:20 被阅读0次

    Tp6 类库&雪花算法

    在产生订单时 订单号的生成使用雪花算法

    这里通过在tp6这个场景下 通过类库的方式 来使用此算法生成订单号

    首先在订单控制器层同 引用类类库

    <?php
    namespace app\api\controller\order;
    use app\api\controller\ApiBase;
    use app\common\lib\Show;
    use app\common\business\Order;
    class Index extends ApiBase{
        public function save(){
            $addressId = input("param.address_id",0,"intval");
            $ids = input("param.ids",0,"trim");
            $addressId = 1;
            if(!$addressId || !$ids){
                return Show::error("参数错误");
            }
            $this->userId = 6;
            $data = [
                'ids' => $ids,
                'address_id' => $addressId,
                'user_id' => $this->userId,
            ];
            try {
                $result = (new Order())->save($data);
            } catch (\Exception $e) {
                return Show::error($e->getMessage());
            }
            if(!$result){
                return Show::error("订单创建失败");
            }
    
            return Show::success($result);
        }
    }
    

    通过在控制器中调用Order业务层save方法

    <?php
    namespace app\common\business;
    use app\common\lib\idwork;
    class Order extends BusBase{
    
        public $model = NULL;
    
        public function __construct(){
    
            $this->model = new OrderModel();
        }
        //保存订单 此处只针对订单号的生成
        public function save($data){
            //拿到订单号
            $workId =  rand(1,1023);
            $orderId = idwork::getInstance()->setWorkId($workId)->nextId();
         }
    }
    

    idwork类库 lib文件下的idwork.php

    <?php
    /**
     * ID 生成策略
     * 毫秒级时间41位+机器ID, 10位+毫秒内序列12位。高位始终为0,表示正数。
     * 0           41     51     64
     * +-----------+------+------+
     * |time       |pc    |inc   |
     * +-----------+------+------+
     *  前41bits是以微秒为单位的timestamp。
     *  接着10bits是事先配置好的机器ID。
     *  最后12bits是累加计数器。
     *  macheine id(10bits)标明最多只能有1024台机器同时产生ID,sequence number(12bits)也标明1台机器1ms中最多产生4096个ID,
     *
     */
    namespace app\common\lib;
    class IdWork
    {
        private static $workerId;
        private static $maxWorkerId = 1023; //最大的机器节点, 2^10 - 1
    
        private static $sequence = 0;
        private static $sequenceMask = 4095; //最大的序列节点, 2^12 - 1
    
        private static $workerIdShift = 12; //机器ID左移位数,63 - 51
        private static $timestampLeftShift = 22; //毫秒时间戳左移位数,63 - 41
    
        private static $twepoch = 1288834974657;
        private static $lastTimestamp = -1;
    
        /**
         * @var self
         */
        private static $self = null;
    
        /**
         * @return self
         */
        public static function getInstance()
        {
            if (self::$self == null) {
                self::$self = new self();
            }
            return self::$self;
        }
    
        public function setWorkId($workId)
        {
            if ($workId > self::$maxWorkerId || $workId < 0) {
                throw new \Exception("worker Id can't be greater than ".self::$maxWorkerId." or less than 0");
            }
            self::$workerId = $workId;
            return self::$self;
        }
    
        private function timeGen()
        {
            //获得当前时间戳
            $time = explode(' ', microtime());
            $time2 = substr($time[0], 2, 3);
            return $time[1] . $time2;
        }
    
        private function tilNextMillis($lastTimestamp)
        {
            $timestamp = $this->timeGen();
            while ($timestamp <= $lastTimestamp) {
                $timestamp = $this->timeGen();
            }
            return $timestamp;
        }
    
        public function nextId()
        {
            $timestamp = $this->timeGen();
    
            //如果存在并发调用,则自增sequence
            if (self::$lastTimestamp == $timestamp) {
                self::$sequence = (self::$sequence + 1) & self::$sequenceMask;
    
                //如果sequence自增到4095,也就是4096 & 4095 = 0,重新取时间戳
                if (self::$sequence == 0) {
                    $timestamp = $this->tilNextMillis(self::$lastTimestamp);
                }
            } else {
                self::$sequence = 0;
            }
    
            if ($timestamp < self::$lastTimestamp) {
                throw new \Exception("Clock moved backwards.  Refusing to generate id for " . (self::$lastTimestamp - $timestamp) . " milliseconds");
            }
    
            self::$lastTimestamp = $timestamp;
    
            if (PHP_INT_SIZE === 4) {
                return 0;
            }
    
            $nextId = ((sprintf('%.0f', $timestamp) - sprintf(
                '%.0f',
                self::$twepoch
            )) << self::$timestampLeftShift) | (self::$workerId << self::$workerIdShift) | self::$sequence;
    
            return $nextId;
        }
    }
    

    相关文章

      网友评论

          本文标题:Tp6 类库&雪花算法

          本文链接:https://www.haomeiwen.com/subject/qwzcwktx.html