灵魂一问:哪种一致性哈希算法才是解决分布式缓存问题的王者?

一致性哈希是由Karger等人于1997年提出的一种特殊的哈希算法,目的是解决分布式缓存的问题,现在在分布式系统中有着广泛的应用。本文将对ketama、jump consistent hash、rendezvous hash和maglev hash四种算法进行对比分析。

一、一致性哈希的特性

  • 平衡性

不同key通过算法映射后,可以比较均衡地分布到所有的后端节点上。

  • 单调性

当有新的节点上线后,系统中原有的key要么还是映射到原来的节点上,要么映射到新加入的节点上,不会出现从一个老节点重新映射到另一个老节点。

  • 稳定性

当服务发生扩缩容的时候,发生迁移的数据量尽可能少。

二、问题背景

假设我们有N个cache服务器节点,那如何将数据映射到这N个节点上呢,最简单的方法就是用数据计算出一个hash值,然后用hash值对N取模,如:hash(data) % N,这样只要计算出来的hash值比较均匀,那数据也就能比较均匀地映射到N个节点上了。但这带来的问题就是,如果发生扩缩容,节点的数量发生了变化,那很多数据的映射关系都会发生变化。显然这种方法虽然简单,但并不太能解决我们的需求。

三、四种常见一致性哈希算法

下面分别介绍对比四种比较常见的一致性哈希算法,看看一致性哈希算法是怎么解决这问题的。

1. 经典一致性哈希

经典的一致性哈希算法也就是我们常说的割环法 ,大家应该都比较熟悉。简单来说就是,我们把节点通过hash的方式,映射到一个范围是[0,2^32]的环上,同理,把数据也通过hash的方式映射到环上,然后按顺时针方向查找第一个hash值大于等于数据的hash值的节点,该节点即为数据所分配到的节点。而更好点的做法是带虚拟节点的方法,我们可以为每个物理节点分配若干个虚拟节点,然后把虚拟节点映射到hash环,分配给每个物理节点虚拟节点数量对应每个物理节点的权重,如下图1所示。这样还是按顺时针的方法查找数据所落到的虚拟节点,再看该虚拟节点是属于哪个物理节点就可以知道数据是分配给哪个物理节点了。

图1

这种割环法的实现多种,下面以比较有名的Ketama Hash实现为例进行对比分析。Ketama Hash的关键源码如下:

#服务器节点例子,第一列为地址,第二列为内存

#------ Server --------Mem-#

#255.255.255.255:6553566666#

10.0.1.1:11211600

10.0.1.2:11211300

10.0.1.3:11211200

10.0.1.4:11211350

10.0.1.5:112111000

10.0.1.6:11211800

10.0.1.7:11211950

10.0.1.8:11211100







typedef struct

{

    unsigned int point;  // point on circle

    char ip[22];

} mcs;







typedef struct

{

    char addr[22];

    unsigned long memory;

} serverinfo;







typedef struct

{

    int numpoints;

    void* modtime;

    void* array; //array of mcs structs

} continuum;







typedef continuum* ketama_continuum;







/** \brief Generates the continuum of servers (each server as many points on a circle).

  * \param key Shared memory key for storing the newly created continuum.

  * \param filename Server definition file, which will be parsed to create this continuum.

  * \return 0 on failure, 1 on success. */

static int

ketama_create_continuum( key_t key, char* filename )

{

    if (shm_ids == NULL) {

        init_shm_id_tracker();

    }







    if (shm_data == NULL) {

        init_shm_data_tracker();

    }







    int shmid;

    int* data;  /* Pointer to shmem location */

    unsigned int numservers = 0;

    unsigned long memory;

    serverinfo* slist;







    slist = read_server_definitions( filename, &numservers, &memory );

    /* Check numservers first; if it is zero then there is no error message

     * and we need to set one. */

    if ( numservers < 1 )

    {

        set_error( "No valid server definitions in file %s", filename );

        return 0;

    }

    else if ( slist == 0 )

    {

        /* read_server_definitions must've set error message. */

        return 0;

    }

#ifdef DEBUG

     syslog( LOG_INFO, "Se
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用分布式事务或者一致性哈希算法实现 Redis Sharding 分片的具体实现方法: 1. 使用分布式事务实现 在使用分布式事务实现 Redis Sharding 分片时,需要使用分布式事务框架(例如,XA、TCC 等)对多个 Redis 实例中的数据进行操作,以保证数据的一致性。具体实现步骤如下: - 将 Redis 实例分成多个片段,每个片段存储在一个 Redis 节点上。 - 对于每个操作,例如写操作或者删除操作,需要在多个 Redis 节点上开启一个分布式事务。 - 在分布式事务中,对于每个 Redis 节点执行相应的操作,例如写入数据或者删除数据。 - 如果所有节点的操作都执行成功,则提交分布式事务,否则回滚分布式事务。 需要注意的是,使用分布式事务实现 Redis Sharding 分片需要考虑如下问题: - 分布式事务的效率较低,会影响 Redis 的性能。 - 分布式事务需要协调多个节点的操作,容易出现死锁和性能瓶颈等问题。 - 分布式事务的实现需要依赖于分布式事务框架,需要额外的开发工作。 2. 使用一致性哈希算法实现 在使用一致性哈希算法实现 Redis Sharding 分片时,需要将数据分散存储在多个 Redis 节点上,并通过一致性哈希算法确定数据应该存储在哪个节点上。具体实现步骤如下: - 将 Redis 实例分成多个片段,每个片段存储在一个 Redis 节点上。 - 对于每个写操作或者查询操作,通过一致性哈希算法确定数据应该存储在哪个节点上。 - 如果要增加或删除节点,可以在一致性哈希算法中添加或删除节点,从而实现动态扩展或缩减 Redis 的容量。 需要注意的是,使用一致性哈希算法实现 Redis Sharding 分片需要考虑如下问题: - 一致性哈希算法可能会导致数据不均衡的问题,需要使用虚拟节点或者增加数据复制等技术解决。 - 一致性哈希算法需要考虑节点故障和数据恢复问题,通常使用主从复制或者集群化技术实现。 - 一致性哈希算法需要考虑节点的负载均衡问题,通常使用预取数据等技术解决

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值