snowflake的JAVA版本

本文介绍了一种基于 Twitter Snowflake 算法的 ID 生成器实现,该生成器能够生成全局唯一且递增的长整型数字 ID,适用于分布式系统中。文章详细解释了 ID 的组成部分,包括时间戳、数据中心 ID、工作节点 ID 和序列号,并通过测试类验证了其并发生成不重复 ID 的能力。
摘要由CSDN通过智能技术生成
  1. /**
  2. * @author zhujuan
  3. * From: https://github.com/twitter/snowflake
  4. * An object that generates IDs.
  5. * This is broken into a separate class in case
  6. * we ever want to support multiple worker threads
  7. * per process
  8. */
  9. public class IdWorker {
  10. protected static final Logger LOG = LoggerFactory.getLogger(IdWorker.class);
  11. private long workerId;
  12. private long datacenterId;
  13. private long sequence = 0L;
  14. private long twepoch = 1288834974657L;
  15. private long workerIdBits = 5L;
  16. private long datacenterIdBits = 5L;
  17. private long maxWorkerId = -1L ^ (-1L << workerIdBits);
  18. private long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
  19. private long sequenceBits = 12L;
  20. private long workerIdShift = sequenceBits;
  21. private long datacenterIdShift = sequenceBits + workerIdBits;
  22. private long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
  23. private long sequenceMask = -1L ^ (-1L << sequenceBits);
  24. private long lastTimestamp = -1L;
  25. public IdWorker(long workerId, long datacenterId) {
  26. // sanity check for workerId
  27. if (workerId > maxWorkerId || workerId < 0) {
  28. throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
  29. }
  30. if (datacenterId > maxDatacenterId || datacenterId < 0) {
  31. throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
  32. }
  33. this.workerId = workerId;
  34. this.datacenterId = datacenterId;
  35. LOG.info(String.format("worker starting. timestamp left shift %d, datacenter id bits %d, worker id bits %d, sequence bits %d, workerid %d", timestampLeftShift, datacenterIdBits, workerIdBits, sequenceBits, workerId));
  36. }
  37. public synchronized long nextId() {
  38. long timestamp = timeGen();
  39. if (timestamp < lastTimestamp) {
  40. LOG.error(String.format("clock is moving backwards. Rejecting requests until %d.", lastTimestamp));
  41. throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
  42. }
  43. if (lastTimestamp == timestamp) {
  44. sequence = (sequence + 1) & sequenceMask;
  45. if (sequence == 0) {
  46. timestamp = tilNextMillis(lastTimestamp);
  47. }
  48. } else {
  49. sequence = 0L;
  50. }
  51. lastTimestamp = timestamp;
  52. return ((timestamp - twepoch) << timestampLeftShift) | (datacenterId << datacenterIdShift) | (workerId << workerIdShift) | sequence;
  53. }
  54. protected long tilNextMillis(long lastTimestamp) {
  55. long timestamp = timeGen();
  56. while (timestamp <= lastTimestamp) {
  57. timestamp = timeGen();
  58. }
  59. return timestamp;
  60. }
  61. protected long timeGen() {
  62. return System.currentTimeMillis();
  63. }

  1. }



测试类



  1. public class IdWorkerTest {
  2. static class IdWorkThread implements Runnable {
  3. private Set<Long> set;
  4. private IdWorker idWorker;
  5. public IdWorkThread(Set<Long> set, IdWorker idWorker) {
  6. this.set = set;
  7. this.idWorker = idWorker;
  8. }
  9. @Override
  10. public void run() {
  11. while (true) {
  12. long id = idWorker.nextId();
  13. if (!set.add(id)) {
  14. System.out.println("duplicate:" + id);
  15. }
  16. }
  17. }
  18. }
  19. public static void main(String[] args) {
  20. Set<Long> set = new HashSet<Long>();
  21. final IdWorker idWorker1 = new IdWorker(0, 0);
  22. final IdWorker idWorker2 = new IdWorker(1, 0);
  23. Thread t1 = new Thread(new IdWorkThread(set, idWorker1));
  24. Thread t2 = new Thread(new IdWorkThread(set, idWorker2));
  25. t1.setDaemon(true);
  26. t2.setDaemon(true);
  27. t1.start();
  28. t2.start();
  29. try {
  30. Thread.sleep(30000);
  31. } catch (InterruptedException e) {
  32. e.printStackTrace();
  33. }
  34. }
  35. }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值