具有次要和主要节点的Ketama

时间:2014-02-03 22:54:47

标签: distributed-computing consistent-hashing

我需要多个密钥才能在多台计算机上存储数据。我使用Ketama一致哈希库工作,但是对于每个键,我想要2台机器来存储该密钥的数据,主要的和次要的。

我可以想象逆时针方向而不是顺时针方向(例如floorEntry而不是ceilingEntry)来查找辅助机器,但这需要更改我没有创作的库。< / p>

有没有办法在没有lib修改的情况下实现这一目标?一个想法是围绕环旋转180“度”,但不确定如何做到这一点。

奖金/可选:除了给定密钥的主要和辅助机器之外,如何找到第三台机器?

1 个答案:

答案 0 :(得分:0)

从分布式密钥库的论文The PRO key-value store 找到一个简单的解决方案。

  

存储键值对时,顺时针方向从下一个服务器开始   (大于或等于)哈希值是主节点,而   下一个不同的节点(后继者)是次要的。

我通过保留primary-&gt;辅助节点的索引来找出“下一个”节点。对n备份节点的支持就像以类似方式构建Node->List[Node]地图一样简单。在Scala中,使用Twitter的KetamaDistributor,这可能看起来像:

import Partitioner._

case class Partition(page: String, primary: String, secondary: String)

class Partitioner(pagesIds: Seq[String], nodes: SortedSet[String]) {

  val ketamaNodes = nodes.map { host => KetamaNode(host, defaultNodeWeight, host) }
  val ketamaDistributor = new KetamaDistributor(ketamaNodes, numReps)

  // Build a map of primary->secondary nodes
  val nodeIndex: Map[String, String] = nodes.sliding(2).foldLeft(Map[String, String]()) {
    case (acc, Vector(x,y)) => acc.updated(x, y)
  } ++ Map(nodes.last -> nodes.head)

  def partitions = {
    pages.map { page =>
      val hash = KeyHasher.KETAMA.hashKey(page)
      val primary = ketamaDistributor.nodeForHash(hash)
      Partition(page, primary, nodeIndex(primary)
    }
  }

}

object Partitioner {
  val numReps = 160
  val defaultNodeWeight = 100
}

用法如下:

def uuid = java.util.UUID.randomUUID.toString
val nodes = (1 to 6).map { i => new Backend(s"machine-$i") }
val pages = (1 to 100).map { _ => uuid }
val partitioner = new Partitioner(pages, nodes)
val partitions = partitioner.partitions
// find the primary and secondary server for a given page
partitions(page.head)
// => Partition(f7eba506-e366-4cf3-ad72-4992fc5431b0,machine-5,machine-6)