雪花算法生成唯一ID PHP版

雪花算法生成唯一ID PHP版

由于最近对老的项目维护出现了订单编号重复的记录;所以对这块优化一下:雪花算法生成唯一ID;具体大家可以详细了解一下其核心思想;利用雪花算法生成了1000万条ID记录;未出现重复记录;实现过程如下,已测试验证过:
循环生成1000万条记录:

namespace App\Http\Controllers\Api;
use App\Lib\SnowFlake;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class SnowFlakeController extends Controller
{
	/**
	 * https://www.jianshu.com/p/fdebbb0ea785
	 * 雪花算法 生成唯一id
	 * @return \Illuminate\Http\JsonResponse
	 */
	public function snowFlakeId()
	{
		set_time_limit(0);
		ini_set('memory_limit', '2048M');
	
		//可批量插入
		$snowFlake = new SnowFlake;
		for($i = 0; $i < 10000000; $i++){
			$snow_flake_id = "";
			$snow_flake_id = $snowFlake->nextId();
			\DB::table('snow_flake_bak')->insert(['snow_flake_id' => $snow_flake_id]);
		}
		echo 'done--'.$i;die;
	}
}
生成代码:
namespace App\Lib;

/**
 * 雪花算法 生成唯一ID
 * Class Base62Convert
 * @package App\Lib
 */
class SnowFlake
{  
    //开始时间,固定一个小于当前时间的毫秒数即可  
    const twepoch =  1474992000000;//2016/9/28 0:0:0  
  
    //机器标识占的位数  
    const workerIdBits = 10;  
  
    //毫秒内自增数点的位数  
    const sequenceBits = 12;  
  
    protected $workId = 0;  
  
    //要用静态变量  
    static $lastTimestamp = -1;  
    static $sequence = 0;  
  
  
    function __construct($workId = 1){
        //机器ID范围判断  
        $maxWorkerId = -1 ^ (-1 << self::workerIdBits);
        if($workId > $maxWorkerId || $workId< 0){  
            throw new Exception("workerId can't be greater than ".$maxWorkerId." or less than 0");  
        }  
        //赋值  
        $this->workId = $workId;  
    }  
  
    //生成一个ID  
    public  function nextId(){
        $timestamp = $this->timeGen();  
        $lastTimestamp = self::$lastTimestamp;  
        //判断时钟是否正常  
        if ($timestamp < $lastTimestamp) {  
            throw new Exception("Clock moved backwards.  Refusing to generate id for %d milliseconds", ($lastTimestamp - $timestamp));  
        }  
        //生成唯一序列  
        if ($lastTimestamp == $timestamp) {  
            $sequenceMask = -1 ^ (-1 << self::sequenceBits);  
            self::$sequence = (self::$sequence + 1) & $sequenceMask;  
            if (self::$sequence == 0) {  
                $timestamp = $this->tilNextMillis($lastTimestamp);  
            }  
        } else {  
            self::$sequence = 0;  
        }  
        self::$lastTimestamp = $timestamp;  
        //  
        //时间毫秒/数据中心ID/机器ID,要左移的位数  
        $timestampLeftShift = self::sequenceBits + self::workerIdBits;  
        $workerIdShift = self::sequenceBits;  
        //组合3段数据返回: 时间戳.工作机器.序列  
        $nextId = (($timestamp - self::twepoch) << $timestampLeftShift) | ($this->workId << $workerIdShift) | self::$sequence;  
        return $nextId;  
    }  
  
    //取当前时间毫秒  
    protected function timeGen(){  
        $timestramp = (float)sprintf("%.0f", microtime(true) * 1000);  
        return  $timestramp;  
    }  
  
    //取下一毫秒  
    protected function tilNextMillis($lastTimestamp) {  
        $timestamp = $this->timeGen();  
        while ($timestamp <= $lastTimestamp) {  
            $timestamp = $this->timeGen();  
        }  
        return $timestamp;  
    }  
}

1000万数据无重复记录
在这里插入图片描述
记录数据:
在这里插入图片描述
总条数:
在这里插入图片描述
生成18位的随机数字;可根据实际需要前后加入英文字符等;工作中的日常可拿来封装后即用;

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值