1.session_create_id();
注:php 7.1新增的函数,用来生成session id,低版本无法使用。
2.生成uuid
- 看到某些人会用uuid去代替用户的uid
- 从代码中可以看出,通过unique生成一个以毫秒级时间戳为前缀的字符后md5加密
- 再通过分隔符进行分割后得到uuid
- 这种方式虽然极大程度的避免了uid的重复
- 但是生成的uid太长,足足36个字符,而且是混杂英文和数字符号的,可读性很差
- 而一般的uid中都是纯数值组成的
<?php
function generateUUid($strtoupper = false)
{
$charid = call_user_func($strtoupper ? 'strtoupper' : 'strtolower', md5(uniqid(microtime(true), true)));
$hyphen = chr(45);
$uuid = substr($charid, 0, 8) . $hyphen . substr($charid, 8, 4) . $hyphen . substr($charid, 12, 4) . $hyphen . substr($charid, 16, 4) . $hyphen . substr($charid, 20, 12);
return $uuid;
}
//结果:37f14a07-cb18-2e54-4e40-da1e2fa0456d
3.利用数据库主键索引递增
- 而最经常采用的方式应该是使用数据库的主键索引,因为主键索引必然唯一
- 这里很多人会疑惑,主键索引不是会从1开始吗,这uid会有1位数的?
- 小了,格局小了,你可以设置主键索引的offset,让他从100000开始,不就可以解决这个问题了吗
- 这时候有人又问,那主键索引增加不是有规律的吗,比如插一条,会自增1
- 这时候就可以设置主键索引的增长步长,让他插入一条的步长不为1即可
- 而为了让uid看起来更加没有关联性,你可以设置步长为基数,比如3
- 这样增长起来,就会是100000,100003,100006,100009,100012....
4.雪花算法
<?php
/**
* 分布式 id 生成类 组成: <毫秒级时间戳+机器id+序列号>
* 默认情况下41bit的时间戳可以支持该算法使用到2082年,10bit的工作机器id可以支持1023台机器,序列号支持1毫秒产生4095个自增序列id
*/
namespace redis_model;
class SnowflakeId
{
const EPOCH = 1641862815726; //开始时间,固定一个小于当前时间的毫秒数
const max12bit = 4095;
const max41bit = 1099511627775;
/**
* 生成唯一数字串
* @param int|null $machineId
* @return float|int
*/
public static function CreateOnlyId(int $machineId=null){
// 时间戳 42字节
$time = floor(microtime(true) * 1000);
// 当前时间 与 开始时间 差值
$time -= self::EPOCH;
// 二进制的 毫秒级时间戳
$base = decbin(self::max41bit + $time);
// 机器id 10 字节
if($machineId){
$machineId = str_pad(decbin($machineId), 10, "0", STR_PAD_LEFT);
}
// 序列数 12字节
$random = str_pad(decbin(mt_rand(0, self::max12bit)), 12, "0", STR_PAD_LEFT);
// 拼接
$base = $base.$machineId.$random;
// 转化为 十进制 返回
return bindec($base);
}
/**
* 生成memberID
* @param int|null $machineId 机器ID 最大值 999
* @return bool|string
*/
public static function createMemberId(int $machineId=null){
if($machineId > 999){
return false;
}
// 时间戳 42字节
$time = floor(microtime(true) * 1000);
// 当前时间 与 开始时间 差值
$time -= self::EPOCH;
// 二进制的 毫秒级时间戳
$base = decbin(self::max41bit + $time);
// 序列数 12字节
$random = str_pad(decbin(mt_rand(0, self::max12bit)), 12, "0", STR_PAD_LEFT);
// 拼接
$base = $base.null.$random;
// 转化为 十进制 返回
return bindec($base).$machineId.mt_rand(0,9);
}
/**
* 生成订单ID
* @param int|null $machineId
* @return string
*/
public static function createOrderId(int $machineId=null){
return "HB".self::CreateOnlyId($machineId).mt_rand(10,99).mt_rand(10,99);
}
}