Redis集群:存储能力受单机限制,以及无法实现写操作的负载均衡。
一、集群的作用
集群(Redis Cluster),是Redis 3.0开始引入的分布式存储方案。由多个节点(Node)组成,Redis的数据分布在这些节点中;集群中的节点分为主节点和从节点:只有主节点负责读写请求!!和集群信息的维护;从节点负责高可用,只进行主节点数据和状态信息的复制。
为什么从节点只负责高可用?不进行读操作?
slot的事根据 master 的地址构建的,因此可以知晓 RedisCluster 从节点是不提供读服务,只做高可用。
你觉得RedisCluster的从节点可以进行读操作嘛? 狐狸教程
作用:
- 数据分片:集群最核心的功能,将数据分散到多个节点,突破了Redis单机内存大小的限制,存储容量大大增加;每个主节点都可以对外提供读服务和写服务,大大提高了集群的响应能力。
- 高可用:集群支持主从复制和主节点的自动故障转移(与哨兵类似);当任一节点发生故障时,集群仍然可以对外提供服务。
二、集群的搭建
搭建一个简单的集群:共6个节点,3主3从。在同一台服务器上,以端口号进行区分;主节点端口号:7000/7001/7002,从节点端口号:8000/8001/8002。
群的搭建有两种方式:
- 手动执行Redis命令,一步步完成搭建;
- 使用Ruby脚本搭建。原理相同,将Redis命令进行了打包封装。
1、Redis命令搭建集群
可分为四步:
- 启动节点:将节点以集群模式启动,此时节点是独立的,并没有建立联系;
- 节点握手:让独立的节点连成一个网络;
- 分配槽:将16384个槽分配给主节点;
- 指定主从关系:为从节点指定主节点;前三步完成后集群便可以对外提供服务,指定主从节点为了提供高可用的服务。
1、启动节点
使用集群模式启动,通过配置文件设置cluster-enabled yes;
// 配置文件
// 在启动节点阶段,节点是没有主从关系的,因此从节点不需要加slaveof配置。
// 而且集群的主从关系指定使用cluster replicate命令。
#redis-7000.conf
port 7000
cluster-enabled yes
cluster-config-file "node-7000.conf"
logfile "log-7000.log"
dbfilename "dump-7000.rdb"
daemonize yes
// 使用redis-server启动节点
redis-server redis-7000.conf
cluster-enabled yes:Redis实例可以分为单机模式(standalone)和集群模式(cluster);cluster-enabled yes可以启动集群模式。单机模式下执行info server输出的redis_mode为standalone;集群模式下为cluster。
cluster-config-file:指定了集群配置文件的位置。每个节点都会维护一份集群配置文件,集群配置文件由Redis节点维护,不需要人工修改。每当集群发生变化时(如增减节点),集群内所有节点会将最新信息更新到该配置文件;节点重启后,会重新读取该配置文件,获取集群信息,可以方便的重新加入到集群中。也就是说,当Redis节点以集群模式启动时,会首先寻找是否有集群配置文件,如果有则使用文件中的配置启动,如果没有,则初始化配置并将配置保存到文件中。
cluster nodes可以查看集群中所有节点信息:
节点ID和runid的区别?
第一项表示节点id,由40个16进制字符串组成,节点id与 主从复制 一文中提到的runId不同,Redis每次启动runId都会重新创建,但是节点id只在集群初始化时创建一次,并保存到集群配置文件中,以后节点重新启动时会直接在集群配置文件中读取。
2、节点握手
节点启动后是相互独立的,并不知道其他节点存在;需要进行节点握手,将独立的节点组成一个网络。
节点握手命令cluster meet {ip} {port}:如在7000节点中执行cluster meet 192.168.72.128 7001,可以完成7000节点和7001节点的握手;注意ip使用的是局域网ip而不是localhost或127.0.0.1,是为了其他机器上的节点或客户端也可以访问。
在一个节点中,通过cluster meet完成所有节点的握手,这样集群内的节点都可以彼此感知通信:
cluster meet 192.168.72.128 7002
cluster meet 192.168.72.128 8000
cluster meet 192.168.72.128 8001
cluster meet 192.168.72.128 8002
3、分配槽
集群中借助槽实现数据分区,集群共有16384个槽(2^14),槽是数据管理和迁移的基本单位。集群所有槽都分配了节点时,集群处于上线状态(ok);如果有任意一个槽没有分配节点,则集群处于下线状态(fail)。
cluster addslots命令:分配槽给节点,槽的编号0-16383;
// 槽的分配
redis-cli -p 7000 cluster addslots {0..5461}
redis-cli -p 7001 cluster addslots {5462..10922}
redis-cli -p 7002 cluster addslots {10923..16383}
槽的分配信息,存储在clusterNode的slots数组和clusterState的slots数组中,两者的区别是:前者存储的是该节点中分配了哪些槽,后者存储的是所有槽分别分布在哪个节点。命令执行过程如下:
- 校验槽:遍历需要插入的输入槽,检查它们是否都没有分配,如果有一个槽已分配,命令执行失败;方法是检查输入槽在clusterState.slots[]中对应的值是否为NULL;
- 插入槽:遍历输入槽,将其分配给节点A;方法是修改clusterNode.slots[]中对应的比特为1,以及clusterState.slots[]中对应的指针指向A节点;
- 消息散播:执行完成后,该节点通过通信机制通知其他节点,所有节点都会知道0..5461的槽分配给了该节点。
4、指定主从关系
集群中指定主从关系不再使用slaveof命令,而是使用cluster replicate命令;参数使用节点id。
为从节点指定主节点&#x