php snowflake algorithm SnowFlake generates unique ID

The advantage of this algorithm is very simple. It can generate about 400W different 16-bit digital IDs (decimal) per second.

Extended reading:

https://segmentfault.com/a/1190000021244328 The                      laravel framework installs third-party packages through composer to implement the snowflake algorithm

https://blog.csdn.net/JineD/article/details/107141757             Another blog post of mine, forget Snowflake and feel the global unique ID generation algorithm with 587 times higher performance

One, analysis of the principle of snowflake algorithm

1. Common generation strategies for distributed ID:

  The common distributed ID generation strategies are as follows:

  1. The database self-increasing ID.
  2. UUID is generated.
  3. Redis's atomic self-increment method.
  4. Split the database horizontally, set the initial value and the same increment step size.
  5. Apply for self-increment ID in batches.
  6. Snow algorithm.
  7. Baidu UidGenerator algorithm (based on snowflake algorithm to achieve custom timestamp).
  8. Meituan Leaf algorithm (depends on database, ZK).

  This article mainly introduces the SnowFlake algorithm, which is Twitter's open source distributed id generation algorithm.

  The core idea is to use a 64-bit long number as the globally unique id. It is widely used in distributed systems, and ID introduces a timestamp to maintain self-increment and non-repetition.

2. The structure of the snowflake algorithm:

  Mainly divided into 5 parts:

  1. It is 1 bit: 0, which is meaningless.
  2. It is 41 bits: it means the time stamp.
  3. It is 10 bits: it means the ID of the computer room, 0000000000, because what I passed in is 0.
  4. It is 12 bits: the serial number represented is the serial number of the id generated at the same time in this millisecond on a certain machine in a certain computer room, 0000 0000 0000.

  Next we will explain the four parts:

1 bit is meaningless:

  Because the first bit in the binary is 1, if it is 1, then it is all negative, but the ids we generate are all positive, so the first bit is uniformly 0.

41 bit: indicates the timestamp, in milliseconds.

  41 bit can represent as many numbers as 2^41-1, that is, it can identify 2 ^ 41-1 milliseconds, and converted into years is 69 years.

10 bit: Record the working machine id, which means that this service can be deployed on up to 2^10 machines, which is 1024 machines.

  However, 5 bits of 10 bits represent the ID of the computer room, and 5 bits represent the ID of the machine. It means that at most 2 ^ 5 computer rooms (32 computer rooms) can be represented, and each computer room can represent 2 ^ 5 machines (32 machines), which can be split at will, for example, 4 digits to identify the business number, and the other 6 digits As the machine number. Can be combined at will.

12 bit: This is used to record different IDs generated in the same millisecond.

  The largest positive integer that 12 bit can represent is 2 ^ 12-1 = 4096, which means that the number represented by this 12 bit can be used to distinguish 4096 different IDs within the same millisecond. That is, the maximum number of IDs generated by the same machine in the same millisecond is 4096

   To put it simply, if a certain service of yours is to generate a globally unique id, then you can send a request to the system deployed with the SnowFlake algorithm, and the SnowFlake algorithm system will generate the unique id. The SnowFlake algorithm system must first know the machine number where it is located (here, let’s talk about all 10 bits as the working machine ID) and then after the SnowFlake algorithm system receives this request, it will first generate a 64-bit long using binary bit operations. Type id, the first bit in 64 bits is meaningless. Then use the current timestamp (unit to milliseconds) to occupy 41 bits, and then set the machine id with 10 bits. Finally, let's make a judgment. This is the first request within this millisecond on this machine in the current computer room. Add a serial number to the request that generates the id this time, as the last 12 bits.

 

Two, PHP source code implementation case

demo1:

<?php
 
/**
 * 雪花算法类
 * @package app\helpers
 */
class SnowFlake
{
    const EPOCH = 1479533469598;
    const max12bit = 4095;
    const max41bit = 1099511627775;
 
    static $machineId = null;
 
    public static function machineId($mId = 0) {
        self::$machineId = $mId;
    }
 
    public static function generateParticle() {
        /*
        * Time - 42 bits
        */
        $time = floor(microtime(true) * 1000);
 
        /*
        * Substract custom epoch from current time
        */
        $time -= self::EPOCH;
 
        /*
        * Create a base and add time to it
        */
        $base = decbin(self::max41bit + $time);
 
 
        /*
        * Configured machine id - 10 bits - up to 1024 machines
        */
        if(!self::$machineId) {
            $machineid = self::$machineId;
        } else {
            $machineid = str_pad(decbin(self::$machineId), 10, "0", STR_PAD_LEFT);
        }
 
        /*
        * sequence number - 12 bits - up to 4096 random numbers per machine
        */
        $random = str_pad(decbin(mt_rand(0, self::max12bit)), 12, "0", STR_PAD_LEFT);
 
        /*
        * Pack
        */
        $base = $base.$machineid.$random;
 
        /*
        * Return unique time id no
        */
        return bindec($base);
    }
 
    public static function timeFromParticle($particle) {
        /*
        * Return time
        */
        return bindec(substr(decbin($particle),0,41)) - self::max41bit + self::EPOCH;
    }
}

demo2:

<?php
 public function createID(){
        //假设一个机器id
        $machineId = 1234567890;
 
        //41bit timestamp(毫秒)
        $time = floor(microtime(true) * 1000);
 
        //0bit 未使用
        $suffix = 0;
 
        //datacenterId  添加数据的时间
        $base = decbin(pow(2,40) - 1 + $time);
 
        //workerId  机器ID
        $machineid = decbin(pow(2,9) - 1 + $machineId);
 
        //毫秒类的计数
        $random = mt_rand(1, pow(2,11)-1);
 
        $random = decbin(pow(2,11)-1 + $random);
        //拼装所有数据
        $base64 = $suffix.$base.$machineid.$random;
        //将二进制转换int
        $base64 = bindec($base64);
 
        $id = sprintf('%.0f', $base64);
 
        return $id;
    }

 

Guess you like

Origin blog.csdn.net/JineD/article/details/112037367