Redis集群方式共有三种:主从模式,哨兵模式,cluster(集群)模式

主从模式:是三种集群方式里最简单的。它主要是基于Redis的主从复制特性架构的。通常我们会设置一个主节点,N个从节点;默认情况下,主节点负责处理使用者的IO操作,而从节点则会对主节点的数据进行备份,并且也会对外提供读操作的处理。主要的特点如下:

主从模式下,当某一节点损坏时,因为其会将数据备份到其它Redis实例上,这样做在很大程度上可以恢复丢失的数据

主从模式下,可以保证负载均衡

主从模式下,主节点和从节点是读写分离的。使用者不仅可以从主节点上读取数据,还可以很方便的从从节点上读取到数据,这在一定程度上缓解了主机的压力

从节点也是能够支持写入数据的,只不过从从节点写入的数据不会同步到主节点以及其它的从节点下

复制架构中出现宕机情况,怎么办?

如果在主从复制架构中出现宕机的情况,需要分情况看

一. 从Redis宕机

1.在Redis中从库重新启动后会自动加入到主从架构中,自动完成同步数据

如果从库在断开期间,主库的变化不大,从库再次启动后,主库依然会将所有的数据做RDB操作吗?还是增量更新?(从库有做持久化的前提下)

不会,因为在Redis2.8版本后就实现了,主从断线后恢复的情况下实现增量复制

二. 主Redis宕机

1.第一步,在从数据库中执行SLAVEOF NO ONE命令,断开主从关系并且提升为主库继续服务

2.第二步,将主库重新启动后,执行SLAVEOF命令,将其设置为其他库的从库,这时数据就能更新回来

这个手动完成恢复的过程其实是比较麻烦的并且容易出错,有没有好办法解决呢?当前有的,Redis提高的哨兵(sentinel)的功能。

优点:

1.高可靠性,主从实时备份,有效解决单节点数据丢失问题。

2.可做读写分离,从库分担读操作,缓解主库压力

缺点:

主库异常,需要手动主从切换

哨兵模式

哨兵模式:是基于主从模式做的一定变化,它能够为Redis提供了高可用性。其实,哨兵模式的核心还是主从复制。只不过相对于主从模式在主节点宕机导致不可写的情况下,多了一个竞选机制——从所有的从节点竞选出新的主节点。竞选机制的实现,是依赖于在系统中启动一个sentinel(哨兵)进程。哨兵是一个独立的进程,作为进程,它会独立运行。其原理是哨兵通过发送命令,等待Redis服务器响应,从而监控运行的多个Redis实例
 

哨兵两个作用

1.通过发送命令,让Redis服务器返回监控其运行状态,包括主服务器和从服务器

2.当哨兵监测到master宕机,会自动将slave切换成master,然后通过发布订阅模式通知其他的从服务器,修改配置文件,让它们切换主机

然而一个哨兵进程对Redis服务器进行监控,可能会出现问题,为此,我们可以使用多个哨兵进行监控。各个哨兵之间还会进行监控,这样就形成了多哨兵模式

sentinel特点

1.监控:它会监听主服务器和从服务器之间是否在正常工作。

2.通知:它能够通过API告诉系统管理员或者程序,集群中某个实例出了问题。

3.故障转移:它在主节点出了问题的情况下,会在所有的从节点中竞选出一个节点,并将其作为新的主节点。

4.提供主服务器地址:它还能够向使用者提供当前主节点的地址。这在故障转移后,使用者不用做任何修改就可以知道当前主节点地址

故障切换

假设主服务器宕机,哨兵1先检测到这个结果,系统并不会马上进行failover过程,仅仅是哨兵1主观的认为主服务器不可用,这个现象成为主观下线。当后面的哨兵也检测到主服务器不可用,并且数量达到一定值时,那么哨兵之间就会进行一次投票,投票的结果由一个哨兵发起,进行failover操作。切换成功后,就会通过发布订阅模式,让各个哨兵把自己监控的从服务器实现切换主机,这个过程称为客观下线。这样对于客户端而言,一切都是透明的
 

sentinel,也可以集群,部署多个哨兵,sentinel可以通过发布与订阅来自动发现Redis集群上的其它sentinel。sentinel在发现其它sentinel进程后,会将其放入一个列表中,这个列表存储了所有已被发现的sentinel

集群中的所有sentinel不会并发着去对同一个主节点进行故障转移。故障转移只会从第一个sentinel开始,当第一个故障转移失败后,才会尝试下一个。当选择一个从节点作为新的主节点后,故障转移即成功了(而不会等到所有的从节点配置了新的主节点后)。这过程中,如果重启了旧的主节点,那么就会出现无主节点的情况,这种情况下,只能重启集群
 

当竞选出新的主节点后,被选为新的主节点的从节点的配置信息会被sentinel改写为旧的主节点的配置信息。完成改写后,再将新主节点的配置广播给所有的从节点

优点:1、有效解决主从模式主库异常手动主从切换的问题

缺点:

1、运维复杂,哨兵选举期间,不能对外提供服务

2.资源浪费,Redis 数据节点中 slave 节点作为备份节点不提供服务;

3.Redis Sentinel 主要是针对 Redis 数据节点中的主节点的高可用切换,对 Redis 的数据节点做失败判定分为主观下线和客观下线两种,对于 Redis 的从节点有对节点做主观下线操作,并不执行故障转移。

4.不能解决读写分离问题,实现起来相对复杂。

5.使用Jedis实现了分片集群,是由客户端控制哪些key数据保存到哪个数据库中,如果在水平扩容时就必须手动进行数据迁移,而且需要将整个集群停止服务

Redis集群(cluster)

Redis 集群是一个提供在多个Redis间节点间共享数据的程序集。

Redis集群并不支持处理多个keys的命令,因为这需要在不同的节点间移动数据,从而达不到像

Redis那样的性能,在高负载的情况下可能会导致不可预料的错误.

Redis 集群通过分区来提供一定程度的可用性,在实际环境中当某个节点宕机或者不可达的情况下继续处理命令. Redis 集群的优势:

自动分割数据到不同的节点上。

整个集群的部分节点失败或者不可达的情况下能够继续处理命令。

Redis 集群的数据分片 Redis 集群没有使用一致性hash, 而是引入了 哈希槽的概念.

Redis 集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽.集群的每个节点负责一部分hash槽,举个例子,比如当前集群有3个节点,那么:

节点 A 包含 0 到 5500号哈希槽.

节点 B 包含5501 到 11000 号哈希槽.

节点 C 包含11001 到 16384号哈希槽.

这种结构很容易添加或者删除节点. 比如如果我想新添加个节点D, 我需要从节点 A, B, C中得部分槽到D上. 如果我想移除节点A,需要将A中的槽移到B和C节点上,然后将没有任何槽的A节点从集群中移除即可. 由于从一个节点将哈希槽移动到另一个节点并不会停止服务,所以无论添加删除或者改变某个节点的哈希槽的数量都不会造成集群不可用的状态.

Redis 集群的主从复制模型 为了使在部分节点失败或者大部分节点无法通信的情况下集群仍然可用,所以集群使用了主从复制模型,每个节点都会有N-1个复制品.

在我们例子中具有A,B,C三个节点的集群,在没有复制模型的情况下,如果节点B失败了,那么整个集群就会以为缺少5501-11000这个范围的槽而不可用.

然而如果在集群创建的时候(或者过一段时间)我们为每个节点添加一个从节点A1,B1,C1,那么整个集群便有三个master节点和三个slave节点组成,这样在节点B失败后,集群便会选举B1为新的主节点继续服务,整个集群便不会因为槽找不到而不可用了

不过当B和B1 都失败后,集群是不可用的.

Redis 一致性保证 Redis 并不能保证数据的强一致性. 这意味这在实际中集群在特定的条件下可能会丢失写操作.

第一个原因是因为集群是用了异步复制. 写操作过程:

客户端向主节点B写入一条命令.

主节点B向客户端回复命令状态.

主节点将写操作复制给他得从节点 B1, B2 和 B3.

主节点对命令的复制工作发生在返回命令回复之后, 因为如果每次处理命令请求都需要等待复制操作完成的话, 那么主节点处理命令请求的速度将极大地降低 —— 我们必须在性能和一致性之间做出权衡。 注意:Redis 集群可能会在将来提供同步写的方法。 Redis 集群另外一种可能会丢失命令的情况是集群出现了网络分区, 并且一个客户端与至少包括一个主节点在内的少数实例被孤立。

举个例子 假设集群包含 A 、 B 、 C 、 A1 、 B1 、 C1 六个节点, 其中 A 、B 、C 为主节点, A1 、B1 、C1 为A,B,C的从节点, 还有一个客户端 Z1 假设集群中发生网络分区,那么集群可能会分为两方,大部分的一方包含节点 A 、C 、A1 、B1 和 C1 ,小部分的一方则包含节点 B 和客户端 Z1 .

Z1仍然能够向主节点B中写入, 如果网络分区发生时间较短,那么集群将会继续正常运作,如果分区的时间足够让大部分的一方将B1选举为新的master,那么Z1写入B中得数据便丢失了.

注意, 在网络分裂出现期间, 客户端 Z1 可以向主节点 B 发送写命令的最大时间是有限制的, 这一时间限制称为节点超时时间(node timeout), 是 Redis 集群的一个重要的配置选项

Redis主从复制搭建

master 192.168.100.40
slave1 192.168.100.30
slave2 192.168.100.20

#三台服务器都搭建Redis数据库

关闭防火墙

systemctl stop firewalld
setenforce 0

 安装依赖环境

yum install -y gcc gcc-c++ make

解压文件到指定文件夹

tar zxvf redis-5.0.7.tar.gz
cd /opt/redis-5.0.7/

 安装

make
make PREFIX=/usr/local/redis install 
#执行软件包提供的install_server.sh 脚本文件,设置Redis服务所需要的相关配置文件

执行软件包提供的脚本文件

cd /opt/redis-5.0.7/utils
./install_server.sh

按四下回车在下面这行后面
Please select the redis executable path []
输入/usr/local/redis/bin/redis-server

创建软链接

ln -s /usr/local/redis/bin/* /usr/local/bin/

开启重启查看Redis服务

/etc/init.d/redis_6379 start


/etc/init.d/redis_6379 restart

/etc/init.d/redis_6379 status

netstat -natp | grep 6379

redis的集群和主从 redis主从属于集群吗_Redis

redis的集群和主从 redis主从属于集群吗_大数据_02

  

redis的集群和主从 redis主从属于集群吗_redis_03

redis的集群和主从 redis主从属于集群吗_服务器_04

  

redis的集群和主从 redis主从属于集群吗_大数据_05

 

redis的集群和主从 redis主从属于集群吗_服务器_06

在Master节点 修改Redis配置文件

vim /etc/redis/6379.conf


bind 0.0.0.0      #70行,修改监听地址为0.0.0.0

appendonly yes                   #700行,开启AOF持久化功能

redis的集群和主从 redis主从属于集群吗_Redis_07

redis的集群和主从 redis主从属于集群吗_Redis_08

 

 重启服务

/etc/init.d/redis_6379 restart

redis的集群和主从 redis主从属于集群吗_服务器_09

 在slave节点   修改Redis配置文件

vim /etc/redis/6379.conf


bind 0.0.0.0                      #70行,修改监听地址为0.0.0.0

appendonly yes                    #700行,开启AOF持久化功能


replicaof 192.168.100.40 6379     #288行,指定要同步的Master节点IP和端口

redis的集群和主从 redis主从属于集群吗_服务器_10

redis的集群和主从 redis主从属于集群吗_服务器_11

 

redis的集群和主从 redis主从属于集群吗_服务器_12

 

slave节点配置与master节点类似使用scp命令进行远程传输后进行修改

redis的集群和主从 redis主从属于集群吗_redis的集群和主从_13

 

 查看主从服务器是否连接

/etc/init.d/redis_6379 restart

netstat -natp | grep redis

redis的集群和主从 redis主从属于集群吗_redis的集群和主从_14

 查看Master节点上看日志

tail /var/log/redis_6379.log

redis的集群和主从 redis主从属于集群吗_redis_15

在Master节点上验证从节点

redis的集群和主从 redis主从属于集群吗_大数据_16

 

  在master节点上添加数据并在从节点查看

[root@localhost ~]# redis-cli 
127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379> set num a
OK
127.0.0.1:6379> get num
"a"

redis的集群和主从 redis主从属于集群吗_大数据_17

redis的集群和主从 redis主从属于集群吗_大数据_18

 

 Redis哨兵模式搭建

master 192.168.100.40
slave1 192.168.100.30
slave2 192.168.100.20
sentinel-1: 1992.168.100.60
sentinel-2: 1992.168.100.50
sentinel-3: 1992.168.100.10

修改sentinel哨兵模式配置文件

vim /opt/redis-5.0.7/sentinel.conf
 
protected-mode no                  #17行,关闭保护模式
port 26379                         #21行,Redis哨兵默认的监听端口
daemonize yes                      #26行,指定sentine1为后台启动
logfile"/var/log/sentinel.log"     #36行,指定日志存放路径
dir"/var/lib/redis/6379"           #65行,指定数据库存放路径

sentinel monitor mymaster 192.168.100.40 6379 2
#84行,修改指定该哨兵节点监控192.168.100.40:6379这个主节点,该主节点的名称是mymaster,最后的2的含义与主节点的故障判定有关:至少需要2个哨兵节点同意,才能判定主节点故障并进行故障转移

sentinel down-after-milliseconds mymaster 3000
#113行,判定服务器down掉的时间周期,默认30000毫秒(30秒)

sentinel failover-timeout mymaster 180000
#146行,同一个sentine1对同一个master两次failover之间的间隔时间(180秒)
 
#远程传续将配置文件传输给其他哨兵服务器
scp /opt/redis-5.0.7/sentinel.conf 192.168.100.60:/opt/redis-5.0.7/
scp /opt/redis-5.0.7/sentinel.conf 192.168.100.50:/opt/redis-5.0.7/

启动哨兵模式

cd /opt/redis-5.0.7/
redis-sentinel sentinel.conf &


#所有哨兵服务器执行

查询哨兵消息

redis-cli -p 26379 info sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=192.168.239.10:6379,slaves=2,sentinels=3
[1]+  完成                  redis-sentinel sentinel.conf

故障模拟

ps -ef | grep redis  #在master节点查看redis-server进程号
 

kill -9 19942        #杀死master节点redis-server进程

验证结果

tail -f /var/log/sentinel.log

在哨兵上查看是否转换成功

redis-cli -p 26379 info sentinel

# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=192.168.100.40:6379,slaves=2,sentinels=3

故障恢复

rm -rf /var/run/redis_6379.pid  #删除pid文件如果pid文件不删除则服务起不来
/etc/init.d/redis_6379 start    #启动服务
netstat -natp |grep 6379  

redis-cli info replication       #主服务器查看

Redis 群集模式

redis的集群六个节点 3主3从
master1    192.168.100.40    redis-5.0.7.tar.gz
master2    192.168.100.41    redis-5.0.7.tar.gz
master3    192.168.100.42    redis-5.0.7.tar.gz
slave1    192.168.100.50    redis-5.0.7.tar.gz
slave2    192.168.100.51    redis-5.0.7.tar.gz
slave3    192.168.100.52    redis-5.0.7.tar.gz

关闭防火墙

systemctl stop firewalld.service
systemctl disable firewalld.service
setenforce 0

开启集群功能

修改服务器配置文件

vim /opt/redis-5.0.7/redis.conf
 
bind 192.168.100.40                       #69行,注释掉bind项,改为自己
protected-mode no                         #88行,修改,关闭保护模式
port 6379                                 #92行redis默认监听端口,
daemonize yes                             #136行,开启守护进程,以独立进程启动
cluster-enabled yes                       #832行,取消注释,开启群集功能
cluster-config-file nodes-6001.conf       #840行,取消注释,群集名称文件设置
cluster-node-timeout 15000                #846行,取消注释群集超时时间设置
appendonly yes                            #700行,修改,开启AOF持久化
#远程传输完要修改监听地址为自己
scp /opt/redis-5.0.7/redis.conf 192.168.100.41:/opt/redis-5.0.7/
scp /opt/redis-5.0.7/redis.conf 192.168.100.42:/opt/redis-5.0.7/
scp /opt/redis-5.0.7/redis.conf 192.168.100.50:/opt/redis-5.0.7/
scp /opt/redis-5.0.7/redis.conf 192.168.100.51:/opt/redis-5.0.7/
scp /opt/redis-5.0.7/redis.conf 192.168.100.52:/opt/redis-5.0.7/

启动集群节点

/etc/init.d/redis_6379 restart

启动集群

redis-cli --cluster create 192.168.100.41:6001 192.168.100.42:6001 192.168.100.51:6001 192.168.100.52:6001 192.168.100.40:6001 192.168.80.45:6001 --cluster-replicas 1
#六个实例分为三组,每组一主一从,前面的做主节点,后面的做从节点。下面交互的时候需要输入yes 才可以创建。
-replicas 1       #表示每个主节点有1个从节点

测试群集

redis-cli -h 192.168.100.40 -p 6379 -c           #加-c参数,节点之间可以互相跳转
192.168.100.40:6379> cluster slots               #查看节点哈希槽编号范围
1) 1) (integer) 5461
   2) (integer) 10922                            #哈希槽编号范围
   3) 1) "192.168.100.41"  
      2) (integer) 6379                          #主节点ip和端口
      3) "052ac2ee43622afd452gdfh16774gd4787w1899d"
   4) 1) "192.168.239.60" 
      2) (integer) 6379                          #从节点ip和端口
      3) "268asf3gsdq27j54grgj3q488235dfg33a68hw2q"
2) 1) (integer) 0
   2) (integer) 5460
   3) 1) "192.168.100.42"
      2) (integer) 6379
      3) "310asje3h89dfbfd8032janm493fa891feh13b69"
   4) 1) "192.168.100.51"
      2) (integer) 6379
      3) "565qwefrh317fejk46w2w8defaq4au76gnj14saw"
3) 1) (integer) 10923
   2) (integer) 16383
   3) 1) "192.168.100.52"
      2) (integer) 6379
      3) "b5sz6s89tdbh5ros1dfa5891dqwaicahq4612a5q"
   4) 1) "192.168.100.53"
      2) (integer) 6379
      3) "ds58qaxfe9s1361qfe9gh49cv9ax2ade6as312ao"