https://www.cnblogs.com/51life/p/10233340.html https://www.cnblogs.com/leeSmall/p/8398401.html(有拓扑图) https://www.cnblogs.com/vansky/p/9293980.html(各种同步、超时参数)
Redis有三种集群方式:主从复制,哨兵模式和分布式集群
一、Redis主从复制:
主节点负责写数据,从节点负责读数据,主节点定期把数据同步到从节点保证数据的一致性(读写分离)
1、Redis主从拓扑
a) 一主一从:用于主节点故障转移从节点,当主节点的“写”命令并发高且需要持久化,可以只在从节点开启AOF(主节点不需要),这样即保证了数据的安全性,也避免持久化对主节点的影响
b) 一主多从:针对“读”较多的场景,“读”由多个从节点来分担,但节点越多,主节点同步到多节点的次数也越多,影响带宽,也加重主节点的不稳定
c) 树状主从:一主多从的缺点(主节点推送次数多压力大)可用些方案解决,主节点只推送一次数据到从节点B,再由从节点B推送到C,减轻主节点推送的压力。
数据同步 redis 2.8版本以上使用psync命令完成同步,过程分“全量”与“部分”复制 全量复制:一般用于初次复制场景(第一次建立SLAVE后全量) 部分复制:网络出现问题,从节点再次连接主节点时,主节点补发缺少的数据,每次数据增量同步 心跳:主从有长连接心跳,主节点默认每10S向从节点发ping命令,repl-ping-slave-period控制发送频率
主从的缺点 a)主从复制,若主节点出现问题,则不能提供服务,需要人工修改配置(或者敲命令)将从变主(哨兵解决) b)主从复制主节点的写能力单机,能力有限(分布式集群解决) c)单机节点的存储能力也有限(分布式集群解决)
主从故障如何故障转移 a)主节点(master)故障,从节点slave-1端执行 slaveof|replicaof no one后变成新主节点; b)其它的节点成为新主节点的从节点,并从新节点复制数据; c)需要人工干预,无法实现高可用。
2、主从复制的相关操作
master配置修改端口:s0.conf
port 6379 requirepass 123456 masterauth 123456 #新增配置:下次作为从服务器登录主服务器密码
slave1修改配置: s1.conf
port 6380 #新增配置,注意ip不要用127.0.0.1 replicaof 192.168.174.131 6379 (5.x+) | slaveof 192.168.174.131 6379 requirepass 123456 masterauth 123456 pidfile "/var/run/redis_6380.pid" replica-read-only yes #从默认只读,从服务写会造成主从不一致,默认配置,不用改
slave2修改配置: s2.conf
port 6381 replicaof 192.168.174.132 6379 | 6380 #slave1的从服务器 requirepass 123456 masterauth 123456 pidfile "/var/run/redis_6381.pid"
requirepass是认证密码,之后要作主从切换,所以建议所有的密码都一致, masterauth是从机访问主机时,所需的密码(即主机的requirepass)
启动主机: redis-server s0.conf
启动从机: redis-server s1.conf redis-server s2.conf
验证主从复制:
master: [root@localhost master]# redis-cli 127.0.0.1:6379> auth 123456 OK 127.0.0.1:6379> set test chenqm OK 127.0.0.1:6379> info replication role:master connected_slaves:2 slave0:ip=127.0.0.1,port=6380,state=online,offset=2559,lag=0 slave1:ip=127.0.0.1,port=6381,state=online,offset=2559,lag=0 ...... slave1: [root@localhost slave2]# redis-cli -p 6380 127.0.0.1:6380> auth 123456 OK 127.0.0.1:6380> get test "chenqm" slave2: [root@localhost slave2]# redis-cli -p 6381 127.0.0.1:6381> auth 123456 OK 127.0.0.1:6381> get test "chenqm"
切换主从: 主节点shutdown后,将从节点转换成为主节点
127.0.0.1:6380> replicaof no one | slaveof no one
将当前节点转变为另一节点的从节点
127.0.0.1:6381> replicaof 192.168.174.131 6380 | slaveof 127.0.0.1 6380
二、哨兵模式:
万一主机挂了,redis提供了一个sentinel(哨兵),以此实现主从切换的功能(哨兵只监控主机,从机挂机不影响)
哨兵模式是一种特殊的模式,首先Redis提供了哨兵的命令,哨兵是一个独立的进程,作为进程,它会独立运行。其原理是哨兵通过发送命令,等待Redis服务器响应,从而监控运行的多个Redis实例 1、通过发送命令,让Redis服务器返回监控其运行状态,包括主服务器和从服务器。 2、当哨兵监测到master宕机,会自动将slave切换成master,然后通过发布订阅模式通知其他的从服务器,修改配置文件,让它们切换主机。 3、一个哨兵进程对Redis服务器进行监控,可能会出现问题,为此,我们可以使用多个哨兵进行监控。各个哨兵之间还会进行监控,这样就形成了多哨兵模式。 4、只要设定待监控的主服务,并给它取一个唯一的名称,从服务会被自动检查到,不需要手动指定。
配置sentinel: vi sentinel.conf:(redis根目录下存在./sentinel.conf,src下存在redis-sentinel命令)
port 26379 daemonize yes protected-mode no sentinel monitor mymaster 192.168.174.131 6379 1 sentinel auth-pass mymaster 123456
#哨兵服务端口 port 26379 #哨兵监控的master,当集群中有超过一半以上 及 2个(quorum)哨兵认为master死了时,才能真正认为该master已经不可用了【注意这里ip不能写127.0.0.1,否则将来程序也会去找127.0.0.1】 sentinel monitor mymaster 192.168.174.131 6379 2 (quorum) #设置master和slave验证密码(sentinel不能分别为master和slave设置不同的密码,因此master和slave的密码应该设置相同) sentinel auth-pass mymaster 123456 #守护进程模式 daemonize yes #关闭保护模式 protected-mode no #master或slave多长时间(默认10秒)不能使用后标记为s_down状态。 sentinel down-after-milliseconds mymaster 3000 #从节点执行replicaof no one命令一直失败的话,当时间超过18S时则故障转移失败 sentinel failover-timeout mymaster 18000
1、启动sentinel服务:
./redis-sentinel ../sentinel.conf
注意启动的顺序:首先主机服务,然后启动从机服务,最后启动哨兵服务
2、关闭master进程:kill -9 6379 (使用shutdown退出有时候不会修改配置文件)
3、查看客户端
master切换了,当6379端口的这个服务重启的时候,他会变成slave。 因为sentinel在切换master的时候,把对应的sentinel.conf和redis.conf文件的配置修改。
4、多哨兵模式下选举 调研Redis高可用两种方案_服务器 这个选举的大体思路是: 每个哨兵节点通过向其他哨兵节点发送”sentinel is-master-down-by addr”命令来申请成为哨兵领导者。 而每个哨兵节点在收到一个”sentinel is-master-down-by addr”命令时,只允许给第一个节点投票,其他节点的该命令都会被拒绝。 如果一个哨兵节点收到了半数以上的同意票半且超过它配置的quorum的票数,则成为哨兵领导者。
哨兵模式的优缺点: 优点: 哨兵模式是基于主从模式的,所有主从的优点,哨兵模式都具有。 主从可以自动切换,系统更健壮,可用性高。 缺点: Redis较难支持在线扩容,在集群容量达到上限时在线扩容会变得很复杂。
三、Redis-Cluster分布式集群
Redis的哨兵模式基本已经可以实现高可用,读写分离,但是在这种模式下每台redis服务器都存储相同的数据,浪费内存,所以在Redis3.0以上加入了cluster模式,实现的redis的分布式存储,也就是说每台redis节点上存储不同的内容。
搭建分布式集群: (工具连接只需要连接任一主机,可以看到所有数据,但必须保证任一组主从有一个没挂)
1、创建cluster目录,分别配置多个redis.conf,(6个r1-r6)官方建议至少3主3从
redis.conf:
#pidfile文件对应6000,6001,6002,6003,6004,6005 pidfile /var/run/redis_6000.pid #端口6000,6001,6002,6003,6004,6005 port 6000 masterauth "123456" requirepass "123456" #新增 cluster-enabled yes cluster-config-file nodes_6000.conf #nodes_6001.conf ... cluster-node-timeout 5000
2、分别启动6个服务器
redis-server r1.conf redis-server r2.conf ... #检查启动情况 ps -ef|grep redis
3、Redis5.0开始不再使用ruby搭建集群,使用命令redis-cli:(注意不要写127.0.0.1)
redis-cli --cluster create 192.168.174.131:6001 192.168.174.131:6002 192.168.174.131:6003 192.168.174.131:6004 192.168.174.131:6005 192.168.174.131:6006 -a 123456 --cluster-replicas 1
出现Can I set the above configration?(type 'yes' to accept): 输入 yes
replicas 1 表示我们希望为集群中的每个主节点创建一个从节点 手动挂载从节点: redis-cli --cluster add-node 192.168.174.131:6007 192.168.174.131:6008 --cluster-slave --cluster-master-id ba8415845612eceeb50f89eaa44485a393b58d1a
创建集群出错:[ERR] Node xxxxx is not empty. Either the node already knows other nodes (check with CLUSTER NODES)
解决方法:
1)、停止所有redis进程,将需要新增的节点下aof、rdb等本地备份文件删除; 2)、同时将新Node的集群配置文件删除,即:删除redis.conf里面cluster-config-file所在的文件,一般为nodes.conf; 3)、再次添加新节点如果还是报错,对数据库进行清除: 192.168.174.131:6000> flushdb
4、测试:
打开端口为6000的客户端 查看: [root@localhost master]# redis-cli -c -p 6001 -a 123456 127.0.0.1:6000> cluster info 127.0.0.1:6000> cluster slots 127.0.0.1:6000> set id 111 -> Redirected to slot [7568] located at 127.0.0.1:6002 OK 127.0.0.1:6002> get id "122"
5、集群下配置哨兵(集群下能自动主从切换,主节点挂了从节点自动成为主节点)
port 26379 daemonize yes protected-mode no logfile "/var/log/sentinel.log" sentinel monitor mymaster1 192.168.174.131 6001 1 sentinel monitor mymaster2 192.168.174.131 6002 1 sentinel monitor mymaster3 192.168.174.131 6003 1 sentinel auth-pass mymaster1 123456 sentinel auth-pass mymaster2 123456 sentinel auth-pass mymaster3 123456
6、从节点读取不了数据(error) MOVED
原因:Redis Cluster集群中的从节点,默认设置的是不分担读请求的、只作备份和故障转移用 解决办法:在get数据之前先使用命令readonly
指令集合: 集群: cluster info :打印集群的信息 cluster slots: 打印集群节点信息(主从和槽信息) cluster nodes :列出集群当前已知的所有节点( node),以及这些节点的相关信息。
节点: cluster meet <ip> <port> :将 ip 和 port 所指定的节点添加到集群当中,让它成为集群的一份子。 cluster forget <node_id> :从集群中移除 node_id 指定的节点。 cluster replicate <master_node_id> :将当前从节点设置为 node_id 指定的master节点的slave节点。只能针对slave节点操作。 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 槽中的键 。