当前位置:编程学习 > php >>

循环生成1000万条记录雪花算法生成唯一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万数据无重复记录
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,