四、客户端集群命令
cluster集群相关命令,更多Redis相关命令见文档:http://redis.readthedocs.org/en/latest/
[plain] view plain copy PRint?
集群 cluster info 打印集群的信息 cluster nodes 列出集群当前已知的所有节点(node),以及这些节点的相关信息。 节点 cluster meet <ip> <port> 将ip和port所指定的节点添加到集群当中,让它成为集群的一份子。 cluster forget <node_id> 从集群中移除 node_id 指定的节点。 cluster replicate <node_id> 将当前节点设置为node_id指定的节点的从节点。 cluster saveconfig 将节点的配置文件保存到硬盘里面。 槽(slot) cluster addslots <slot> [slot ...] 将一个或多个槽(slot)指派(assign)给当前节点。 cluster delslots <slot> [slot ...] 移除一个或多个槽对当前节点的指派。 cluster flushslots 移除指派给当前节点的所有槽,让当前节点变成一个没有指派任何槽的节点。 cluster setslot <slot> node <node_id> 将槽 slot 指派给 node_id 指定的节点,如果槽已经指派给另一个节点,那么先让另一个节点删除该槽>,然后再进行指派。 cluster setslot <slot> migrating <node_id> 将本节点的槽 slot 迁移到 node_id 指定的节点中。 cluster setslot <slot> importing <node_id> 从 node_id 指定的节点中导入槽 slot 到本节点。 cluster setslot <slot> stable 取消对槽 slot 的导入(import)或者迁移(migrate)。 键 cluster keyslot <key> 计算键 key 应该被放置在哪个槽上。 cluster countkeysinslot <slot> 返回槽 slot 目前包含的键值对数量。 cluster getkeysinslot <slot> <count> 返回 count 个 slot 槽中的键。 五、redis-trib.rb操作集群每台机器增加端口6383%20redis实例节点,并启动实例。
1.添加新master节点1)add-node%20 将一个节点添加到集群里面,%20第一个是新节点ip:port,%20第二个是任意一个已存在节点ip:port./bin/redis-trib.rb%20add-node%20192.168.36.54:6383%20192.168.36.54:6380
[plain] view%20plain copy print?![在CODE上查看代码片]()
>>> Adding node 192.168.36.54:6383 to cluster 192.168.36.54:6380 Connecting to node 192.168.36.54:6380: OK Connecting to node 192.168.36.189:6380: OK Connecting to node 192.168.36.189:6382: OK Connecting to node 192.168.36.54:6382: OK Connecting to node 192.168.36.54:6381: OK Connecting to node 192.168.36.189:6381: OK >>> Performing Cluster Check (using node 192.168.36.54:6380) M: f6285c8a7506b224840d7b26b2b5d1671320c21f 192.168.36.54:6380 slots:0-5460 (5461 slots) master 1 additional replica(s) M: b1a15a3cd14ea65671a7134850e17b8919a17da5 192.168.36.189:6380 slots:5461-10922 (5462 slots) master 1 additional replica(s) S: de4302f43ff89843675446396552fd19f741246a 192.168.36.189:6382 slots: (0 slots) slave replicates 26ce71d626175f88e0416e3f45b2bfb29304c7b3 S: 83fc65283bbbb71b4c089337df05594d67f4cab6 192.168.36.54:6382 slots: (0 slots) slave replicates b1a15a3cd14ea65671a7134850e17b8919a17da5 M: 26ce71d626175f88e0416e3f45b2bfb29304c7b3 192.168.36.54:6381 slots:10923-16383 (5461 slots) master 1 additional replica(s) S: 1080e423a55a2c24dae649dac03ffa09ed26d3e8 192.168.36.189:6381 slots: (0 slots) slave replicates f6285c8a7506b224840d7b26b2b5d1671320c21f [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered. Connecting to node 192.168.36.54:6383: OK >>> Send CLUSTER MEET to node 192.168.36.54:6383 to make it join the cluster. [OK] New node added correctly. 新节点没有包含任何数据,%20因为它没有包含任何slot。新加入的加点是一个主节点,%20当集群需要将某个从节点升级为新的主节点时,%20这个新节点不会被选中。2)为新节点分配slot
你只需要指定集群中其中一个节点的地址,%20redis-trib%20就会自动找到集群中的其他节点。目前%20redis-trib%20只能在管理员的协助下完成重新分片的工作,%20要让%20redis-trib%20自动将哈希槽从一个节点移动到另一个节点,%20目前来说还做不到%20(不过实现这个功能并不难)。./bin/redis-trib.rb%20reshard%20192.168.36.54:6383设定你打算移动的哈希槽slots的数量(这里槽数量设置为1000)How%20many%20slots%20do%20you%20want%20to%20move%20(from%201%20to%2016384)?%201000除了移动的哈希槽数量之外,%20redis-trib%20还需要知道重新分片的目标(target%20node),%20也即是,%20负责接收这%201000%20个哈希槽的节点。指定目标需要使用节点的%20ID%20,%20而不是%20IP%20地址和端口。%20比如说,%20我们打算使用集群的第一个主节点来作为目标,%20它的%20IP%20地址和端口是%20192.168.36.54:6383%20,%20而节点%20ID%20则是50cd88737109d0398e35b19747cc02832f05d125%20,%20那么我们应该向%20redis-trib%20提供节点的%20ID%20:What%20is%20the%20receiving%20node%20ID?50cd88737109d0398e35b19747cc02832f05d125redis-trib%20会打印出集群中所有节点的%20ID%20,%20并且我们也可以通过执行以下命令来获得节点的运行%20ID%20:./bin/redis-cli%20-h%20192.168.36.54%20-p%206380%20cluster%20nodes%20|grep%20192.168.36.54:6383接着,%20redis-trib%20会向你询问重新分片的源节点(source%20node),%20也即是,%20要从哪个节点中取出%201000%20个哈希槽,并将这些槽移动到目标节点上面。如果我们不打算从特定的节点上取出指定数量的哈希槽,%20那么可以向%20redis-trib%20输入%20all%20,%20这样的话,%20集群中的所有主节点都会成为源节点,%20redis-trib%20将从各个源节点中各取出一部分哈希槽,%20凑够%201000%20个,%20然后移动到目标节点上面:Please%20enter%20all%20the%20source%20node%20IDs.Type%20'all'%20to%20use%20all%20the%20nodes%20as%20source%20nodes%20for%20the%20hash%20slots.Type%20'done'%20once%20you%20entered%20all%20the%20source%20nodes%20IDs.Source%20node%20#1:all
输入%20all%20并按下回车之后,%20redis-trib%20将打印出哈希槽的移动计划,%20如果你觉得没问题的话,%20就可以输入%20yes%20并再次按下回车,%20redis-trib%20就会正式开始执行重新分片操作,%20将指定的哈希槽从源节点一个个地移动到目标节点上面。在重新分片操作执行完毕之后,%20可以使用以下命令来检查集群是否正常:./bin/redis-trib.rb%20check%20192.168.36.54:6380根据检查结果显示,%20集群运作正常。
2.添加新的slave节点
1)添加节点
./bin/redis-trib.rb%20add-node%20192.168.36.189:6383%20192.168.36.54:6380
2)redis-cli连接上新节点shell,输入命令:cluster%20replicate%20对应master的node-id./bin/redis-cli%20-c -h%20192.168.36.189%20-p%206383>cluster%20replicate%2050cd88737109d0398e35b19747cc02832f05d125在线添加slave%20时,需要dump整个master进程,并传递到slave,再由%20slave加载rdb文件到内存,rdb传输过程中Master可能无法提供服务,整个过程消耗大量io,小心操作.查看执行结果:./bin/redis-cli%20-h%20192.168.36.189%20-p%206383%20cluster%20nodes%20|%20grep%20slave%20|%20grep%2050cd88737109d0398e35b19747cc02832f05d1255178d6342a6470f928cfa6d43d98640b9303ad38%20192.168.36.189:6383%20myself,slave%2050cd88737109d0398e35b19747cc02832f05d125%200%200%200%20connected
3)在线reshard%20数据对于负载/数据不均匀的情况,可以在线reshard%20slot来解决,方法与添加新master的reshard一样,只是需要reshard的master节点是老节点。4)删除一个slave节点./bin/redis-trib.rb%20del-node%20192.168.36.54:6380%205178d6342a6470f928cfa6d43d98640b9303ad385)删除一个master节点删除master节点之前首先要使用reshard移除master的全部slot,然后再删除当前节点(目前只能把被删除master的slot迁移到一个节点上),操作和分配slot类似,指定具体的Source%20node即可。然后在使用4步骤中的命令删除节点
六、集群测试
1.数据测试
使用redis客户端redis-cli进行添加数据操作。
[plain] view%20plain copy print?![在CODE上查看代码片]()
./bin/redis-cli -c -h 192.168.36.189 -p 6380 192.168.36.189:6380> set abc 123 OK 192.168.36.189:6380> set xxx 123 -> Redirected to slot [4038] located at 192.168.36.54:6380 OK 192.168.36.54:6380> set ttt aaa -> Redirected to slot [15942] located at 192.168.36.54:6381 OK redis-cli%20对集群的支持是非常基本的,%20所以它总是依靠%20Redis%20集群节点来将它转向(redirect)至正确的节点。2.故障转移测试
要触发一次故障转移,%20最简单的办法就是令集群中的某个主节点进入下线状态。首先用以下命令列出集群中的所有主节点:
[plain] view%20plain copy print?![在CODE上查看代码片]()
./bin/redis-cli -h 192.168.36.189 -p 6383 cluster nodes |grep master 50cd88737109d0398e35b19747cc02832f05d125 192.168.36.54:6383 master - 0 1428823692383 7 connected 0-332 5461-5794 10923-11255 26ce71d626175f88e0416e3f45b2bfb29304c7b3 192.168.36.54:6381 master - 0 1428823692893 2 connected 11256-16383 f6285c8a7506b224840d7b26b2b5d1671320c21f 192.168.36.54:6380 master - 0 1428823693918 1 connected 333-5460 b1a15a3cd14ea65671a7134850e17b8919a17da5 192.168.36.189:6380 master - 0 1428823692893 4 connected 5795-10922 通过命令输出,%20我们知道端口号为%20192.168.36.54:6380、%20192.168.36.54:6381、192.168.36.54:6383%20和%20192.168.36.189:6380的节点都是主节点,%20然后我们可以通过向端口号为192.168.36.54:6380的主节点发送%20DEBUG%20SEGFAULT%20命令,%20让这个主节点崩溃:./bin/redis-cli%20-h%20192.168.36.54%20-p%206380%20 debug%20segfaultError:%20Server%20closed%20the%20connection我们使用%20cluster%20nodes%20命令,%20查看集群在执行故障转移操作之后,%20主从节点的布局情况:[plain] view%20plain copy print?![在CODE上查看代码片]()
./bin/redis-cli -h 192.168.36.189 -p 6383 cluster nodes 50cd88737109d0398e35b19747cc02832f05d125 192.168.36.54:6383 master - 0 1428823969555 7 connected 0-332 5461-5794 10923-11255 1080e423a55a2c24dae649dac03ffa09ed26d3e8 192.168.36.189:6381 master - 0 1428823968475 8 connected 333-5460 de4302f43ff89843675446396552fd19f741246a 192.168.36.189:6382 slave 26ce71d626175f88e0416e3f45b2bfb29304c7b3 0 1428823968886 2 connected 26ce71d626175f88e0416e3f45b2bfb29304c7b3 192.168.36.54:6381 master - 0 1428823967861 2 connected 11256-16383 83fc65283bbbb71b4c089337df05594d67f4cab6 192.168.36.54:6382 slave b1a15a3cd14ea65671a7134850e17b8919a17da5 0 1428823969555 4 connected f6285c8a7506b224840d7b26b2b5d1671320c21f 192.168.36.54:6380 master,fail? - 1428823891006 1428823888448 1 disconnected b1a15a3cd14ea65671a7134850e17b8919a17da5 192.168.36.189:6380 master - 0 1428823970008 4 connected 5795-10922 5178d6342a6470f928cfa6d43d98640b9303ad38 192.168.36.189:6383 myself,slave 50cd88737109d0398e35b19747cc02832f05d125 0 0 0 connected 重启了之前下线的节点192.168.36.54:6380,%20该节点已经从原来的主节点变成了从节点。[plain] view%20plain copy print?![在CODE上查看代码片]()
./bin/redis-cli -h 192.168.36.189 -p 6383 cluster nodes 50cd88737109d0398e35b19747cc02832f05d125 192.168.36.54:6383 master - 0 1428824165896 7 connected 0-332 5461-5794 10923-11255 1080e423a55a2c24dae649dac03ffa09ed26d3e8 192.168.36.189:6381 master - 0 1428824166406 8 connected 333-5460 de4302f43ff89843675446396552fd19f741246a 192.168.36.189:6382 slave 26ce71d626175f88e0416e3f45b2bfb29304c7b3 0 1428824165382 2 connected 26ce71d626175f88e0416e3f45b2bfb29304c7b3 192.168.36.54:6381 master - 0 1428824165896 2 connected 11256-16383 83fc65283bbbb71b4c089337df05594d67f4cab6 192.168.36.54:6382 slave b1a15a3cd14ea65671a7134850e17b8919a17da5 0 1428824164870 4 connected f6285c8a7506b224840d7b26b2b5d1671320c21f 192.168.36.54:6380 slave 1080e423a55a2c24dae649dac03ffa09ed26d3e8 0 1428824166920 8 connected b1a15a3cd14ea65671a7134850e17b8919a17da5 192.168.36.189:6380 master - 0 1428824166407 4 connected 5795-10922 5178d6342a6470f928cfa6d43d98640b9303ad38 192.168.36.189:6383 myself,slave 50cd88737109d0398e35b19747cc02832f05d125 0 0 0 connected 注:cluster%20nodes%20命令的输出有点儿复杂,%20它的每一行都是由以下信息组成的:节点%20ID%20:例如%203fc783611028b1707fd65345e763befb36454d73%20。ip:port%20:节点的%20IP%20地址和端口号,%20例如%20127.0.0.1:7000%20,%20其中%20:0%20表示的是客户端当前连接的%20IP%20地址和端口号。flags%20:节点的角色(例如%20master%20、%20slave%20、%20myself%20)以及状态(例如%20fail%20,等等)。如果节点是一个从节点的话,%20那么跟在%20flags%20之后的将是主节点的节点%20ID%20:%20例如%20127.0.0.1:7002%20的主节点的节点%20ID%20就是%203c3a0c74aae0b56170ccb03a76b60cfe7dc1912e%20。集群最近一次向节点发送%20PING%20命令之后,%20过去了多长时间还没接到回复。节点最近一次返回%20PONG%20回复的时间。节点的配置纪元(configuration%20epoch):详细信息请参考%20Redis%20集群规范%20。本节点的网络连接情况:例如%20connected%20。节点目前包含的槽:例如192.168.36.189:6380%20目前包含号码为5795-10922的哈希槽。七、集群下java客户端使用如下以jedis为例:
[java] view%20plain copy print?![在CODE上查看代码片]()
package cn.slimsmart.redis.demo.cluster; import java.util.HashSet; import java.util.Set; import redis.clients.jedis.HostAndPort; import redis.clients.jedis.JedisCluster; import redis.clients.jedis.JedisPoolConfig; public class RedisClusterTest { public static void main(String[] args) { JedisPoolConfig config = new JedisPoolConfig(); config.setMaxTotal(100); config.setMaxIdle(100); config.setMinIdle(100); config.setMaxWaitMillis(6 * 1000); config.setTestOnBorrow(true); Set<HostAndPort> jedisClusterNodes = new HashSet<HostAndPort>(); jedisClusterNodes.add(new HostAndPort("192.168.36.54", 6380)); jedisClusterNodes.add(new HostAndPort("192.168.36.54", 6381)); jedisClusterNodes.add(new HostAndPort("192.168.36.54", 6382)); jedisClusterNodes.add(new HostAndPort("192.168.36.54", 6383)); jedisClusterNodes.add(new HostAndPort("192.168.36.189", 6380)); jedisClusterNodes.add(new HostAndPort("192.168.36.189", 6381)); jedisClusterNodes.add(new HostAndPort("192.168.36.189", 6382)); jedisClusterNodes.add(new HostAndPort("192.168.36.189", 6383)); JedisCluster jedisCluster = new JedisCluster(jedisClusterNodes, 2000, 2, config); try { for (int i = 0; i < 1000; i++) { long t1 = System.currentTimeMillis(); jedisCluster.set("" + i, "" + i); long t2 = System.currentTimeMillis(); String value = jedisCluster.get("" + i); long t3 = System.currentTimeMillis(); System.out.println("" + value); System.out.println((t2 - t1) + "mills"); System.out.println((t3 - t2) + "mills"); } } catch (Exception e) { e.printStackTrace(); } finally { jedisCluster.close(); } } } jedis客户端不足之处:1.cluster环境下redis的slave不接受任何读写操作2.client端不支持keys批量操作,不支持select dbNum操作,只有一个db:select 03.JedisCluster 的info()等单机函数无法调用,返回(No way to dispatch this command to Redis Cluster)错误4.JedisCluster 没有针对byte[]的API,需要自己扩展