返回

一致性哈希算法实现负载均衡的原理

见解分享

Elasticsearch分布式的操作(四)

搜索路由:基于一致性哈希(Consistent Hash)

我们知道在创建索引的时候我们时可以决定创建多少个主分片(只能创建的时候指定,以后不可修改)和多少个复制分片(副分片,创建的时候可以改变,之后也可以改变)。Elasticsearch有这个规定实际上是为了剪碎文档,它检索文档是基于一个简单的算法来决定的。这里的routing是一个散列值,默认使用Murmur3进行计算。Murmur3是一种很高效的散列算法,它对长字符串计算速度非常快,并且分布很均匀。这里要记住routing只是用来进行路由,即用来决定文档最终要放到哪个主分片。而分片号仅仅只是该分片在整个索引中的编号。

路由算法是一个函数f(routing,num_primary),返回一个分片号。假设routing是文档的唯一id,那么对于一个num_primary=5的主分片来说,则可以通过下面的算法来计算该文档最终会被路由到哪个主分片。

int shard_num = f(routing, 5) = murmur3(routing) % 5;

从上面的公式不难看出,那么我们是否可以很轻松的预测出该文档会被路由到哪个分片呢?假设我们采用哈希取模的方式,将routing的值对主分片的数量进行取模,那很容易就可以预测出文档会落在哪个分片。但是这里有个问题,它不利于负载均衡,当主分片数发生变更的时候,这个计算结果也会发生变化,那么原来落在一个分片的所有文档都会在分片调整的时候全部迁移到另一个分片。Elasticsearch采用了一种叫一致性哈希(Consistent Hash)的算法来避免这种问题,这种算法具有以下优点:

  • 负载均衡,数据分布的比较均匀
  • 当添加或删除分片的时候,只会影响很小一部分数据。
shard_num = f(routing, 5) = consistentHash(routing, [{1}, {2}, {3}, {4}, {5}])

从上面的公式可以看出,我们现在不再是将routing直接对主分片数量进行取模了,而是将routing的值以及主分片号作为参数传给一致性哈希函数进行计算。这种算法的计算过程比较复杂,但我们可以直接通过java.util.hash中的Hashing来进行计算。

举个例子,假设我们现在创建了一个索引,并且创建了5个主分片,现在我们插入两条数据,routing分别是id1和id2。那么我们可以通过下面的代码来计算这两条数据落在哪个分片上。

int shard_num = Hashing.consistentHash(id1, Arrays.asList({1}, {2}, {3}, {4}, {5}));
int shard_num = Hashing.consistentHash(id2, Arrays.asList({1}, {2}, {3}, {4}, {5}));

这里要注意一点,由于在真实的生产环境中,我们会采用一台或多台机器来存储数据。那么我们就需要考虑到分片与节点之间的映射关系。我们知道每个节点可以存储多个分片,当我们计算出该文档所在的路由后,再根据该分片所在的节点来确定文档最终存放的位置。

shard_num = f(routing, [{1}, {2}, {3}, {4}, {5}])
node_num = g(shard_num, [{node1}, {node2}, {node3}])

我们利用consistentHash来将数据均匀的分布在各主分片上,如果当主分片数发生变化的时候,我们是否还需要重新计算数据所在的路由呢?换句话说,当我们增加或减少一个主分片的时候,这个主分片上所有的数据是不是都要迁移到其他分片上呢?答案是不需要的,因为我们使用的是一致性哈希算法,它的优点就是当新增或减少主分片的时候,不会造成大部分数据的迁移,而只会影响很小一部分数据迁移。

在Elasticsearch中,每个索引可以有多个主分片和复制分片。主分片是存储数据的物理位置,而复制分片是主分片的备份。当数据写入到Elasticsearch时,它会被均匀地分布在各主分片上。如果某个主分片发生故障,那么它的数据会从复制分片中恢复。

一致性哈希算法是Elasticsearch用于实现负载均衡的算法。它可以将数据均匀地分布在各主分片上,并且当新增或减少主分片时,只会影响很小一部分数据迁移。

一致性哈希算法的原理如下:

  1. 将每个主分片分配一个虚拟节点。
  2. 将每个数据项的键值计算出一个哈希值。
  3. 将数据项的哈希值与虚拟节点的哈希值进行比较,并将数据项分配给哈希值最接近的虚拟节点。

这样,当新增或减少主分片时,只需要重新计算虚拟节点的哈希值,而不会影响大部分数据项的分配。

一致性哈希算法在Elasticsearch中的应用如下:

  1. 当数据写入到Elasticsearch时,它会被均匀地分布在各主分片上。
  2. 如果某个主分片发生故障,那么它的数据会从复制分片中恢复。
  3. 当新增或减少主分片时,只会影响很小一部分数据迁移。

一致性哈希算法是一种简单高效的负载均衡算法,它可以将数据均匀地分布在各主分片上,并且当新增或减少主分片时,只会影响很小一部分数据迁移。