The background of the Twitter-snowflake algorithm is quite simple, in order to meet the Twitter request for tens of thousands of messages per second, each message must be assigned a unique ID, these IDs also need some general order (convenient for clients to sort), And the IDs generated by different machines in the distributed system must be different.
Snowflake the time stamp , the work machine ID, and the serial number together.
In addition to the top bit marked as unavailable, the remaining three sets of bit placeholders can be floated to see the specific business requirements. The following is a feasibility study of this algorithm
Console.WriteLine ("41bit Timestamp can support the algorithm life: {0}", (1L<< A) / (3600L* -*365*1000.0)); Console.WriteLine ("number of working machine IDs for 10bit: {0}", (1L<<Ten) -1); Console.WriteLine ("12bit sequence ID number: {0}", (1L<< A) -1);
Operation Result:
The 41bit timestamp can support the algorithm life:69.730570001014710bit number of working machine IDs:102312bit sequence ID number: 4095
By default, the 41bit timestamp (calculated from the current start) can support the algorithm using nearly a year, 10bit of work machine ID can support the 1023 machine, serial number support 1 milliseconds to generate 4095 the ID of the self-increment sequence. In theory, an application can generate 4.09 million self-increment IDs in 1 seconds, which can be used for nearly 70 years. Fully meet the needs of our daily development projects.
Work Machine ID Strictly speaking, the use of this bit can be process-level, machine-level words you can use the MAC address to uniquely mark the work machine, the work process level can use Ip+path to distinguish the work process. If you have fewer working machines, you can use a configuration file to set this ID is a good choice if the machine too much configuration file maintenance is a catastrophic thing. The bit segment of the working machine ID can also be further split, such as with the first 5 bit tags Workerid, the last 5 bit tag Datacenterid, the code is as follows:
classSnowflake {//the bit segment of the work machine ID is split into the first 5 bit tags workerid, and the last 5 bit flags Datacenterid Const intWorkeridbits =5; Const intDatacenteridbits =5; //serial number bit number Const intSequencebits = A; //Maximum number limit Const LongMaxworkerid =-1L^ (-1L<<workeridbits); Const LongMaxdatacenterid =-1L^ (-1L<<datacenteridbits); Private Const LongSequencemask =-1L^ (-1L<<sequencebits); //bitwise left Arithmetic moving amount Public Const intWorkeridshift =sequencebits; Public Const intDatacenteridshift = Sequencebits +workeridbits; Public Const intTimestampleftshift = sequencebits + workeridbits +datacenteridbits; //Serial number Record Private Long_sequence =0L; //time stamp record Private Long_lasttimestamp =-1L; Public LongWorkerid {Get;protected Set; } Public LongDatacenterid {Get;protected Set; } PublicSnowflake (LongWorkerid,LongDatacenterid,Longsequence =0L) {Workerid=Workerid; Datacenterid=Datacenterid; _sequence=sequence; //sanity check for Workerid if(Workerid > Maxworkerid | | Workerid <0) { Throw NewArgumentException (String.Format ("worker Id can ' t be greater than {0} or less than 0", Maxworkerid)); } if(Datacenterid > Maxdatacenterid | | Datacenterid <0) { Throw NewArgumentException (String.Format ("Datacenter Id can ' t is greater than {0} or less than 0", Maxdatacenterid)); } } /// <summary> ///Green time Stamp/// </summary> /// <returns></returns> Public LongTimegen () {DateTime jan1st1970=NewDateTime (1970,1,1,0,0,0, DATETIMEKIND.UTC);// return(Long) (Datetime.utcnow-jan1st1970). TotalMilliseconds; } ReadOnly Object_lock =NewObject (); Public Virtual LongNextID () {Lock(_lock) {vartimestamp =Timegen (); if(Timestamp <_lasttimestamp) { Throw NewInvalidsystemclock (String.Format ("found an exception with less recent timestamp {0} milliseconds", _lasttimestamp-timestamp)); } if(_lasttimestamp = =timestamp) {_sequence= (_sequence +1) &Sequencemask; if(_sequence = =0) { //the serial number exceeds the limit and the timestamp is re-takentimestamp =Tilnextmillis (_lasttimestamp); } } Else{_sequence=0; } _lasttimestamp=timestamp; //Snowflake Algorithm varid = (timestamp << timestampleftshift) |(Datacenterid<< datacenteridshift) |(Workerid<< workeridshift) |_sequence; returnID; } } /// <summary> ///time stamp re-fetch/// </summary> protected Virtual LongTilnextmillis (LongLasttimestamp) { vartimestamp =Timegen (); while(Timestamp <=Lasttimestamp) { //the new timestamp is greater than the old timestamp and is counted as a valid timestamptimestamp =Timegen (); } returntimestamp; } }
twitter-snowflake,64 bit self-increment ID algorithm detailed