Rumah >Java >javaTutorial >Cara menjana ID melalui edaran salji SnowFlake tulisan tangan di Jawa
Hasil id yang dijana oleh algoritma SnowFlake ialah integer 64-bit Strukturnya adalah seperti berikut:
dibahagikan kepada. empat bahagian:
Perenggan pertama: Bit 1 tidak digunakan dan sentiasa ditetapkan pada 0.
(Oleh kerana bit tertinggi dalam binari ialah bit tanda, 1 mewakili nombor negatif, dan 0 mewakili nombor positif. ID yang dijana biasanya integer positif, jadi bit tertinggi ditetapkan kepada 0)
Segmen Kedua: 41 bit ialah masa milisaat (panjang 41 bit boleh digunakan selama 69 tahun)
Segmen ketiga: 10 bit ialah workerId (panjang 10 bit menyokong penggunaan sehingga 1024 nod)
(10 digit di sini dibahagikan kepada dua bahagian. 5 digit pertama mewakili ID pusat data (0-31) dan bahagian kedua 5 digit mewakili ID mesin (0-31))
Perenggan keempat: 12 digit Mengira dalam milisaat (nombor urutan pengiraan 12-bit menyokong setiap nod yang menjana nombor bersiri ID 4096 setiap milisaat)
Pelaksanaan kod:
import java.util.HashSet; import java.util.concurrent.atomic.AtomicLong; public class SnowFlake { //时间 41位 private static long lastTime = System.currentTimeMillis(); //数据中心ID 5位(默认0-31) private long datacenterId = 0; private long datacenterIdShift = 5; //机房机器ID 5位(默认0-31) private long workerId = 0; private long workerIdShift = 5; //随机数 12位(默认0~4095) private AtomicLong random = new AtomicLong(); private long randomShift = 12; //随机数的最大值 private long maxRandom = (long) Math.pow(2, randomShift); public SnowFlake() { } public SnowFlake(long workerIdShift, long datacenterIdShift){ if (workerIdShift < 0 || datacenterIdShift < 0 || workerIdShift + datacenterIdShift > 22) { throw new IllegalArgumentException("参数不匹配"); } this.workerIdShift = workerIdShift; this.datacenterIdShift = datacenterIdShift; this.randomShift = 22 - datacenterIdShift - workerIdShift; this.maxRandom = (long) Math.pow(2, randomShift); } //获取雪花的ID private long getId() { return lastTime << (workerIdShift + datacenterIdShift + randomShift) | workerId << (datacenterIdShift + randomShift) | datacenterId << randomShift | random.get(); } //生成一个新的ID public synchronized long nextId() { long now = System.currentTimeMillis(); //如果当前时间和上一次时间不在同一毫秒内,直接返回 if (now > lastTime) { lastTime = now; random.set(0); return getId(); } //将最后的随机数,进行+1操作 if (random.incrementAndGet() < maxRandom) { return getId(); } //自选等待下一毫秒 while (now <= lastTime) { now = System.currentTimeMillis(); } lastTime = now; random.set(0); return getId(); } //测试 public static void main(String[] args) { SnowFlake snowFlake = new SnowFlake(); HashSet<Long> set = new HashSet<>(); for (int i = 0; i < 10000; i++) { set.add(snowFlake.nextId()); } System.out.println(set.size()); } }
Kaedah mendapatkan id dalam kod menggunakan bit Pelaksanaan Operasi
Memandangkan SnowFlake sangat bergantung pada cap masa, perubahan masa akan menyebabkan ralat dalam SnowFlake algoritma.1 | 00000|0 0000|0000 00000000 //41 digit masa
0|0000000 00000000 00000000 00000000 00000000 00000000 00|0 00 | -digit ID pusat data
0 |0000000 00000000 00000000 00000000 00000000 00|00000|1 1001|0000 00000000 //5 digit ID mesin
0.00000 0000000 00000000 00|00000| urutan
-------------------------------------------------------- ----- ------------------------------------------------ ---
0|0001100 10100010 10111110 10001001 01011100 00|10001|1 1001|0000 00000000 //Keputusan 9>Kelebihan SnowFlake :
Semua dijana id meningkat dalam aliran masa ID pendua tidak akan dijana dalam keseluruhan sistem yang diedarkan (kerana terdapat datacenterId dan workerId untuk dibezakan) Kekurangan SnowFlake:
Atas ialah kandungan terperinci Cara menjana ID melalui edaran salji SnowFlake tulisan tangan di Jawa. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!