客户端操作
注:这里的操作客户端语言,使用的是PHP语言。
搭建好了 Redis 集群并且理解了通信和伸缩细节,但还没有使用客户端去操作集群。Redis 集群对客户端通信协议做了比较大的修改,为了追求性能最大化,并没有采用代理的方式而是采用客户端直连节点的方式。
可以直接用predis类库 使用composer require predis/predis进行安装。 安装后可以使用基于predis的类库提供的相关类和方法来直接操作redis集群,但是该类库功能不够完善。也可以使用phpredis的C扩展,这个功能基本都提供了。
predis类库是基于php进行封装的类库,phpredis的C扩展是使用C语言进行封装的php扩展。
predis类库的相关资料可参看如下链接:
https://packagist.org/packages/predis/predis
phpredis的C扩展相关资料可参考如下链接:
https://github.com/phpredis/phpredis
phpredis的C扩展操作redis集群可参考如下链接:
https://github.com/phpredis/phpredis/blob/develop/cluster.markdown#readme
集群的常见问题
集群功能的常见限制
Redis 集群相对单机在功能上存在一些限制,需要开发人员提前了解,在使用时做好规避。限制如下:
①、key 批量操作支持有限。如 mset、mget,目前只支持具有相同 slot 值的 key 执行批量操作。对于映射为不同 slot 值的 key 由于执行 mget、mset、delete 等操作可能存在于多个节点上因此不被支持。
②、key 事务操作支持有限。同理只支持多 key 在同一节点上的事务操作,当多个 key 分布在不同的节点上时无法使用事务功能。
③、不支持多数据库空间。单机下的 Redis 可以支持16个数据库,集群模式下只能使用一个数据库空间,即 db0。
④、复制结构只支持一层,从节点只能复制主节点,不支持嵌套树状复制结构。(也就是说不支持类似redis主从的树状结构)
解决:
利用redis的C扩展解决
安装:
1、使用源码编译方式安装
wget http://pecl.php.net/get/redis-3.1.5.tgz tar -xvf redis-3.1.5.tgz cd redis-3.1.5.tgz phpize ./configure make make install
2、直接使用pecl扩展库方式进行安装
pecl install http://pecl.php.net/get/redis-3.1.5.tgz
redis的C扩展的简单使用示例,假设你已经安装了。:
//第一个NULL参数表示可以指定redis的一个.ini的配置文件,这里不需要,给NULL参数即可 $obj_cluster = new RedisCluster(NULL, array('119.3.220.26:6391', '119.3.220.26:6392', '119.3.220.26:6393')); $data = $obj_cluster->mget(['name1','name2','name3']); //批量获取key的值 //print_r($data); //成功获取到值
在上面的简单示例中 发现redis的C扩展支持批量获取key的值,同时支持mset等批量操作。该扩展除了支持集群模式下的mset、mget等批量操作外。同时支持超时时间、事务等相关支持。
predis的使用示例,假设你已经将predis类库都下载下来了。(composer require predis/predis):
require "vendor/autoload.php"; //这里不一定要将所有的redis节点ip写上去,一般来说只需要给集群中的master节点的1-2台ip地址即可 $parameters = ['119.3.220.26:6391', '119.3.220.26:6392', '119.3.220.26:6393']; //选项设置为:集群模式 $options = ['cluster' => 'redis']; $client = new Predis\Client($parameters, $options); //设置值 $client->set('name1', '1'); $client->set('name2', '2'); $client->set('name3', '3'); echo $client->get('name2'); //获取值 //试一下predis的批量获取值 $client->mget(['name1','name2','name3']); //运行报错:predis不支持批量获取值
predis类库支持的模式很多,除了cluster集群外,也支持sentinel和redis主从等操作,但是在上面的示例中,我们发现predis不支持批量获取值等类似的操作。
一般情况下使用phpredis的C扩展即可,不过也要看项目和个人了
集群实现批量操作的原理
流程:
1)计算 slot 并根据 slots 缓存获取目标节点连接,发送命令。
2)如果出现连接错误,使用随机连接重新执行键命令,每次命令重试对 $retryLimit 参数减1。
3)如果捕获到 MOVED 重定向错误,使用 cluster slots 命令更新 slots 缓存,调用缓存更新方法。
4)重复执行1)~3)步,直到命令执行成功,或者当 $retries<=0 时抛出异常。
集群常见问题:
1、移除节点之后,因为被移除节点,还保留节点信息,所以必须先删除之前的配置信息,否则有可能出现如下报错
2、重定向问题
在集群模式下,Redis 接收任何键相关命令时 首先计算键对应的槽,再根据槽找出所对应的节点,如果节点是自身,则处理键命令;否则回复 MOVED 重定向错误,通知客户端请求正确的节点。
如下提示:
ASK 重定向问题
客户端 ASK 重定向流程:
Redis 集群支持在线迁移槽(slot)和数据来完成水平伸缩,当 slot 对应的数据从源节点到目标节点迁移过程中,客户端需要做到智能识别,保证键命令可正常执行。例如当一个 slot 数据从源节点迁移到目标节点时,期间可能出现一部分数据在源节点,而另一部分在目标节点。
如果键对象不存在,则可能存在于目标节点,这时源节点会回复 ASK 重定向异常。格式如下:(error)ASK{slot}{targetIP}:{targetPort}。
客户端从 ASK 重定向异常提取出目标节点信息,发送 asking 命令到目标节点打开客户端连接标识,再执行键命令。如果存在则执行,不存在则返回不存在信息。
ASK 与 MOVED 虽然都是对客户端的重定向控制,但是有着本质区别。ASK 重定向说明集群正在进行 slot 数据迁移,客户端无法知道什么时候迁移完成,因此只能是临时性的重定向,客户端不会更新本地的slots 缓存。但是 MOVED 重定向说明键对应的槽已经明确指定到新的节点,因此需要更新 slots 缓存。
有人说恋爱最美的时期 就是暧昧不清的阶段 -->【那些年,我们一起追过的女孩】
声明:禁止任何非法用途使用,凡因违规使用而引起的任何法律纠纷,本站概不负责。
精彩评论