Redis做为缓存的高效中间件,在咱们平常的开发中被频繁的使用,今天就来讲一说Redis的四种模式,分别是「单机版、主从复制、哨兵、以及集群模式」。css
可能,在通常公司的程序员使用单机版基本都能解决问题,在Redis的官网给出的数据是10W QPS,这对于应付通常的公司绰绰有余了,再不行就来个主从模式,实现读写分离,性能又大大提升。html
可是,咱们做为有抱负的程序员,仅限于单机版和主从模式的crud是不行的,至少也要了解「哨兵」和「集群模式」的原理,这样面试的时候才能和面试官扯皮啊。node
以前对于Redis方面也是写了比较多的文章,如:「Redis的基本数据类型和底层的实现原理、事务、持久化、分布式锁、订阅预发布」等,能够说是比较全面的教程了,这篇讲完基本就全了,我会把文章系统的整理成pdf,分享给你们。nginx
单机版的Redis就比较简单了,基本90%的程序员都使用过,官网推荐操做Redis的第三方依赖库是Jedis,在SpringBoot项目中,引入下面依赖就能够直接使用了:程序员
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>${jedis.version}</version>
</dependency>
单机版的Redis也有不少优势,好比实现实现简单、维护简单、部署简单、维护成本很是低,不须要其它额外的开支。面试
可是,由于是单机版的Redis因此也存在不少的问题,好比最明显的单点故障问题,一个Redis挂了,全部的请求就会直接打在了DB上。redis
而且一个Redis抗并发数量也是有限的,同时要兼顾读写两种请求,只要访问量一上来,Redis就受不了了,另外一方面单机版的Redis数据量存储也是有限的,数据量一大,再重启Redis的时候,就会很是的慢,因此局限性也是比较大的。算法
单机版的搭建教程,在网上有很是多的全面的教程,基本就是傻瓜式操做,特别是在本地搭建的话,基本使用yum快捷方便,几句命令就搞定了,这里推荐一个搭建教程:https://www.cnblogs.com/ zuidongfeng/p/8032505.html。数据库
上面这个教程讲的很是的详细,环境的搭建原本是运维的工做,可是做为程序员尝试本身去搭建环境仍是有必要的,并且搭建环境这种东西,基本就是一劳永逸,搭建一次,可能下次换电脑或者重装虚拟机才会再次搭建。c#
这里也放出redis经常使用的redis.conf的配置项,而且附带注释,看我是否是很暖男:
daemonize yes // 设置后台启动,通常设置yes
pidfile /var/run/redis.pid // edis以守护进程方式运行时,redis默认会把pid写入/var/run/redis.pid文件port 6379 // 默认端口为6379
bind 127.0.0.1 //主机地址,设置0.0.0.0表示均可以访问。127.0.0.1表示只容许本机访问
timeout 900 // 客户端闲置多长时间后关闭链接,若是指定为0,表示关闭该功能
logfile stdout // 日志记录方式,默认为标准输出
logfile "./redis7001.log" # 指明日志文件名
databases 16 // 设置数据库的数量,默认数据库为0
save //有多少次更新操做,就将数据同步到数据文件 Redis默认配置文件中提供了三个条件: save 900 1 //900秒(15分钟)内有1个更改
save 300 10 //300秒(5分钟)内有10个更改
save 60 10000 // 60秒内有10000个更改
rdbcompression yes // 指定存储至本地数据库时是否压缩数据dbfilename dump.rdb //指定本地数据库文件名
dir ./ //指定本地数据库存放目录slaveof // 主从同步设置,设置主数据库的ip和端口# 若是非零,则设置SO_KEEPALIVE选项来向空闲链接的客户端发送ACKtcp-keepalive 60
# 默认若是开启RDB快照(至少一条save指令)而且最新的后台保存失败,Redis将会中止接受写操做# 这将使用户知道数据没有正确的持久化到硬盘,不然可能没人注意到而且形成一些灾难stop-writes-on-bgsave-error yes
# 默认若是开启RDB快照(至少一条save指令)而且最新的后台保存失败,Redis将会中止接受写操做。stop-writes-on-bgsave-error yes
# 当导出到 .rdb 数据库时是否用LZF压缩字符串对象rdbcompression yes# 版本5的RDB有一个CRC64算法的校验和放在了文件的最后。这将使文件格式更加可靠。
rdbchecksum yes# 持久化数据库的文件名dbfilename dump-master.rdb
# 工做目录dir /usr/local/redis-4.0.8/redis_master/
# slav服务链接master的密码masterauth testmaster123# 当一个slave失去和master的链接,或者同步正在进行中,slave的行为能够有两种:#1) 若是 slave-serve-stale-data 设置为 "yes" (默认值),slave会继续响应客户端请求,多是正常数据,或者是过期了的数据,也多是还没得到值的空数据。
# 2) 若是 slave-serve-stale-data 设置为 "no",slave会回复"正在从master同步
# (SYNC with master in progress)"来处理各类请求,除了 INFO 和 SLAVEOF 命令。
slave-serve-stale-data yes# 配置是否仅读slave-read-only yes
# 若是你选择“yes”Redis将使用更少的TCP包和带宽来向slaves发送数据。可是这将使数据传输到slave上有延迟,Linux内核的默认配置会达到40毫秒
# 若是你选择了 "no" 数据传输到salve的延迟将会减小但要使用更多的带宽
repl-disable-tcp-nodelay no# slave的优先级,优先级数字小的salve会优先考虑提高为masterslave-priority 100
# 密码验证requirepass testmaster123# redis实例最大占用内存,一旦内存使用达到上限,Redis会根据选定的回收策略(参见:# maxmemmory-policy)删除keymaxmemory 3gb
# 最大内存策略:若是达到内存限制了,Redis如何选择删除key。# volatile-lru -> 根据LRU算法删除带有过时时间的key。# allkeys-lru -> 根据LRU算法删除任何key。# volatile-random -> 根据过时设置来随机删除key, 具有过时时间的key。
# allkeys->random -> 无差异随机删, 任何一个key。
# volatile-ttl -> 根据最近过时时间来删除(辅以TTL), 这是对于有过时时间的key # noeviction -> 谁也不删,直接在写操做时返回错误。maxmemory-policy volatile-lru# AOF开启appendonly no# aof文件名appendfilename "appendonly.aof"
# fsync() 系统调用告诉操做系统把数据写到磁盘上,而不是等更多的数据进入输出缓冲区。# 有些操做系统会真的把数据立刻刷到磁盘上;有些则会尽快去尝试这么作。# Redis支持三种不一样的模式:# no:不要马上刷,只有在操做系统须要刷的时候再刷。比较快。# always:每次写操做都马上写入到aof文件。慢,可是最安全。# everysec:每秒写一次。折中方案。 appendfsync everysec# 若是AOF的同步策略设置成 "always" 或者 "everysec",而且后台的存储进程(后台存储或写入AOF
# 日志)会产生不少磁盘I/O开销。某些Linux的配置下会使Redis由于 fsync()系统调用而阻塞好久。# 注意,目前对这个状况尚未完美修正,甚至不一样线程的 fsync() 会阻塞咱们同步的write(2)调用。
# 为了缓解这个问题,能够用下面这个选项。它能够在 BGSAVE 或 BGREWRITEAOF 处理时阻止主进程进行fsync()。# 这就意味着若是有子进程在进行保存操做,那么Redis就处于"不可同步"的状态。
# 这其实是说,在最差的状况下可能会丢掉30秒钟的日志数据。(默认Linux设定)
# 若是你有延时问题把这个设置成"yes",不然就保持"no",这是保存持久数据的最安全的方式。
no-appendfsync-on-rewrite yes# 自动重写AOF文件auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
# AOF文件可能在尾部是不完整的(这跟system关闭有问题,尤为是mount ext4文件系统时# 没有加上data=ordered选项。只会发生在os死时,redis本身死不会不完整)。
# 那redis重启时load进内存的时候就有问题了。
# 发生的时候,能够选择redis启动报错,而且通知用户和写日志,或者load尽可能多正常的数据。
# 若是aof-load-truncated是yes,会自动发布一个log给客户端而后load(默认)。
# 若是是no,用户必须手动redis-check-aof修复AOF文件才能够。# 注意,若是在读取的过程当中,发现这个aof是损坏的,服务器也是会退出的,# 这个选项仅仅用于当服务器尝试读取更多的数据但又找不到相应的数据时。aof-load-truncated yes
# Lua 脚本的最大执行时间,毫秒为单位lua-time-limit 5000
# Redis慢查询日志能够记录超过指定时间的查询slowlog-log-slower-than 10000
# 这个长度没有限制。只是要主要会消耗内存。你能够经过 SLOWLOG RESET 来回收内存。slowlog-max-len 128
# 客户端的输出缓冲区的限制,可用于强制断开那些由于某种缘由从服务器读取数据的速度不够快的客户端client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
# 当一个子进程重写AOF文件时,文件每生成32M数据会被同步
aof-rewrite-incremental-fsync yes
因为,单机版的Redis在并发量比较大的时候,而且须要较高性能和可靠性的时候,单机版基本就不适合了,因而就出现了「主从模式」。
主从的原理还算是比较简单的,一主多从,「主数据库(master)能够读也能够写(read/write),从数据库进度(only read)」。
可是,主从模式通常实现「读写分离」,「主数据库仅写(only write)」,减轻主数据库的压力,下面一张图搞懂主从模式的原理:
主从模式原理就是那么简单,那它执行的过程(工做机制)又是怎么样的呢?再来一张图:
当开启主从模式的时候,他的具体工做机制以下:
当slave启动后会向master发送SYNC命令,master节点收到从数据库的命令后经过bgsave保存快照(「RDB持久化」),而且期间的执行的些命令会被缓存起来。
而后master会将保存的快照发送给slave,而且继续缓存期间的写命令。
slave收到主数据库发送过来的快照就会加载到本身的数据库中。
最后master将缓存的命令同步给slave,slave收到命令后执行一遍,这样master与slave数据就保持一致了。
之因此运用主从,是由于主从必定程度上解决了单机版并发量大,致使请求延迟或者redis宕机服务中止的问题。
从数据库分担主数据库的读压力,如果主数据库是只写模式,那么实现读写分离,主数据库就没有了读压力了。
另外一方面解决了单机版单点故障的问题,如果主数据库挂了,那么从数据库能够随时顶上来,综上来讲,主从模式必定程度上提升了系统的可用性和性能,是实现哨兵和集群的基础。
主从同步以异步方式进行同步,期间Redis仍然能够响应客户端提交的查询和更新的请求。
主从模式好是好,他也有本身的缺点,好比数据的一致性问题,假如主数据库写操做完成,那么他的数据会被复制到从数据库,如果尚未即便复制到从数据库,读请求又来了,此时读取的数据就不是最新的数据。
如果从主同步的过程网络出故障了,致使主从同步失败,也会出现问题数据一致性的问题。
主从模式不具有自动容错和恢复的功能,一旦主数据库,从节点晋升为主数据库的过程须要人为操做,维护的成本就会升高,而且主节点的写能力、存储能力都会受到限制。
下面的咱们来实操搭建一下主从模式,主从模式的搭建仍是比较简单的,我这里一台centos 7虚拟机,使用开启redis多实例的方法搭建主从。
redis中开启多实例的方法,首先建立一个文件夹,用于存放redis集群的配置文件:
mkdir redis
而后粘贴复制redis.conf配置文件:
cp /root/redis-4.0.6/redis.conf /root/redis/redis-6379.conf
cp /root/redis-4.0.6/redis.conf /root/redis/redis-6380.conf
cp /root/redis-4.0.6/redis.conf /root/redis/redis-6381.conf
复制三份配置文件,一主两从,6379端口做为主数据库(master),6380、6381做为从数据库(slave)。
首先是配置主数据库的配置文件:vi redis-6379.conf:
bind 0.0.0.0 # 注释掉或配置成0.0.0.0表示任意IP都可访问。
protected-mode no # 关闭保护模式,使用密码访问。port 6379 # 设置端口,6380、6381依次为6380、6381。
timeout 30 # 客户端链接空闲多久后断开链接,单位秒,0表示禁用
daemonize yes # 在后台运行pidfile /var/run/redis_6379.pid # pid进程文件名,6380、6381依次为redis_6380.pid、redis_6381.pid
logfile /root/reids/log/6379.log # 日志文件,6380、6381依次为6380.log、6381.log
save 900 1 # 900s内至少一次写操做则执行bgsave进行RDB持久化
save 300 10
save 60 10000
rdbcompression yes #是否对RDB文件进行压缩,建议设置为no,以(磁盘)空间换(CPU)时间dbfilename dump.rdb # RDB文件名称
dir /root/redis/datas # RDB文件保存路径,AOF文件也保存在这里appendonly yes # 表示使用AOF增量持久化的方式appendfsync everysec # 可选值 always, everysec,no,建议设置为everysecrequirepass 123456 # 设置密码
而后,就是修改从数据库的配置文件,再从数据库的配置文件中加入如下的配置信息:
slaveof 127.0.0.1 6379 # 配置master的ip,port
masterauth 123456 # 配置访问master的密码
slaveof-serve-stale-data no
接下来就是启动三个redis实例,启动的命令,先cd到redis的src目录下,而后执行:
./redis-server /root/redis/6379.conf
./redis-server /root/redis/6380.conf./redis-server /root/redis/6381.conf
经过命令ps -aux | grep redis,查看启动的redis进程:
如上图所示,表示启动成功,下面就开始进入测试阶段。
我这里使用SecureCRT做为redis链接的客户端,同时启动三个SecureCRT,分别链接redis1的三个实例,启动时指定端口以及密码:
./redis-cli -p 6379 -a 123456
启动后,在master(6379),输入:set name 'ldc',在slave中经过get name,能够查看:
数据同步成功,这有几个坑一个是redis.conf中没有设置对bind,会致使非本机的ip被过滤掉,通常配置0.0.0.0就能够了。
另外一个是没有配置密码requirepass 123456,会致使IO一直链接异常,这个是我遇到的坑,后面配置密码后就成功了。
还有,就是查看redis的启动日志能够发现有两个warning,虽然不影响搭建主从同步,看着挺烦人的,可是有些人会遇到,有些人不会遇到。
可是,我这我的比较有强迫症,百度也是有解决方案的,这里就不讲了,交给大家本身解决,这里只是告诉你有这个问题,有些人看都不看日志的,看到启动成功就认为万事大吉了,也不看日志,这习惯并很差。
哨兵模式是主从的升级版,由于主从的出现故障后,不会自动恢复,须要人为干预,这就很蛋疼啊。
在主从的基础上,实现哨兵模式就是为了监控主从的运行情况,对主从的健壮进行监控,就好像哨兵同样,只要有异常就发出警告,对异常情况进行处理。
因此,总的归纳来讲,哨兵模式有如下的优势(功能点):
「监控」:监控master和slave是否正常运行,以及哨兵之间也会相互监控
「自动故障恢复」:当master出现故障的时候,会自动选举一个slave做为master顶上去。
哨兵模式的监控配置信息,是经过配置从数据库的sentinel monitor <master-name> <ip> <redis-port> <quorum> 来指定的,好比:
// mymaster 表示给master数据库定义了一个名字,后面的是master的ip和端口,1表示至少须要一个Sentinel进程赞成才能将master判断为失效,若是不知足这个条件,则自动故障转移(failover)不会执行
sentinel monitor mymaster 127.0.0.1 6379 1
固然还有其它的配置信息,其它配置信息,在环境搭建的时候再说。当哨兵启动后,会与master创建一条链接,用于订阅master的_sentinel_:hello频道。
该频道用于获取监控该master的其它哨兵的信息。而且还会创建一条定时向master发送INFO命令获取master信息的链接。
「当哨兵与master创建链接后,按期会向(10秒一次)master和slave发送INFO命令,如果master被标记为主观下线,频率就会变为1秒一次。」
而且,按期向_sentinel_:hello频道发送本身的信息,以便其它的哨兵可以订阅获取本身的信息,发送的内容包含「哨兵的ip和端口、运行id、配置版本、master名字、master的ip端口还有master的配置版本」等信息。
以及,「按期的向master、slave和其它哨兵发送PING命令(每秒一次),以便检测对象是否存活」,如果对方接收到了PING命令,无端障状况下,会回复PONG命令。
因此,哨兵经过创建这两条链接、经过按期发送INFO、PING命令来实现哨兵与哨兵、哨兵与master之间的通讯。
这里涉及到一些概念须要理解,INFO、PING、PONG等命令,后面还会有MEET、FAIL命令,以及主观下线,固然还会有客观下线,这里主要说一下这几个概念的理解:
INFO:该命令能够获取主从数据库的最新信息,能够实现新结点的发现
PING:该命令被使用最频繁,该命令封装了自身节点和其它节点的状态数据。
PONG:当节点收到MEET和PING,会回复PONG命令,也把本身的状态发送给对方。
MEET:该命令在新结点加入集群的时候,会向老节点发送该命令,表示本身是个新人
FAIL:当节点下线,会向集群中广播该消息。
当哨兵与master相同以后就会按期一直保持联系,如果某一时刻哨兵发送的PING在指定时间内没有收到回复(sentinel down-after-milliseconds master-name milliseconds 配置),那么发送PING命令的哨兵就会认为该master「主观下线」(Subjectively Down)。
由于有多是哨兵与该master之间的网络问题形成的,而不是master自己的缘由,因此哨兵同时会询问其它的哨兵是否也认为该master下线,如果认为该节点下线的哨兵达到必定的数量(「前面的quorum字段配置」),就会认为该节点「客观下线」(Objectively Down)。
如果没有足够数量的sentinel赞成该master下线,则该master客观下线的标识会被移除;如果master从新向哨兵的PING命令回复了客观下线的标识也会被移除。
当master被认为客观下线后,又是怎么进行故障恢复的呢?原来哨兵中首先选举出一个老大哨兵来进行故障恢复,选举老大哨兵的算法叫作「Raft算法」:
发现master下线的哨兵(sentinelA)会向其它的哨兵发送命令进行拉票,要求选择本身为哨兵大佬。
如果目标哨兵没有选择其它的哨兵,就会选择该哨兵(sentinelA)为大佬。
如果选择sentinelA的哨兵超过半数(半数原则),该大佬非sentinelA莫属。
若是有多个哨兵同时竞选,而且可能存在票数一致的状况,就会等待下次的一个随机时间再次发起竞选请求,进行新的一轮投票,直到大佬被选出来。
选出大佬哨兵后,大佬哨兵就会对故障进行自动回复,从slave中选出一名slave做为主数据库,选举的规则以下所示:
全部的slave中slave-priority优先级最高的会被选中。
如果优先级相同,会选择偏移量最大的,由于偏移量记录着数据的复制的增量,越大表示数据越完整。
如果以上二者都相同,选择ID最小的。
经过以上的层层筛选最终实现故障恢复,当选的slave晋升为master,其它的slave会向新的master复制数据,如果down掉的master从新上线,会被看成slave角色运行。
哨兵模式是主从模式的升级版,因此在系统层面提升了系统的可用性和性能、稳定性。当master宕机的时候,可以自动进行故障恢复,需不要人为的干预。
哨兵与哨兵之间、哨兵与master之间可以进行及时的监控,心跳检测,及时发现系统的问题,这都是弥补了主从的缺点。
哨兵一主多从的模式一样也会遇到写的瓶颈,已经存储瓶颈,如果master宕机了,故障恢复的时间比较长,写的业务就会受到影响。
增长了哨兵也增长了系统的复杂度,须要同时维护哨兵模式。
最后,咱们进行一下哨兵模式的搭建,配置哨兵模式仍是比较简单的,在上面配置的主从模式的基础上,同时建立一个文件夹用于存放三个哨兵的配置文件:
mkdir /root/redis-4.0.6/sentinel.conf /root/redis/sentinel/sentinel1.conf
mkdir /root/redis-4.0.6/sentinel.conf /root/redis/sentinel/sentinel2.conf
mkdir /root/redis-4.0.6/sentinel.conf /root/redis/sentinel/sentinel3.conf
分别在这三个文件中添加以下配置:
daemonize yes # 在后台运行
sentinel monitor mymaster 127.0.0.1 6379 1 # 给master起一个名字mymaster,而且配置master的ip和端口
sentinel auth-pass mymaster 123456 # master的密码
port 26379 #另外两个配置36379,46379端口
sentinel down-after-milliseconds mymaster 3000 # 3s未回复PING就认为master主观下线
sentinel parallel-syncs mymaster 2 # 执行故障转移时,最多能够有2个slave实例在同步新的master实例
sentinel failover-timeout mymaster 100000 # 若是在10s内未能完成故障转移操做认为故障转移失败
配置完后分别启动三台哨兵:
./redis-server sentinel1.conf --sentinel
./redis-server sentinel2.conf --sentinel
./redis-server sentinel3.conf --sentinel
而后经过:ps -aux|grep redis进行查看:
能够看到三台redis实例以及三个哨兵都已经正常启动,现登录6379,经过INFO Repliaction查看master信息:
当前master为6379,而后咱们来测试一下哨兵的自动故障恢复,直接kill掉6379进程,而后经过登录6380再次查看master的信息:
能够看到当前的6380角色是master,而且6380可读可写,而不是只读模式,这说明咱们的哨兵是起做用了,搭建成功,感兴趣的能够自行搭建,也有可能你会踩一堆的坑。
最后,Cluster是真正的集群模式了,哨兵解决和主从不能自动故障恢复的问题,可是同时也存在难以扩容以及单机存储、读写能力受限的问题,而且集群以前都是一台redis都是全量的数据,这样全部的redis都冗余一份,就会大大消耗内存空间。
集群模式实现了Redis数据的分布式存储,实现数据的分片,每一个redis节点存储不一样的内容,而且解决了在线的节点收缩(下线)和扩容(上线)问题。
集群模式真正意义上实现了系统的高可用和高性能,可是集群同时进一步使系统变得愈来愈复杂,接下来咱们来详细的了解集群的运做原理。
集群的原理图仍是很好理解的,在Redis集群中采用的是虚拟槽分区算法,会把redis集群分红16384 个槽(0 -16383)。
好比:下图所示三个master,会把0 -16383范围的槽可能分红三部分(0-5000)、(5001-11000)、(11001-16383)分别数据三个缓存节点的槽范围。
当客户端请求过来,会首先经过对key进行CRC16 校验并对 16384 取模(CRC16(key)%16383)计算出key所在的槽,而后再到对应的槽上进行取数据或者存数据,这样就实现了数据的访问更新。
之因此进行分槽存储,是将一整堆的数据进行分片,防止单台的redis数据量过大,影响性能的问题。
节点之间实现了将数据进行分片存储,那么节点之间又是怎么通讯的呢?这个和前面哨兵模式讲的命令基本同样。
首先新上线的节点,会经过 Gossip 协议向老成员发送Meet消息,表示本身是新加入的成员。
老成员收到Meet消息后,在没有故障的状况下会恢复PONG消息,表示欢迎新结点的加入,除了第一次发送Meet消息后,以后都会发送按期PING消息,实现节点之间的通讯。
通讯的过程当中会为每个通讯的节点开通一条tcp通道,以后就是定时任务,不断的向其它节点发送PING消息,这样作的目的就是为了了解节点之间的元数据存储状况,以及健康情况,以便即便发现问题。
上面说到了槽信息,在Redis的底层维护了unsigned char myslots[CLUSTER_SLOTS/8] 一个数组存放每一个节点的槽信息。
由于他是一个二进制数组,只有存储0和1值,以下图所示:
这样数组只表示本身是否存储对应的槽数据,如果1表示存在该数据,0表示不存在该数据,这样查询的效率就会很是的高,相似于布隆过滤器,二进制存储。
好比:集群节点1负责存储0-5000的槽数据,可是此时只有0、一、2存储有数据,其它的槽尚未存数据,因此0、一、2对应的值为1。
而且,每一个redis底层还维护了一个clusterNode数组,大小也是16384,用于储存负责对应槽的节点的ip、端口等信息,这样每个节点就维护了其它节点的元数据信息,便于及时的找到对应的节点。
当新结点加入或者节点收缩,经过PING命令通讯,及时的更新本身clusterNode数组中的元数据信息,这样有请求过来也就能及时的找到对应的节点。
有两种其它的状况就是,如果请求过来发现,数据发生了迁移,好比新节点加入,会使旧的缓存节点数据迁移到新结点。
请求过来发现旧节点已经发生了数据迁移而且数据被迁移到新结点,因为每一个节点都有clusterNode信息,经过该信息的ip和端口。此时旧节点就会向客户端发一个MOVED 的重定向请求,表示数据已经迁移到新结点上,你要访问这个新结点的ip和端口就能拿到数据,这样就能从新获取到数据。
假若正在发生数据迁移呢?旧节点就会向客户端发送一个ASK 重定向请求,并返回给客户端迁移的目标节点的ip和端口,这样也能获取到数据。
扩容和收缩也就是节点的上线和下线,可能节点发生故障了,故障自动恢复的过程(节点收缩)。
节点的收缩和扩容时,会从新计算每个节点负责的槽范围,并发根据虚拟槽算法,将对应的数据更新到对应的节点。
还有前面的讲的新加入的节点会首先发送Meet消息,详细能够查看前面讲的内容,基本同样的模式。
以及发生故障后,哨兵老大节点的选举,master节点的从新选举,slave怎样晋升为master节点,能够查看前面哨兵模式选举过程。
集群模式是一个无中心的架构模式,将数据进行分片,分布到对应的槽中,每一个节点存储不一样的数据内容,经过路由可以找到对应的节点负责存储的槽,可以实现高效率的查询。
而且集群模式增长了横向和纵向的扩展能力,实现节点加入和收缩,集群模式是哨兵的升级版,哨兵的优势集群都有。
缓存的最大问题就是带来数据一致性问题,在平衡数据一致性的问题时,兼顾性能与业务要求,大多数都是以最终一致性的方案进行解决,而不是强一致性。
而且集群模式带来节点数量的剧增,一个集群模式最少要6台机,由于要知足半数原则的选举方式,因此也带来了架构的复杂性。
slave只充当冷备,并不能缓解master的读的压力。
集群模式的部署比较简单,只要在redis.conf加入下面的配置信息便可:
port 6379# 本示例6个节点端口分别为637九、6380、638一、638二、638三、6384
daemonize yes # r后台运行
pidfile /var/run/redis_6379.pid # 分别对应637九、6380、638一、638二、638三、6384
cluster-enabled yes # 开启集群模式
masterauth 123456# 若是设置了密码,须要指定master密码
cluster-config-file nodes_6379.conf # 集群的配置文件,一样对应637九、6380、638一、638二、638三、6384六个节点
cluster-node-timeout 10000 # 请求超时时间
同时开启这六个实例,经过下面的命令将这六个实例以集群的方式运行
./redis-cli --cluster create --cluster-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 -a 123456
这样就实现了集群的搭建