[不忘初心]
在通常情况下,Redis单机服务能够解决一般应用场景,但随着互联网数据的爆炸式增长,缓存的大小及组织方式也需要相对应的调整。本文源自于官方文档对于集群教程的通俗解释,我们先一起学习一下。马上开始我们的正文部分吧。
--------------------------------------------------------------------------------------------------------------------------------------------------------
本文是Redis集群教程的入门教程,本教程不包含复杂难懂的分布式概念。仅仅介绍了如何搭建,测试,操作集群的方法,以及从用户的角度出发观察整个系统的运行行为。这其中不包含在Redis集群规范中包含的细节内容。
然而,本教程从最终用户的角度,尽可能的提供关于Redis集群在可用性和一致性特征方便的信息,并且用一种简单易于理解的方式来说明。
值得注意的是:本教程适用于Redis 3.0 或者更高的版本。
如果你打算深入的学习Redis集群的部署方法,虽然不是强制的,还是推荐你在阅读完这篇教程之后,再去看看集群规范的内容。然而,一个比较好的做法是先从本文开始学习,之后建立一个Redis集群练习一下,再阅读集群规范的相关内容。
集群简介(Redis Cluster 101)
- 将数据集自动的拆分到多个节点的能力。
- 当集群中的一部分节点失效或者无法与其他节点连接时,仍然能够继续处理请求命令的能力。
Redis集群的TCP端口
- 正常的客户端通信端口(默认6379)用来与客户端进行通讯,并向所有链接到集群的客户端开放,再加上其他集群节点(使用客户端端口做数据迁移时使用)
- 集群总线端口(16379)不许能够被其他集群节点可以访问到。
Redis集群与Docker(本内容有兴趣的看官先自行学习)
Redis集群数据共享
- 节点A负责处理0号到5500号哈希槽
- 节点B负责处理5501号到11000号哈希槽
- 节点C负责处理11001号到16384号哈希槽
Redis的主从复制模式
Redis集群的一致性保证
- 当超过该时间限制时,master节点会被是为失效,并且将会被其备份的slave所取代。
- 类似的,当超时之后,如果没有一个主节点能感知到大多数节点网络中的其余的主节点,那么将返回一个错误,并且停止接受写操作。
Redis集群配置参数
- cluster-enable<yes/no>:如果是yes的话,将会使用一个特殊的Redis实例并且支持Redis集群,否则的话,像通常情况下一样,只会启动一个单独的Redis实例。
- cluster-config-file<filename>:请记住:尽管这是一个可配置项,但是这并不是一个有用户进行编辑的文件。但是,Redis集群节点能够在每次在此配置变化时,自动的保留集群配置(状态),为的是能够在重启时进行载入。这个文件中,记录了集群中其他节点的状态,持有的变量等信息。这个文件通常是作为接受到的消息的结果时,进行重写和保存至磁盘。
- cluster-node-timeout<milloseconds>:Redis集群节点的最大是失效时间,超过这个限制节点将会被视为失效。如果一个master节点在给定的时间之内没有重新链接到集群中,其将会被视为失效,并且被slave节点替代。这个参数控制了Redis集群中其他非常重要的功能。请记住:集群中的每一个几点在给定的时间之内,如果没有链接到主体的master节点网络中,其将不再接受命令、
- cluster-slave-validity-factor<factor>:如果设置为0,slave将会永远在master发生故障时进行替换,而忽略master节点与slave节点中仍然持续的断开时间。如果这个数字是一个正数,最大的断开时间计算方法为节点的失效时间(见上一条)乘以这个正数。并且如果这个节点是slave节点,其将不会在超过给定的短线时间后对master节点进行替换。举个例子:如果节点的失效时间为5s,该参数配置为10,那么slave节点将在50s之后不会对master节点进行替换。特别提醒:当这个值不是0时,都有可能导致Redis集群中发生故障的master无法找到一个slave来替换,在这种情况下,只有当该master重新连接的情况下才能让整个Redis集群节点恢复其可用性。
- cluster-migration-barrier<count>:master节点持有的最小的slave连接数,使得其余的slave提升为master时不会被任何slave节点覆盖。在下文的复制迁移部分我们将更加详细的介绍这个配置项的功能。
- cluster-require-full-coverage<yes/no>:如果设置为yes,也是默认的,集群节点将会在只能接受部分keys时,停止接受写命令。如果设置为no,尽管请求只能处理一个keys的子集,集群节点仍然能够提供服务。
创建并使用Redis集群
port 7000 cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 appendonly yes正如你所看到的,cluster-enabled选项用于开启节点的集群模式。每一个Redis示例都包含有一个文件路径:关于这个节点的配置文件的位置,默认情况下是nodes.conf。这个文件无需我们手动进行配置,其是在Redis启动是创建的,并且在需要的时刻进行自动更新。
mkdir cluster-test cd cluster-test mkdir 7000 7001 7002 7003 7004 7005在7000到7005每一个目录中都创建要给redis.conf文件,文件的内容可以使用上文刚刚介绍的最小配置项,但是,请记住,一定要确保配置文件中的命名,与文件目录结构保持一致。
cd 7000 ../redis-server ./redis.conf正如你所见的,每一个示例都会打印出运行日志,因为node.conf文件不存在,所以每一个节点都会创建一个新的ID:
[82462] 26 Nov 11:56:55.329 * No cluster configuration found, I'm 97a3a64667477371c4479320d683e4c8db5858b1对应的实例将会一直使用这个ID值,从在整个Redis集群中唯一标识自己。每个节点通过这个ID值来识别其他节点,而不是通过IP或端口。因为,IP或端口都可能会改变,但是这个ID在整个节点的生命周期内都是不会变化的。因此,我们将这个ID值成为节点ID。
创建集群
gem install redis执行以下命令来创建集群:
./redis-trib.rb create --replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005命令的解释如下:
- 给定的命令将会被ruby程序翻译为create,这表示我们想要创建一个新的集群。
- 选项--replicas 1意思是为每一个master节点创建一个slave节点。
- 其他参数表示redis实例的地址及端口,以空格为间隔。
>>> Creating cluster Connecting to node 127.0.0.1:7000: OK Connecting to node 127.0.0.1:7001: OK Connecting to node 127.0.0.1:7002: OK Connecting to node 127.0.0.1:7003: OK Connecting to node 127.0.0.1:7004: OK Connecting to node 127.0.0.1:7005: OK >>> Performing hash slots allocation on 6 nodes... Using 3 masters: 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7000 replica #1 is 127.0.0.1:7003 127.0.0.1:7001 replica #1 is 127.0.0.1:7004 127.0.0.1:7002 replica #1 is 127.0.0.1:7005 M: 9991306f0e50640a5684f1958fd754b38fa034c9 127.0.0.1:7000 slots:0-5460 (5461 slots) master M: e68e52cee0550f558b03b342f2f0354d2b8a083b 127.0.0.1:7001 slots:5461-10921 (5461 slots) master M: 393c6df5eb4b4cec323f0e4ca961c8b256e3460a 127.0.0.1:7002 slots:10922-16383 (5462 slots) master S: 48b728dbcedff6bf056231eb44990b7d1c35c3e0 127.0.0.1:7003 S: 345ede084ac784a5c030a0387f8aaa9edfc59af3 127.0.0.1:7004 S: 3375be2ccc321932e8853234ffa87ee9fde973ff 127.0.0.1:7005 Can I set the above configuration? (type 'yes' to accept): yes如果你接受自动创建的集群配置,那么输入yes,集群就会完成配置并且进行相互连接。
>>> Nodes configuration updated >>> Sending CLUSTER MEET messages to join the cluster Waiting for the cluster to join... >>> Performing Cluster Check (using node 127.0.0.1:7000) M: 9991306f0e50640a5684f1958fd754b38fa034c9 127.0.0.1:7000 slots:0-5460 (5461 slots) master M: e68e52cee0550f558b03b342f2f0354d2b8a083b 127.0.0.1:7001 slots:5461-10921 (5461 slots) master M: 393c6df5eb4b4cec323f0e4ca961c8b256e3460a 127.0.0.1:7002 slots:10922-16383 (5462 slots) master M: 48b728dbcedff6bf056231eb44990b7d1c35c3e0 127.0.0.1:7003 slots: (0 slots) master M: 345ede084ac784a5c030a0387f8aaa9edfc59af3 127.0.0.1:7004 slots: (0 slots) master M: 3375be2ccc321932e8853234ffa87ee9fde973ff 127.0.0.1:7005 slots: (0 slots) master [OK] All nodes agree about slots configuration.
[OK] All 16384 slots covered这表示集群中的16384个哈希槽都会有一个明确的master节点来处理,集群就能够正常的运作了。
与集群交互
- redis-py-cluster:看上去是redis-rb-cluster的Python版本。支持redis-py的大多数功能。并且其仍在开发之中。
- Predis:流行的Predis对redis的集群提供支持,其最近也获得更新并且也在开发之中。
- Jedis:最流行的Java客户端,其最近也增加了对redis集群的支持,关于Jedis集群的内容请在其project的readme部分学习。
- Redis unstable分支中的redis-cli程序实现了非常基本的集群支持,可以使用redis-cli -c来启动。
- 更多支持内容,请各位看官在官方文档中了解学习。
$ redis-cli -c -p 7000 redis 127.0.0.1:7000> set foo bar -> Redirected to slot [12182] located at 127.0.0.1:7002 OK redis 127.0.0.1:7002> set hello world -> Redirected to slot [866] located at 127.0.0.1:7000 OK redis 127.0.0.1:7000> get foo -> Redirected to slot [12182] located at 127.0.0.1:7002 "bar" redis 127.0.0.1:7000> get hello -> Redirected to slot [866] located at 127.0.0.1:7000 "world"注意:如果你是通过脚本来创建redis集群,那么你的集群可能监听不同的端口,默认从30001开始。
使用redis-rd-cluster来编写一个示例应用
require './cluster' startup_nodes = [ {:host => "127.0.0.1", :port => 7000}, {:host => "127.0.0.1", :port => 7001} ] rc = RedisCluster.new(startup_nodes,32,:timeout => 0.1) last = false while not last begin last = rc.get("__last__") last = 0 if !last rescue => e puts "error #{e.to_s}" sleep 1 end end ((last.to_i+1)..1000000000).each{|x| begin rc.set("foo#{x}",x) puts rc.get("foo#{x}") rc.set("__last__",x) rescue => e puts "error #{e.to_s}" end sleep 0.1 }这个应用做了一件非常简单的事情:它不断的用foo<number>为key,number为value。因此,如果你运行这个程序的话,应用将按照下面的顺序执行命令:
- SET foo0 0
- SET foo1 1
- SET foo2 2
- And so forth...
- 第一个参数:记录启动节点的startup nodes列表,列表中包括两个集群节点的地址。
- 第二个参数:指定了对于集群中的各个不同的节点,Redis集群对象可以获得的最大连接数。
- 第三个参数:timeout指定了一个命令在指定多久之后,才会被看作是执行失败。
ruby ./example.rb 1 2 3 4 5 6 7 8 9 ^C (I stopped the program here)这个应用程序并不是十分有趣,稍后我们会看到一个更加意思的集群应用实例,不过在此之前,我们需要再使用这个例子来观察重新分片场景下,程序的运行情况。
对集群的重新分片
./redis-trib.rb reshard 127.0.0.1:7000你只需要指定集群中其中一个节点的地址,redis-trib就会自动找到集群中的其他节点。
How many slots do you want to move (from 1 to 16384)?我们可以尝试重新分片1000个哈希槽,如果example程序在没有sleep命令下还在运行的话,其中应该包含不少数量的keys。
$ redis-cli -p 7000 cluster nodes | grep myself 97a3a64667477371c4479320d683e4c8db5858b1 :0 myself,master - 0 0 0 connected 0-5460好了,我们的目标节点ID是: 97a3a64667477371c4479320d683e4c8db5858b
$ ./redis-trib.rb reshard 127.0.0.1:7000 ... Please enter all the source node IDs. Type 'all' to use all the nodes as source nodes for the hash slots. Type 'done' once you entered all the source nodes IDs. Source node #1:all在重新分片的过程中,你就会看到example程序的运行对集群网络没有造成任何影响。如果你想要再次验证的话,那么可以在重新分片的过程中多次停止或重新启动example程序来验证这一点。
$ ./redis-trib.rb reshard 127.0.0.1:7000 ... Moving slot 11421 from 393c6df5eb4b4cec323f0e4ca961c8b256e3460a Moving slot 11422 from 393c6df5eb4b4cec323f0e4ca961c8b256e3460a Moving slot 5461 from e68e52cee0550f558b03b342f2f0354d2b8a083b Moving slot 5469 from e68e52cee0550f558b03b342f2f0354d2b8a083b ... Moving slot 5959 from e68e52cee0550f558b03b342f2f0354d2b8a083b Do you want to proceed with the proposed reshard plan (yes/no)? yes输入 yes 并使用按下回车之后, redis-trib 就会正式开始执行重新分片操作, 将指定的哈希槽从源节点一个个地移动到目标节点上面:
$ ./redis-trib.rb reshard 127.0.0.1:7000 ... Moving slot 5934 from 127.0.0.1:7001 to 127.0.0.1:7000: Moving slot 5935 from 127.0.0.1:7001 to 127.0.0.1:7000: Moving slot 5936 from 127.0.0.1:7001 to 127.0.0.1:7000: Moving slot 5937 from 127.0.0.1:7001 to 127.0.0.1:7000: ... Moving slot 5959 from 127.0.0.1:7001 to 127.0.0.1:7000:
$ ./redis-trib.rb check 127.0.0.1:7000 Connecting to node 127.0.0.1:7000: OK Connecting to node 127.0.0.1:7002: OK Connecting to node 127.0.0.1:7005: OK Connecting to node 127.0.0.1:7001: OK Connecting to node 127.0.0.1:7003: OK Connecting to node 127.0.0.1:7004: OK >>> Performing Cluster Check (using node 127.0.0.1:7000) M: 9991306f0e50640a5684f1958fd754b38fa034c9 127.0.0.1:7000 slots:0-5959,10922-11422 (6461 slots) master M: 393c6df5eb4b4cec323f0e4ca961c8b256e3460a 127.0.0.1:7002 slots:11423-16383 (4961 slots) master S: 3375be2ccc321932e8853234ffa87ee9fde973ff 127.0.0.1:7005 slots: (0 slots) slave M: e68e52cee0550f558b03b342f2f0354d2b8a083b 127.0.0.1:7001 slots:5960-10921 (4962 slots) master S: 48b728dbcedff6bf056231eb44990b7d1c35c3e0 127.0.0.1:7003 slots: (0 slots) slave S: 345ede084ac784a5c030a0387f8aaa9edfc59af3 127.0.0.1:7004 slots: (0 slots) slave [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered.上面的最后一行显示,集群运行正常。
./redis-trib.rb reshard --from <node-id> --to <node-id> --slots <number of slots> --yes <host>:<port>如果你经常的需要重新分片的话,使用这条命令实现里重新分片过程的自动化。然而,现在,redis-trib还没有办法自动的再平衡集群节点中key的分布和按照需求,智能的移动这些哈希槽。这个功能将会在以后加入进来。
一个更加有趣的示例应用
- 每次使用INCR命令更新一个计数器时,应用都会记录下计数器执行的INCR命令。
- 在每次发送INCR命令之前,程序会随机的从集群中读取一个计数器的值,并将与自己记录的值进行对比,看两个值是否相同
$ ruby consistency-test.rb 925 R (0 err) | 925 W (0 err) | 5030 R (0 err) | 5030 W (0 err) | 9261 R (0 err) | 9261 W (0 err) | 13517 R (0 err) | 13517 W (0 err) | 17780 R (0 err) | 17780 W (0 err) | 22025 R (0 err) | 22025 W (0 err) | 25818 R (0 err) | 25818 W (0 err) |每行输出都打印了程序执行的读取次数和写入次数,以及执行操作的过程中因为集群不可用而造成的错误数量。
$ redis 127.0.0.1:7000> set key_217 0 OK那么consistency-test将会像我们报告错误:
(in the other tab I see...) 94774 R (0 err) | 94774 W (0 err) | 98821 R (0 err) | 98821 W (0 err) | 102886 R (0 err) | 102886 W (0 err) | 114 lost | 107046 R (0 err) | 107046 W (0 err) | 114 lost |在我们修改计数器值的时候,计数器的正确值是114.但因为我们将计数器的值修改为0,所以程序报告说丢失了114个命令。
故障转移测试
$ redis-cli -p 7000 cluster nodes | grep master 3e3a6cb0d9a9a87168e266b0a0b24026c0aae3f0 127.0.0.1:7001 master - 0 1385482984082 0 connected 5960-10921 2938205e12de373867bf38f1ca29d31d0ddb3e46 127.0.0.1:7002 master - 0 1385482983582 0 connected 11423-16383 97a3a64667477371c4479320d683e4c8db5858b1 :0 myself,master - 0 0 0 connected 0-5959 10922-11422好了,我们发现7000,7001,7002是主节点,然后我们通过向7002端口发送DEBUG SEGFAULT命令,让这个主节点崩溃:
$ redis-cli -p 7002 debug segfault Error: Server closed the connection现在,我们将看到consistency-test程序将会报告大量的错误信息:
18849 R (0 err) | 18849 W (0 err) | 23151 R (0 err) | 23151 W (0 err) | 27302 R (0 err) | 27302 W (0 err) | ... many error warnings here ... 29659 R (578 err) | 29660 W (577 err) | 33749 R (578 err) | 33750 W (577 err) | 37918 R (578 err) | 37919 W (577 err) | 42077 R (578 err) | 42078 W (577 err) |正如你所看到的,在故障转移期间,总共丢失了578个都命令,577个写命令,然而却没有产生数据不一致。这样的结果听起来有点器官,因为在本教程的开始部分说:Redis使用异步复制的方法,其可能会在故障转移中间,丢失写命令。但是,我们也只是说可能,实际上,这种情况并不常见,因为Redis几乎是同时执行将命令回复发送给客户端,以及将命令复制给从节点。所以,实际上造成命令丢失的时间窗口是非常小的。但,实际情况是,概率小不等于不发生,因此,Redis集群并不能保证数据的强一致性。
$ redis-cli -p 7000 cluster nodes 3fc783611028b1707fd65345e763befb36454d73 127.0.0.1:7004 slave 3e3a6cb0d9a9a87168e266b0a0b24026c0aae3f0 0 1385503418521 0 connected a211e242fc6b22a9427fed61285e85892fa04e08 127.0.0.1:7003 slave 97a3a64667477371c4479320d683e4c8db5858b1 0 1385503419023 0 connected 97a3a64667477371c4479320d683e4c8db5858b1 :0 myself,master - 0 0 0 connected 0-5959 10922-11422 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e 127.0.0.1:7005 master - 0 1385503419023 3 connected 11423-16383 3e3a6cb0d9a9a87168e266b0a0b24026c0aae3f0 127.0.0.1:7001 master - 0 1385503417005 0 connected 5960-10921 2938205e12de373867bf38f1ca29d31d0ddb3e46 127.0.0.1:7002 slave 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e 0 1385503418016 3 connected现在,集群中的master主节点为7000,7001,7005,其中7005就是因为7002节点下线才变为主节点的。
- 节点ID:如 3fc783611028b1707fd65345e763befb36454d73 。
- ip:port:节点的 IP 地址和端口号, 例如 127.0.0.1:7000, 其中 :0 表示的是客户端当前连接的 IP 地址和端口号。
- flags :节点的角色(例如 master 、 slave 、 myself )以及状态(例如 fail ,等等)。
- 如果节点是一个从节点的话, 那么跟在 flags 之后的将是主节点的节点 ID : 例如 127.0.0.1:7002 的主节点的节点 ID 就是3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e 。
- 集群最近一次向节点发送 PING 命令之后, 过去了多长时间还没接到回复。
- 节点最近一次返回 PONG 回复的时间。
- 节点的配置纪元(configuration epoch):详细信息请参考 Redis 集群规范 。
- 本节点的网络连接情况:例如 connected 。
- 节点目前包含的槽:例如 127.0.0.1:7001 目前包含号码为 5960 至 10921 的哈希槽。
手动故障转移
使用CLUSTER FAILOVER命令可以在Redis集群中进行手动故障转移,注意,你必须对你想要转移的master节点的slave上执行该命令手动故障转移是非常特殊的,并且相对实际master节点失效导致的故障转移安全的多,因为,进行客户端从旧的master节点迁移到新的master节点上时,只有当系统已经确定新的master节点负责处理从旧的master节点执行复制流才会执行,其避免了在整个过程中数据丢失。
下面是你在执行手动故障转移时能够看到的服务日志:
# Manual failover user request accepted. # Received replication offset for paused master manual failover: 347540 # All master replication stream processed, manual failover can start. # Start of election delayed for 0 milliseconds (rank #0, offset 347540). # Starting a failover election for epoch 7545. # Failover election won: I'm the new master.基本上,客户端链接到master节点上进行故障转移是停止的。与此同时,master节点发送其复制偏移量给其slave节点,slave在等待偏移量到达。当复制偏移量到达slave节点时,开始执行故障转移过程,并且旧的master节点被告知进行配置切换。当个客户端在旧的master节点上完成操作之后,slave将重定向到新的master节点上。
添加新节点到集群中
- 如果要添加一个新节点是master主节点,那么我们需要创建一个空节点,然后将某些卡系统移动到这个空节点中。
- 如果要添加一个新节点是slave节点,我们需要将这个主节点设置为集群中某个节点的副本。
- 创建一个新的终端窗口
- 进入cluster-test目录
- 创建7006文件夹
- 在上一步基础之上,创建redis,conf文件,然后将端口改为7006.
- 使用命令”../redis-server ./redis.conf”命令启动节点
./redis-trib.rb add-node 127.0.0.1:7006 127.0.0.1:7000正如你所见,我们使用了add-node命令,第一个参数指明:新节点的地址与端口,第二个参数指明:集群中任意一个已经存在的节点的地址与端口。
redis 127.0.0.1:7006> cluster nodes 3e3a6cb0d9a9a87168e266b0a0b24026c0aae3f0 127.0.0.1:7001 master - 0 1385543178575 0 connected 5960-10921 3fc783611028b1707fd65345e763befb36454d73 127.0.0.1:7004 slave 3e3a6cb0d9a9a87168e266b0a0b24026c0aae3f0 0 1385543179583 0 connected f093c80dde814da99c5cf72a7dd01590792b783b :0 myself,master - 0 0 0 connected 2938205e12de373867bf38f1ca29d31d0ddb3e46 127.0.0.1:7002 slave 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e 0 1385543178072 3 connected a211e242fc6b22a9427fed61285e85892fa04e08 127.0.0.1:7003 slave 97a3a64667477371c4479320d683e4c8db5858b1 0 1385543178575 0 connected 97a3a64667477371c4479320d683e4c8db5858b1 127.0.0.1:7000 master - 0 1385543179080 0 connected 0-5959 10922-11422 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e 127.0.0.1:7005 master - 0 1385543177568 3 connected 11423-16383注意,新节点现在已经链接上了集群,已经成为集群的组成部分,并且可以通过客户端的命令请求进行重定向了。但是,和其他master节点相比,新节点还有两个区别,如下:
增加一个副本节点的方法
./redis-trib.rb add-node --slave 127.0.0.1:7006 127.0.0.1:7000注意:现在的这条命令和我们之前增加一个新节点的命令完全一样,因此,我们没有明确指明复制哪个master节点。在这种情况下:redis-trib将会为整个master节点中的任意一个增加其对应的新的包含少量复制的副本节点。
./redis-trib.rb add-node --slave --master-id 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e 127.0.0.1:7006 127.0.0.1:7000使用这种方法,我们就明确的分配了一个特定的master节点用来作为副本的目标对象。
redis 127.0.0.1:7006> cluster replicate 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912eOK。现在我们就拥有了这些哈希槽的一个新副本,集群中其余所有的节点都已经更新了自己的节点列表及配置。我们可以通过下面的命令来确认上面的结果:
$ redis-cli -p 7000 cluster nodes | grep slave | grep 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e f093c80dde814da99c5cf72a7dd01590792b783b 127.0.0.1:7006 slave 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e 0 1385543617702 3 connected 2938205e12de373867bf38f1ca29d31d0ddb3e46 127.0.0.1:7002 slave 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e 0 1385543617198 3 connected结果显示:3c3a0c...有两个slave节点,运行在端口7002与7006上。
移除一个节点
./redis-trib del-node 127.0.0.1:7000 `<node-id>`第一个参数:集群中任意一个节点。
副本迁移
CLUSTER REPLICATE <master-node-id>然而,这里存在着一个特殊情况:当你想从一个master节点自动的复制到另一个master节点,而不用系统管理员的协助。这种自动的对复制操作重配置方法被称为副本迁移,这种做法也能够提高Redis集群的可用性。
- 在给定的时刻,集群将会尝试从一个拥有大量副本对象的master节点上迁移一个副本对象。
- 为了从副本迁移中获得好处,你仅仅需要对集群中的一个单独的master节点增加少量的副本对象,至于是否为master节点无关紧要。
- 这里有一个配置参数控制着副本迁移的功能:cluster-migration-barrier,你可以在由Redis集群提供的redis,conf文件中了解到更多内容。
Redis集群中的节点升级
- 使用CLUSTER FAILOVER 手动触发master节点的故障转移,目标对象为其slave节点。
- 等待master转变为slave节点。
- 最后,按照slave升级的步骤,再升级该节点。
- 如果你想要刚刚升级的节点再次成为master节点,那么再手动触发一次故障转移操作,来达到这个目的。
迁移到Redis集群
- 多个key操作,或事务,或Lua脚本包含多个key,没有使用这些方法。Key的访问是独立的。(即使通过事务或Lua脚本将多个命令同时执行,对相同的key一起操作)
- 多个key操作,或事务,或Lua脚本包含多个key,使用了这些方法,但仅仅在这些key有相同的hash tag,意思就是说,这些一起使用的key都有一个恰好相同的子字符串“{...}”。举个例子,下面的多个key操作就在相同的hash tag上下文中:SUNION {user:1000}.foo {user:1000}.bar
- 多个key操作,或事务,或Lua脚本包含多个key,使用了这些方法,并且这些key的名称是不明确的,不相同的,或者hash tag也是不同的。
- 停止你的客户端。当前非自动的实时的迁移到Redis集群是有可能的。你可以在你的应用/环境中进行计划性的动态迁移。
- 为你的N个master节点每一个都生成一个AOF文件,使用BGREWRITEAOF命令,然后等待AOF文件写入完成。
- 将你的aof-1到aof-n文件保存在某处。在这种情况下,你可以停止这些旧的Redis实例(这种做法是非常有用的,因为在非虚拟机部署的条件下,你经常需要重复使用相同的计算机)。
- 创建一个由N个master节点和0个slave节点构成Redis集群。待会再增加slave节点。确保你的所有节点都是用aof文件实现持久化。
- 停止刚刚创建的所有节点,再用之前的aof文件替换这些节点目录下面aof文件,如,aof-1,aof-2等等
- 重新启动Reids集群节点,加载这些AOF文件。这些节点重新编译这些aof文件中的key,而不是依照它们的配置。
- 使用reids-trib fix命令来修复集群,使得这些keys能够按照每个节点的哈希槽正确的迁移。每个节点有已经授权的,当然也有未授权的。
- 使用redis-trib check命令在末尾检查,确保你的集群正确的运行。
- 重新启动客户端,修改为使用Redis集群感知客户端的库。