luocker / leaf-distributer

分布式算法的组件包,包含一致性哈希算法,可用于redis的分布式集群环境 consistent hashing php

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

leaf-distributer

leaf-distributer 是一个遵循PSR-3规范的,分布式算法组件,适用于基于客户端的轻量级集群分布式场景:如Redis、Memcached、MySQL。

特点及出发点:

  1. 使用composer包,遵循psr-3标准规范,便于集成到基于composer的项目中。
  2. 提供autoload注册方式,即便你的项目没有使用composer,也能方便的集成。
  3. 本组件的原型,已经在我司内部使用并得到验证。因Memcached拓展本身已经提供了一致性哈希算法的解决方案,而MySQL也有相对成熟的Cluster方案可做分库分表,所以,该组件在我的实际运用中,目前主要还是用在做redis分布式集群环境中,究其原因,主要还是Redis(版本<=2.8)没有一套官方的分布式解决方案。当然你可以选择使用Codis,只不过运维成本稍高。因此,如果你的公司规模不大,运维能力不是足够强大,或者项目相对较小的话,使用本组件做分布式解决方案,是相对较好的选择。

适用说明:

  1. 集成一致性哈希算法与取模算法。
  2. 适用于基于客户端的轻量级的分布式解决方案。
  3. 特别适用场景:Redis的集群分布式算法(Redis官方在3.0版本才出了自己的分布式解决方法)。
  4. 基于MySQL做分布式方案解决方案有很多且比较成熟,但对于小团队而言,使用一致性哈希替代取模算法同样不失为一种较好的解决方案。
  5. 支持集群中的配置是组模式(多个组,组成一个集群,每个组都是主从配置,一主多从,或多主多从,或主从配置一样均可)。
  6. 支持取配置类型:举例来说,根据某个维度(比如根据Redis的一个Key),通常来说,你根据这个Key获取的server配置,是这个配置组中的Read(从)库之一。但是某些情况下,你可能需要读主库的数据,而不是从库的数据,这种情况的话,你需要获取的就不是从库的配置,而是这个配置组下主库(Write)的配置了。

1. leaf-distributer 使用——引入

引入有2种方式:

1、基于composer的项目的引入方式:

composer require leaf-distributer

2、非composer项目引入方式:

\Leaf\Distributer\Autoloader::register();

2. leaf-distributer 的使用——配置

本组件的使用场景:

  • 你有多台server服务器,想做集群。
  • 你需要根据一个Key(维度,在Redis中,你可以称之为Key,如果是MySQL,你也可以认为是你要做分库分表的维度),根据这个Key,返回集中中某一台server的配置。
  • 最后,你根据这个配置,做实例连接,操作数据的读取和写入等。

这其中,有几点你可能需要考虑: 主从配置问题:多台server,可能是分组的,每个集群都是多个组组成,每个组都是主从方式。本组件要求配置这样来定义:

return

    [
        'groupA' => [ //cluster name, required
            //server group for writing data
            'write'  => [
                ['host' => 'x.x.1.11', 'port' => 6379, 'auth' => 'passwd', 'db' => 0, 'weight' => 3], //weight: server weight
                ['host' => 'x.x.1.12', 'port' => 6379, 'auth' => 'passwd', 'db' => 0, 'weight' => 2],
            ],
            //server group for reading data
            'read'   => [
                ['host' => 'x.x.1.21', 'port' => 6379, 'auth' => 'passwd', 'db' => 0, 'weight' => 1],
                ['host' => 'x.x.1.31', 'port' => 6379, 'auth' => 'passwd', 'db' => 0, 'weight' => 1],
            ],
            //cluster weight
            'weight' => 1,  //cluster的权重配置,用于做hash虚拟节点数量分配
        ],
        'GroupB' => [
            'write'  => [
                ['host' => 'x.x.2.11', 'port' => 6379, 'auth' => 'passwd', 'db' => 0, 'weight' => 1],
            ],
            'read'   => [
                ['host' => 'x.x.2.21', 'port' => 6379, 'db' => 0, 'weight' => 1],
                ['host' => 'x.x.2.31', 'port' => 6379, 'db' => 0, 'weight' => 1],
                ['host' => 'x.x.2.41', 'port' => 6379, 'db' => 0, 'weight' => 1],
                ['host' => 'x.x.2.51', 'port' => 6379, 'db' => 0, 'weight' => 1],
            ],
            'weight' => 1,
        ],
    ];

上面的配置,是==一个==一群的配置,这个集群有2组配置,每组都是主从的(实际线上业务,推荐你用哨兵做高可用)。关于每个组的配置,说明如下: weight:标识这组配置在cluster集群中的权重。权重越高,数据在落在这组server的概率就越高。默认为1。 write:主库(具有write权限的)配置,可以为多个。 read:从库(具有read权限的)配置,可以为多个。如果你的项目中,没有主从,则write项和read项配置为相同的即可。 需要说明的是,read项和write项配置都是可以为多个的。每一个也可以配置权重。

Tips:每一组配置,可以为主从,推荐一主多从+哨兵模式对这组配置做高可用,当然,从太多并不推荐,因为主从同步带宽占用你也得考虑,否则你的项目从从太多,同步数据网络带宽太高高必是隐患。

3. leaf-distributer 的使用——基本使用

使用示例在src/Example/single-consistent-hashing.php中,具体示例代码如下:

<?php

//1、引入:如果你的项目没有使用composer,需要先引入Autoloader,并注册自动加载
$autoloader = dirname(__FILE__) . '/../Autoloader.php';
require $autoloader;
\Leaf\Distributer\Autoloader::register();

//2、先实例化分布式算法的管理器
use \Leaf\Distributer\DistriManager;

$distriManager = new DistriManager();

//3、定义配置
$configGroup = require( 'standard-config.php' );

//4、获取分布式算法分发对象
$distributer = $distriManager->getDistributer()->init($configGroup);

$config = $distributer->lookUp('aa', 'write');

首先,你需要做包引入,如果没有使用composer,则需要注册一下自动加载机制。如果你的项目使用了composer,则下面注册自动加载机制的代码可忽略。

$autoloader = dirname(__FILE__) . '/../Autoloader.php';
require $autoloader;
\Leaf\Distributer\Autoloader::register();

然后,实例化一个分布式管理器

$distriManager = new DistriManager();

接下来,获取一个分布式分发器,设置分发器的名字为A,并制定分布式算法为一致性哈希。

$distributer = $distriManager->getDistributer('A',DistriMode::DIS_CONSISTENT_HASHING);

需要说明的是,获取分布式分发器,是可以指定分布式分发器的名称的。默认获取的分布式分发器的名称是default。如果你的项目中,需要使用多个集群,那么多个分布式集群都可以用 $distriManager 来管理。但是分布式分发器的名称不能相同。 举例来说:

获取一个redis集群A的分布式分发器,并设置这个分发器使用分布式算法为一致性哈希分布式算法:$distriManager->getDistributer('A',DistriMode::DIS_CONSISTENT_HASHING);

然后我们获取一个redis集群B的分布式分发器,并制定这个分布式分发器使用的分布式算法为取模算法:$distriManager->getDistributer('B',DistriMode::DIS_MODULO);

接下来,我们需要告诉这个分发器我们的其中配置,并做初始化。

$distributer->init($configGroup);

然后,我们可以通过一个key,获取查找出某个server的配置了

$config = $distributer->lookUp('aa');

需要说明的是,有些情况下,你可能需要获取写库的配置,比如某些场景下,你存入数据之后,需要立即读出来,这个时候,从库有可能并未同步数据,如果直接由从库中取数据,是可能出不出来的。所以,你可以这样指定查找主库(具备write权限的库) 的配置: $config = $distributer->lookUp('aa', 'write');

4. leaf-distributer 的基本使用——高级使用

建议:你可以将分布式算法管理器 $distriManager 注册到全局树种。可以使用依赖注入的方式,也可以使用注册树模式,这取决于你的项目。 高级使用分为几个部分:

  • 使用一致性哈希分布式算法的话,如何最大限度的避免哈希碰撞
  • 关于权重的设置
  • 如何写自己的分布式算法,并注册到 leaf-distributer 组件中

####如何最大限度的避免哈希碰撞 在本组件内,一致性哈希的分布式算法,实际上是维护了一个哈希环,环上有虚拟节点,虚拟节点的值,是实际配置组的哈希值(具体机理,可阅读源码)。默认情况下,我们并没有使用md5算法作为hash值,原因是hash值位数相对较低,产生哈希碰撞的概率也相对高一些(虽然你极难遇到)。默认的hash算法是 ==sha384== 算法。当然,如果你觉得效率或者其他原因,你想用默认的这个哈希算法,可以指定其他算法。 所有支持的哈希算法,都定义HashMode中,举例来说,你想使用MD5算法生成哈希环上的节点的值:

$distributer = $distriManager->getDistributer('A',DistriMode::DIS_CONSISTENT_HASHING);
$distributer->getDistriHandler()->setHashFunc(HashMode::STR_MD5);
$distributer->init($configGroups);

####关于权重的设置 权重的设置,取决于你的server的配置,如果全部server配置相同,则权重无需配置,如果不同。你有2个地方可能需要配置权重 1、集群配置中,配置server组的配置,它决定了这组server在集群中的权重,默认情况下,会根据权重虚拟成160个节点,如果weight设置了1个倍数,则这组server虚拟节点数量同等翻倍。 2、每个组中,write项下的server和read项下的server都是可以单独配置权重的。它只会影响单个server在同组中同类型server中的权重。

####如何自定义分布式算法并注册到本组件 1、你的分布式算法需要继承基类:

Leaf\Distributer\DistriHandler\DistriAbstract

并实现相关方法。

2、注册分布式算法的标识和相关的处理类:

	Leaf\Distributer\DistriMode::registerDistriModeClass($intMode,$className);

需要注意:$intMode参数必须是整型,且不能为1和2,因为1和2分别是系统的一致性哈希和取模算法的标识和对应的处理类。

3、然后你就可以使用你自己的分布式算法来处理了:

//假定3是你设置的分布式算法的标识,并假定你已经实现了处理类
$intMode = 3;
//获取分布式处理器并制定其分布式算法为自定义分布式算法
$distributer = $distriManager->getDistributer('A',$intMode);
//根据配置初始化
$distributer->init($configGroups);
//根据某个维度获取一个配置
$config = $distributer->lookUp('someKey');

todo.计划内容:

  • 暂无

About

分布式算法的组件包,包含一致性哈希算法,可用于redis的分布式集群环境 consistent hashing php

License:MIT License


Languages

Language:PHP 100.0%