Redis学习笔记之十三:Redis集群

来源:互联网 发布:软件测试员培训 编辑:程序博客网 时间:2024/06/05 03:55

    1、Redis开启集群

    默认情况下Redis并没有开启集群模式,如果想要开启,需要将配置中的cluster-enabled修改为yes便开启了集群模式。在这个模式下与单机模式有点区别:只能使用0号数据库。 Redis在启动时会默认创建16个数据库,编号 0 ~ 15,使用指令SELECT可以选择数据库,默认是0号,如果你的Redis开启了AOF,打开AOF文件最上面的指令一定是SELECT。如图:


    第二点区别在于不能使用slaveof指令复制主数据库的数据:


    修改配置文件启动Redis后 就进入集群模式了,可以使用指令CLUSTER NODES查看集群内有哪些节点(一个节点就为一个Redis服务器)。


    可以看到当前集群中只有一个节点,那就是当前服务器(图中的myself指向自己)。除此之外,服务器依旧可以使用单机模式下(非集群模式)的所有功能。


    2、节点连接

    以不同的端口号启动6个Redis服务实例,注意配置文件以及端口千万不要使用同一个。结果如下:


    如果不使用Redis提供的工具redis-trib(这个工具在src目录下),用不着6个实例。

    然后进入到src目录执行指令 

 ./redis-trib.rb create --replicas 1 127.0.0.1:6379 127.0.0.1:6380 127.0.0.1:6381 127.0.0.1:6382 127.0.0.1:6383 127.0.0.1:6384
    后面的ip地址就是启动的Redis实例的ip以及端口。这点可以参考Redis官网文档。

    如果启动没有报错,将看到以下(部分输出)结果:


    如果启动报错,那么可能有以下几个原因:

    ①、指令后面的ip地址中有的实例没有启动或者没有启动成功。

    ②、给定的实例数不足6个,脚本需要6个实例(3主3从)。

    ③、提示slots被使用了,进入各个服务器,使用指令cluster slots找到使用的槽,然后使用指令cluster delslot删除掉,或者使用cluster reset指令重置,然后再重试。

    如果启动没有报错,但是无法形成集群,那么可能有以下几个原因:

    ①、使用了同一个配置文件,这种修改为各个实例使用不同的配置文件。

    ②、在复制实例之前 已经开启了集群模式并启动了,由于集群模式会使用一个nodes.conf文件用来保存集群中各个节点的信息,这种情况下复制所有实例都是使用的同一个nodes.conf,会认为是同一个节点。所以删除nodes.conf文件重启,这个文件会自动创建,所以不用担心。

    启动成功后启动客户端执行指令cluster nodes查看节点,其实就是查看nodes.conf文件。


    可以看到有6个节点 3个master 3个slave。其中myself表示当前节点,从图中可以看到当前节点是一个从服务器。除了使用Redis提供的工具之外,还可以使用指令cluster meet ip port进行节点连接,Redis提供的工具也正是这样做的。

    

    3、槽指派

    仔细看2中cluster nodes指令的执行结果,可以看到主节点的末尾有一个数字范围,这称为槽。Redis集群一共有16384个槽,每个节点负责处理一部分槽,只有当所有槽都分配完毕后,集群才能正常使用。

    3.1、槽与数据的关系

    Redis集群在使用时,会通过一个函数计算Key对应的槽数值,然后检查负责处理该槽的节点是哪一个,如果是自己,就自己处理,否则就会发出一条MOVED指令,告知客户端去请求对应的节点。整个结果如下图所示:


    所以username会交给右边的master节点进行处理。

    查看节点有哪些槽可以使用cluster slots指令,查看Key对应的槽值使用cluster keyslot指令。


    可以看到username的槽值为14315。


    3.2、MOVED指令

    这个指令类似于HTTP协议中的Redirect,客户端在收到这个指令时,并不会打印出来,而是会直接去请求目标节点。在单机模式下的客户端会打印出MOVED错误,如下:


    如果客户端以集群模式启动,则不会打印错误,而是会像浏览器遇到304那样,直接去请求目标节点。


    -c表示以集群模式启动客户端。


    4、添加新的节点

    当集群已经工作一段时间后,发现想要加入新的节点,假设节点端口为6385. 启动客户端进入6385端口所在的服务器:执行cluster meet指令将将当前节点加入到已有集群中:


    可以看到加入到了集群中,且当前节点是一个主节点,但处理的槽为空。 这时可以使用指令cluster setslot指令进行槽迁移。

    ①、向新加入的节点发送指令,告诉节点14315这个槽将交给你来处理,你到这个节点去导入。


    ②、向槽所在的节点发送指令,告诉槽所在的节点,这个槽将要迁移到目标节点中。


    这个指令必须发送给槽所在的节点。

    ③、向槽所在的节点发送指令,要迁移多少键到目标节点中。


    表示要从14315槽迁移100个键到指定槽,然后向槽指定的节点发送指令,将数据迁移到指定的节点。


    表示迁移到主机为localhost,端口为6385,迁移的键名为username,数据库为0号数据库,超时时间为10(s?ms?).

    由于集群模式下只能使用0号数据库,所以数据库固定了。 一直重复3,直到14315槽的数据全部迁移完毕。

    这时可以查看username在哪个数据库了。


    在端口为6381的服务器查看username提示ASK错误,在端口为6385的服务器查看:


    可以看到都是ASK错误,ASK错误表示两个节点的数据还在迁移中,所以还有最后一步

    ④、向目标节点发送消息,告诉目标节点数据已经迁移完毕


    在《Redis设计与实现》书中说的是任意节点发送此指令即可,但不知道什么原因,这种方式不行:


    一直在Redirect。然后再调用指令cluster nodes,可以发现14315槽交给了6385的端口处理了,如果要迁移的槽没有数据就直接发送④指令了。


    后面表示还有10号槽要迁移。


    5、故障处理

    还记得有从节点吗? 当主节点发生故障时,会从该主节点的从节点中选择出一个节点作为新的主节点,并将主节点的槽交由从节点处理,当之前的主节点修复故障后重新启动,会作为现主节点的从节点继续工作。


参考资料

    《Redis的设计与实现》

    



原创粉丝点击