class SnowFlake::ID

example SnowFlake::ID.new(1,1).next_id

Attributes

datacenter_id[RW]
datacenter_id_bits[RW]
datacenter_id_shift[RW]
last_timestamp[RW]
max_datacenter_id[RW]
max_worker_id[RW]
sequence[RW]
sequence_bits[RW]
sequence_mask[RW]
timestamp_left_shift[RW]
twepoch[RW]
worker_id[RW]
worker_id_bits[RW]
worker_id_shift[RW]

Public Class Methods

new(worker_id, datacenter_id) click to toggle source

@param worker_id 工作ID (0~31) @param datacenter_id 数据中心ID (0~31)

# File lib/snow_flake.rb, line 24
def initialize(worker_id, datacenter_id)
  self.twepoch = 1420041600000 # start time (2015-01-01)
  self.worker_id_bits = 5 # worker id bits
  self.datacenter_id_bits = 5 # datacenter id bits
  # Supported maximum worker id, resulting in 31
  self.max_worker_id = -1 ^ (-1 << worker_id_bits)
  # Supported maximum datacenter id, resulting in 31
  self.max_datacenter_id = -1 ^ (-1 << datacenter_id_bits)
  self.sequence_bits = 12 # The number of sequences in ID
  # The machine ID moves to the left 12 bits.
  self.worker_id_shift = sequence_bits
  # The data identification ID moves to the left 17 bits (12+5)
  self.datacenter_id_shift = sequence_bits + worker_id_bits
  # The time is shifted to the left by 22 bits(5+5+12)
  self.timestamp_left_shift = sequence_bits + worker_id_bits + datacenter_id_bits
  # The mask of generating sequence is 4095 (0b111111111111=0xfff=4095)
  self.sequence_mask = -1 ^ (-1 << sequence_bits)
  self.sequence = 0 # Millisecond sequence(0~4095)
  self.last_timestamp = -1 # Last timestamp of ID generation
  if worker_id > max_worker_id || worker_id < 0
    raise "worker Id can't be greater than #{max_worker_id} or less than 0"
  end
  if datacenter_id > max_datacenter_id || datacenter_id < 0
    raise "datacenter Id can't be greater than #{max_datacenter_id} or less than 0"
  end
  self.worker_id = worker_id # worker ID(0~31)
  self.datacenter_id = datacenter_id # datacenter ID(0~31)
end

Public Instance Methods

next_id() click to toggle source
# File lib/snow_flake.rb, line 53
def next_id
  timestamp = time_gen
  if timestamp < last_timestamp
    raise "Clock moved backwards.  Refusing to generate id for #{last_timestamp - timestamp} milliseconds"
  end
  if last_timestamp == timestamp
    self.sequence = (sequence + 1) & sequence_mask
    timestamp = till_next_millis(last_timestamp) if sequence.zero?
  else
    self.sequence = 0
  end
  self.last_timestamp = timestamp
  ((timestamp - twepoch) << timestamp_left_shift) | (datacenter_id << datacenter_id_shift) | (worker_id << worker_id_shift) | sequence
end
till_next_millis(last_timestamp) click to toggle source
# File lib/snow_flake.rb, line 68
def till_next_millis(last_timestamp)
  timestamp = time_gen
  timestamp = time_gen while timestamp <= last_timestamp
  timestamp
end
time_gen() click to toggle source
# File lib/snow_flake.rb, line 74
def time_gen
  (Time.now.to_f * 1000).floor
end