首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么这段代码会生成重复的id?

为什么这段代码会生成重复的id?
EN

Stack Overflow用户
提问于 2019-06-08 07:00:51
回答 1查看 79关注 0票数 1

我有以下代码来生成唯一的eventId。这不是一个纯粹的GUID生成器,而是一种跨不同机器/进程生成唯一id的方法。

代码语言:javascript
复制
import java.util.concurrent.atomic.AtomicInteger

object EventIdGenerator extends Serializable {
  val totalBits = 64
  private val epochBits = 42
  private val partitionIdBits = 10
  private val sequenceBits = 12
  private val sequenceInt = new AtomicInteger(0)

  private val maxPartitionId = (Math.pow(2, partitionIdBits) - 1).toInt
  private val maxSequenceId = (Math.pow(2, sequenceBits) - 1).toInt

  def nextEventId(partitionId: Int): Long = {
    assert(partitionId <= maxPartitionId)

    val nextSequence = sequenceInt.incrementAndGet() % maxSequenceId

    val timestamp =  if (nextSequence == 0) {
      Thread.sleep(1)
      System.currentTimeMillis()
    } else System.currentTimeMillis()

    timestamp << (totalBits - epochBits) |
    partitionId << (totalBits - epochBits - partitionIdBits) |
    nextSequence
  }
}

这应该是从运行在不同机器上的几个JVM上的分布式程序调用的。在这里,分区id在不同的JVM和机器上是唯一的。

当我在单线程中运行这个程序时,它工作得很好。但是,当我在多个线程中运行它时,每个线程都使用唯一的分区id调用nextEventId,有时我会得到重复的事件id。我不知道下面的代码出了什么问题。

EN

回答 1

Stack Overflow用户

发布于 2019-06-08 16:06:46

您只有1024个不同的nextSequence值。因此,如果您的请求速率超过每毫秒1024 (对于一个分区),则有大约100%的机会发生冲突。事实上,我相信由于时钟精度的原因,碰撞将以更小的速率出现。

我看到如果您检测到nextSequence溢出,您会尝试使用sleep(1)来避开它。但它不能在多线程环境中工作。特定分区甚至可能永远不会看到nextSequence等于0。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56502044

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档