Redis学习 - 复制以及三种部署模式
什么是复制
单机的redis通常状况是无奈满足我的项目需要的,个别都倡议应用集群部署的形式进行数据的多机备份和部署,这样既能够保障数据安全,同时在redis宕机的时候,复制也能够对于数据进行疾速的修复。
<!-- more -->
采取的形式
- 单机部署(疏忽)
- 主从链
- 一主多从
- 哨兵模式
- 集群模式
复制的前提
- 须要保障
redis.conf
外面的配置是正确的,比方:
dir ./dbfilename "dump.rdb"
- 须要保障指定的门路对于redis来说是可写的,意味着如果当前目录没有写权限同样会失败
从服务器连贯主服务器的几种形式
- 在从服务器的配置文件外面配置连贯那个主服务器:
连贯的具体配置如下:
在5.0版本中应用了replicaof
代替了slaveof
(github.com/antirez/red…),slaveof
还能够持续应用,不过倡议应用replicaof
上面是集体的配置
# replicaof <masterip> <masterport> replicaof 127.0.0.1 16379
正告:此大节只阐明了这一个配置的更改,进行主从配置的时候还有其余几个参数须要更改,这里只作为局部内容参考
- 在启动的适宜,在redis从服务器的redis-cli当中敲击如下的命令:
127.0.0.1:16380> slaveof 127.0.0.1 16379OK Already connected to specified master
这样就能够在从服务器动静的指定要连贯哪个主服务器了,然而这种配置是以后运行时无效,下次再次进入的时候,会依据配置文件进行配置或者依照默认的规定以后实例就是master3.
- 在从服务器执行
slaveof no one
,以后实例脱离管制主动成为master
redis 复制启动的过程==(重点)==
主服务器操作 | 从服务器操作 |
---|---|
1. (期待命令) | 1. 连贯(从新连贯)主服务器,发送sync命令 |
2. 开始执行bgsave,应用缓冲区记录bgsave之后执行所有写命令 | 2. 依据配置选项是应用现有的数据(存在)解决客户端申请,还是向申请的客户端返回错误信息 |
3. bgsave执行结束,向从服务器发送快照文件,同时异步执行缓冲区记录的写命令 | 3. 抛弃所有的旧数据,载入主服务器的快照文件 |
4. 快照文件发送结束,开始向着从服务器发送存储在缓冲区的写命令 | 4. 实现对于快照的解释操作,复原日常的申请操作 |
5. 缓冲区写命令发送实现,同时当初每执行一个写命令就像从服务器发送雷同写命令 | 5. 执行主服务器发来的所有存储在缓冲区的写命令,并且从当初开始承受主服务器的每一个命令 |
倡议:因为bgsave须要开启进行子线程的创立写入缓冲区的创立,所以最好在零碎中预留30% - 45% 内存用于redis的bgsave操作特地留神:当从服务器连贯主服务器的那一刻,执行到第三步会清空以后redis外面的所有数据。
配置形式和命令形式的区别:
redis.conf 配置slaveof 的形式:不会马上进行主服务器同步,而是先载入以后本地存在的rdb或者aof到redis中进行数据恢复,而后才开始同步复制
命令slaveof形式:会立刻连贯主服务器进行同步操作
对于redis的主主复制:
如果咱们尝试让两台服务器相互slaveof 那么会呈现下面状况呢?
从下面的复制过程能够看到,当一个服务器slaveof另一个服务器,产生的后果只会是两边互相笼罩,也就是从服务器会去同步主服务器的数据,如果此时依照主主的配置,两边相互同步对方的数据,这样产生的数据可能会不统一,或者数据罗唆就是不残缺的。不仅如此,这种操作还会大量占用资源区让两台服务器相互晓得对方
当一台服务器连贯另一台服务器的时候会产生什么?
当有新服务器连贯的时候 | 主服务器操作 |
---|---|
步骤3还没有执行 | 所有从服务器都会收到雷同的快照文件和雷同缓冲区写命令 |
步骤3正在执行或者曾经执行 | 实现了之前同步的五个操作之后,会跟新服务器从新执行一次新的五个步骤 |
系统故障解决
复制和长久化尽管曾经根本能够保证系统的数据安全,然而总有意外的状况,比方忽然断电断网,零碎磁盘故障,服务器宕机等一系列状况,那么会呈现各种莫名微妙的问题,上面针对这些状况阐明一下解决形式:
验证快照文件以及aof文件
在redis的bin
目录上面,存在如下的两个sh
-rwxr-xr-x 1 root root 9722168 Nov 15 20:53 redis-check-aof-rwxr-xr-x 1 root root 9722168 Nov 15 20:53 redis-check-rdb
他们的命令作用和内容如下:
[xd@iZwz99gyct1a1rh6iblyucZ bin]$ ./redis-check-aof Usage: ./redis-check-aof [--fix] <file.aof>[xd@iZwz99gyct1a1rh6iblyucZ bin]$ ./redis-check-rdb Usage: ./redis-check-rdb <rdb-file-name>
redis-check-aof:如果退出--fix
选项,那么命令会尝试修复aof文件,会将内容外面呈现谬误的命令以及上面的所有命令清空,个别状况下回清空尾部的一些未实现命令。
redis-check-rdb:遗憾的是目前这种修复收效甚微。倡议在修复rdb的时候,用SHA1和SHA256验证文件是否残缺。
校验和与散列值:
redis2.6 之后退出了校验和与散列值进行验证。
快照文件减少CRC64校验和
什么是crc循环冗余校验?https://zh.wikipedia.org/wiki...
更换故障主服务器:
- 假如A故障,存在BC两台机器,B为从服务,C为将要替换的主服务器
- 向机器B发送save命令,同时创立一个新的快照文件,同步实现之后,发送给C
- 机器C下面启动redis,让C成为B的主服务器
Redis sentienel 哨兵
能够监督指定主服务器以及属下的从服务器
也就是咱们罕用的哨兵模式
然而随着时代提高,目前应用redis根本还是以cluster模式
为主
redis主从复制模式(redis6.0版本):
前提阐明:
有条件的能够弄三台虚拟机查看成果,这样模仿进去的成果算是比拟实在的。
三台从服务器以及一台主服务器的配置
集体的方法是copy一个专用的配置,而后进行批改(这里只列举区别以及改变较多的中央,其余中央依据须要配置):
第一台机器的配置:
pidfile /var/run/redis_16379.pidport 16379dbfilename dump16379.rdbappendfilename "appendonly16379.aof"logfile "log16379"
第二台机器的配置:
pidfile /var/run/redis_16380.pidport 16380dbfilename dump16380.rdbappendfilename "appendonly16380.aof"logfile "log16380"
第三台机器的配置:
pidfile /var/run/redis_16381.pidport 16381dbfilename dump16381.rdbappendfilename "appendonly16381.aof"logfile "log16381"
这时候要配置一台主服务器
pidfile /var/run/redis_10000.pidport 10000dbfilename dump10000.rdbappendfilename "appendonly10000.aof"logfile "log10000"
启动redis一主多从:
配置很简略,能够用手动进行主从复制,也能够应用redis.conf提前配置,具体区别上文曾经进行过介绍,这里不再赘述。
从服务器能够通过命令:slaveof 127.0.0.1 10000
实现主从复制拷贝
能够通过命令info replication
查看主从配置的信息。
主服务器启动日志:
127.0.0.1:10000> info replication# Replicationrole:masterconnected_slaves:0master_replid:e2a92d8c59fbdde3b162da12f4d74ff28bab4fbbmaster_replid2:0000000000000000000000000000000000000000master_repl_offset:0second_repl_offset:-1repl_backlog_active:0repl_backlog_size:1048576repl_backlog_first_byte_offset:0repl_backlog_histlen:0127.0.0.1:10000> info replication# Replicationrole:masterconnected_slaves:3slave0:ip=127.0.0.1,port=16381,state=online,offset=14,lag=1slave1:ip=127.0.0.1,port=16380,state=online,offset=14,lag=1slave2:ip=127.0.0.1,port=16379,state=online,offset=14,lag=1master_replid:029e455ee6f8fdc0e255b6d5c4f63136d933fb24master_replid2:0000000000000000000000000000000000000000master_repl_offset:14second_repl_offset:-1repl_backlog_active:1repl_backlog_size:1048576repl_backlog_first_byte_offset:1repl_backlog_histlen:14
能够看到进行主从配置之后,以后的目录上面多出了对应备份文件
当进行主从配置之后,从服务就无奈进行写入了,主服务器才能够写入:
127.0.0.1:16379> set key 1(error) READONLY You can't write against a read only replica.
测试一主多从复制:
主服务器敲入如下命令:
127.0.0.1:10000> hset key1 name1 value1(integer) 1127.0.0.1:10000> keys *1) "key1"
从服务器:
127.0.0.1:16379> hget key1 name1"value1"127.0.0.1:16380> hget key1 name1"value1"127.0.0.1:16381> hget key1 name1"value1"
主从链
配置形式:
和主从配置一样,只不过主节点换为从节点。
留神:主从链的配置仍然只能是master节点能够写数据,同时两头的节点也是slave
扩大
如何检测磁盘是否写入数据?
- 主从服务器通过一个虚标值(unique dummy value)来验证从服务器是否真的把数据写入到本人的磁盘。
- 通过命令:
info
查看后果当中的aof_appending_bio_fsync
的值是否为0:
\# 5.0 版本之后改为如下模式验证repl_backlog_active:0
redis主从哨兵模式(Redis sentienel)(redis6.0版本)
哨兵模式有什么作用:
Redis的哨兵模式就是对redis零碎进行实时的监控,其次要性能有上面两点
1.监测主数据库和从数据库是否失常运行。
2.当咱们的主数据库呈现故障的时候,能够主动将从数据库转换为主数据库,实现主动的切换。
为什么要应用哨兵模式:
- 主从复制在主节点宕机的状况下,须要人工干预复原redis,无奈实现高可用。
- 主节点宕机的状况下须要备份数据到新的从节点,而后其余节点将主节点设置为新的redis,须要一次全量复制同步数据的过程
哨兵模式原理
主节点故障的时候,由redis sentinel主动实现故障发现和转移
如何部署哨兵模式:
- 首先依照上一节配置,曾经设置了一个主节点三个从节点的配置
上面的配置如下:主节点:10000
从节点1:16379
从节点2:16380
从节点3:16381
[xd@iZwz99gyct1a1rh6iblyucZ ~]$ ps -ef | grep redisxd 2964 2910 0 18:02 pts/0 00:00:00 grep --color=auto redisroot 26412 1 0 Nov23 ? 00:06:07 ./redis-server 127.0.0.1:10000root 26421 1 0 Nov23 ? 00:05:37 ./redis-server 127.0.0.1:16379root 26428 1 0 Nov23 ? 00:05:37 ./redis-server 127.0.0.1:16380root 26435 1 0 Nov23 ? 00:05:37 ./redis-server 127.0.0.1:16381
sentinel.conf
配置文件在装置redis的源码包外面有,所以如果误删了能够下回来而后把文件弄到手,其实能够配置一个罕用的或者通用的配置放到本人的本地有须要间接替换- 配置5个sentienl.conf文件(倡议奇数个哨兵,不便宕机选举产生新的节点)
[xd@iZwz99gyct1a1rh6iblyucZ bin]$ sudo cp sentinel.conf sentinel_26379.conf[xd@iZwz99gyct1a1rh6iblyucZ bin]$ sudo cp sentinel.conf sentinel_26380.conf[xd@iZwz99gyct1a1rh6iblyucZ bin]$ sudo cp sentinel.conf sentinel_26381.conf[xd@iZwz99gyct1a1rh6iblyucZ bin]$ sudo cp sentinel.conf sentinel_10000.conf
- 四个配置文件的改变顺次如下:
所有的sentinel.conf
配置如下:
# 指定哨兵端口port 20000# 监听主节点10000sentinel monitor mymaster 127.0.0.1 10000 2# 连贯主节点时的明码,如果redis配置了明码须要填写sentinel auth-pass mymaster 12345678# 故障转移时最多能够有2从节点同时对新主节点进行数据同步sentinel config-epoch mymaster 2# 故障转移超时工夫180s,sentinel failover-timeout mymasterA 180000 # sentinel节点定期向主节点ping命令,当超过了300S工夫后没有回复,可能就认定为此主节点呈现故障了……sentinel down-after-milliseconds mymasterA 300000# 故障转移后,1代表每个从节点按程序排队一个一个复制主节点数据,如果为3,指3个从节点同时并发复制主节点数据,不会影响阻塞,但存在网络和IO开销sentinel parallel-syncs mymasterA 1# 设置后盾启动daemonize yes# 过程的pid文件,保险起见设置不一样的,特地是设置后盾启动的时候pidfile /var/run/redis-sentinel.pid
扩大:如何断定转移失败:a - 如果转移超时失败,下次转移时工夫为之前的2倍;
b - 从节点变主节点时,从节点执行slaveof no one命令始终失败的话,当工夫超过180S时,则故障转移失败
c - 从节点复制新主节点工夫超过180S转移失败
上面为配好五个之后的配置:
-rw-r--r-- 1 root root 10772 Nov 28 21:00 sentienl_26382.conf-rw-r--r-- 1 root root 10767 Nov 28 20:43 sentinel_10000.conf-rw-r--r-- 1 root root 10772 Nov 28 21:03 sentinel_26379.conf-rw-r--r-- 1 root root 10766 Nov 28 20:46 sentinel_26380.conf-rw-r--r-- 1 root root 10772 Nov 28 20:59 sentinel_26381.conf-rw-r--r-- 1 root root 10772 Nov 28 21:03 sentinel_26382.conf-rw-r--r-- 1 root root 10744 Nov 28 18:06 sentinel.conf
- 上一节曾经启动过,这里不再介绍
- 启动sentinel服务
启动五个哨兵:
./redis-sentinel ./sentinel_10000.conf ./redis-sentinel ./sentinel_26379.conf ./redis-sentinel ./sentinel_263780.conf ./redis-sentinel ./sentinel_263781.conf ./redis-sentinel ./sentinel_263782.conf
应用ps
命令查看所有的服务:
root 3267 1 0 21:14 ? 00:00:01 ./redis-sentinel *:20000 [sentinel]root 3280 1 0 21:15 ? 00:00:01 ./redis-sentinel *:26379 [sentinel]root 3296 1 0 21:20 ? 00:00:00 ./redis-sentinel *:26380 [sentinel]root 3303 1 0 21:21 ? 00:00:00 ./redis-sentinel *:26381 [sentinel]root 3316 3254 0 21:28 pts/0 00:00:00 grep --color=auto redisroot 26412 1 0 Nov23 ? 00:06:17 ./redis-server 127.0.0.1:10000root 26421 1 0 Nov23 ? 00:05:47 ./redis-server 127.0.0.1:16379root 26428 1 0 Nov23 ? 00:05:47 ./redis-server 127.0.0.1:16380root 26435 1 0 Nov23 ? 00:05:47 ./redis-server 127.0.0.1:16381
- 验证一下哨兵是否管用
10000是主节点,他的info
信息如下:
# Keyspacedb0:keys=1,expires=0,avg_ttl=0127.0.0.1:10000> info replication# Replicationrole:masterconnected_slaves:3
应用kill -9 master节点过程端口号
之后,咱们曾经干掉了额主过程,验证一下从节点是否启动
进入到6379端口的redis-cli
当中,能够看到从节点6379的实例被选举为新的的节点
127.0.0.1:16379> info replication# Replicationrole:masterconnected_slaves:2slave0:ip=127.0.0.1,port=16380,state=online,offset=857706,lag=1slave1:ip=127.0.0.1,port=16381,state=online,offset=858242,lag=1
挂掉的主节点复原之后,能不能进行复原为主节点?
尝试重启挂掉的master之后,能够发现他变成了从节点
127.0.0.1:10000> info replication# Replicationrole:slavemaster_host:127.0.0.1master_port:16379master_link_status:upmaster_last_io_seconds_ago:2
留神:生产环境倡议让redis Sentinel部署到不同的物理机上
如果不喜爱下面的启动哨兵模式,也能够应用上面的命令开启:
[root@dev-server-1 sentinel]# redis-server sentinel1.conf --sentinel[root@dev-server-1 sentinel]# redis-server sentinel2.conf --sentinel[root@dev-server-1 sentinel]# redis-server sentinel3.conf --sentinel
哨兵模式部署倡议
a,sentinel节点应部署在多台物理机(线上环境)
b,至多三个且奇数个sentinel节点
c,通过以上咱们晓得,3个sentinel可同时监控一个主节点或多个主节点
监听N个主节点较多时,如果sentinel出现异常,会对多个主节点有影响,同时还会造成sentinel节点产生过多的网络连接,
个别线上倡议还是, 3个sentinel监听一个主节点
也能够依照上面的形式在启动哨兵的时候启动:
哨兵模式的优缺点:
长处:
- 哨兵模式基于主从复制模式,所以主从复制模式有的长处,哨兵模式也有
- 哨兵模式下,master挂掉能够主动进行切换,零碎可用性更高
毛病:
- 同样也继承了主从模式难以在线扩容的毛病,Redis的容量受限于单机配置
- 须要额定的资源来启动sentinel过程,实现绝对简单一点,同时slave节点作为备份节点不提供服务
redis集群模式(redis6.0版本)
随着利用的扩大,尽管主从模式和哨兵模式的退出解决了高可用的问题,然而古代的利用根本都是要求能够动静扩大了,为了反对动静扩大,redis在后续的版本当中退出了哨兵的模式
集群模式次要解决的问题是:
Cluster模式实现了Redis的分布式存储,即每台节点存储不同的内容,来解决在线扩容的问题
redis结构设计:
应用的是无核心的构造,每一个节点和节点之间相互连接
- redis 应用彼此互联的(ping-pong)的形式,进行相互关联,外部应用二进制协定优化速度
- 客户端与redis节点直连,不须要两头代理层.客户端不须要连贯集群所有节点,连贯集群中任何一个可用节点即可
- 节点的fail是通过集群中超过半数的节点检测生效时才失效
redis集群的工作机制
- 在Redis的每个节点上,都有一个插槽(slot),取值范畴为0-16383,redis会依据接节点的数量调配槽的地位来进行断定发送给哪一个cluster节点
- 当咱们存取key的时候,Redis会依据CRC16的算法得出一个后果,而后把后果对16384求余数,这样每个key都会对应一个编号在0-16383之间的哈希槽,通过这个值,去找到对应的插槽所对应的节点,而后间接主动跳转到这个对应的节点上进行存取操作
- 为了保障高可用,Cluster模式也引入主从复制模式,一个主节点对应一个或者多个从节点,当主节点宕机的时候,就会启用从节点
- 当其它主节点ping一个主节点A时,如果半数以上的主节点与A通信超时,那么认为主节点A宕机了。如果主节点A和它的从节点都宕机了,那么该集群就无奈再提供服务了
配置集群(重点):
为了不产生烦扰,先把上一节所有的redis过程干掉,包含哨兵的配置
应用kil -9 过程端口号
间接抹掉整个利用
配置如下:
- 集群至多须要三主三从,同时须要奇数的节点配置。
- 咱们能够将之前的主从配置的一主三从减少两个主节点,目前的配置如下:
-rw-r--r-- 1 root root 84993 Nov 28 21:41 redis10000.conf-rw-r--r-- 1 root root 84936 Nov 28 21:35 redis16379.conf-rw-r--r-- 1 root root 84962 Nov 28 21:35 redis16380.conf-rw-r--r-- 1 root root 84962 Nov 28 21:35 redis16381.conf# 减少两个次要节点-rw-r--r-- 1 root root 84962 Nov 28 21:35 redis16382.conf-rw-r--r-- 1 root root 84962 Nov 28 21:35 redis16383.conf
主节点的配置次要如下:
port 7100 # 本示例6个节点端口别离为7100,7200,7300,7400,7500,7600 daemonize yes # r后盾运行 pidfile /var/run/redis_7100.pid # pidfile文件对应7100,7200,7300,7400,7500,7600 cluster-enabled yes # 开启集群模式 masterauth passw0rd # 如果设置了明码,须要指定master明码cluster-config-file nodes_7100.conf # 集群的配置文件,同样对应7100,7200等六个节点cluster-node-timeout 15000 # 申请超时 默认15秒,可自行设置
启动如下:
[root@iZwz99gyct1a1rh6iblyucZ bin]# ./redis-server ./cluster/redis17000_cluster.conf[root@iZwz99gyct1a1rh6iblyucZ bin]# ./redis-server ./cluster/redis17100_cluster.conf[root@iZwz99gyct1a1rh6iblyucZ bin]# ./redis-server ./cluster/redis17200_cluster.conf[root@iZwz99gyct1a1rh6iblyucZ bin]# ./redis-server ./cluster/redis17300_cluster.conf[root@iZwz99gyct1a1rh6iblyucZ bin]# ./redis-server ./cluster/redis17400_cluster.conf[root@iZwz99gyct1a1rh6iblyucZ bin]# ./redis-server ./cluster/redis17500_cluster.conf[root@iZwz99gyct1a1rh6iblyucZ bin]# ps -ef | grep redisroot 4761 1 0 15:55 ? 00:00:00 ./redis-server 127.0.0.1:17000 [cluster]root 4767 1 0 15:55 ? 00:00:00 ./redis-server 127.0.0.1:17100 [cluster]root 4773 1 0 15:55 ? 00:00:00 ./redis-server 127.0.0.1:17200 [cluster]root 4779 1 0 15:55 ? 00:00:00 ./redis-server 127.0.0.1:17300 [cluster]root 4785 1 0 15:55 ? 00:00:00 ./redis-server 127.0.0.1:17400 [cluster]root 4791 1 0 15:55 ? 00:00:00 ./redis-server 127.0.0.1:17500 [cluster]root 4797 4669 0 15:55 pts/0 00:00:00 grep --color=auto redis
启动了下面六个节点之后,应用上面的命令并且敲入yes
让他们变为集群:
[root@iZwz99gyct1a1rh6iblyucZ bin]# ./redis-cli --cluster create 127.0.0.1:17000 127.0.0.1:17100 127.0.0.1:17200 127.0.0.1:17300 127.0.0.1:17400 127.0.0.1:17500 --cluster-replicas 1>>> Performing hash slots allocation on 6 nodes...Master[0] -> Slots 0 - 5460Master[1] -> Slots 5461 - 10922Master[2] -> Slots 10923 - 16383Adding replica 127.0.0.1:17400 to 127.0.0.1:17000Adding replica 127.0.0.1:17500 to 127.0.0.1:17100Adding replica 127.0.0.1:17300 to 127.0.0.1:17200>>> Trying to optimize slaves allocation for anti-affinity[WARNING] Some slaves are in the same host as their masterM: 1179bb5f47e7f8221ba7917b5852f8064778e0db 127.0.0.1:17000 slots:[0-5460] (5461 slots) masterM: 153afa1b9b14194de441fffa791f8d9001badc66 127.0.0.1:17100 slots:[5461-10922] (5462 slots) masterM: 4029aeeb6b80e843279738d6d35eee7a1adcd2ff 127.0.0.1:17200 slots:[10923-16383] (5461 slots) masterS: 3ceb11fe492f98432f124fd1dcb7b2bb1e769a96 127.0.0.1:17300 replicates 1179bb5f47e7f8221ba7917b5852f8064778e0dbS: 66eaea82ccf69ef96dbc16aac39fd6f6ed3d0691 127.0.0.1:17400 replicates 153afa1b9b14194de441fffa791f8d9001badc66S: c34aeb59c8bedc11b4aeb720b70b0019e7389093 127.0.0.1:17500 replicates 4029aeeb6b80e843279738d6d35eee7a1adcd2ff
验证集群:
- 输出
redis-cli
进入任意的一个主节点,留神是主节点,从节点不能做写入操作
Redirected to slot [9189] located at 127.0.0.1:17100
依据Hash的算法,算出连贯那个节点槽,而后提醒slot[9189] 落到了17100下面,所以集群会主动跳转进行Key的退出
[root@iZwz99gyct1a1rh6iblyucZ bin]# ./redis-cli -p 17000127.0.0.1:17000> set key1 1[root@iZwz99gyct1a1rh6iblyucZ bin]# ./redis-cli -p 17000127.0.0.1:17000> set key1 1(error) MOVED 9189 127.0.0.1:17100[root@iZwz99gyct1a1rh6iblyucZ bin]# ./redis-cli -p 17000 -c127.0.0.1:17000> set key1 ke-> Redirected to slot [9189] located at 127.0.0.1:17100OK
小贴士:集群之后不能应用传统的连贯形式,因为每一个key都要通过一次hash的操作找到对应的槽 -》节点之后能力做后续的操作应用如下命令进入后失常
./redis-cli -p 17000 -c
-c 代表以集群的形式连贯
- 能够应用如下命令验证集群的信息:
127.0.0.1:17000> cluster nodes66eaea82ccf69ef96dbc16aac39fd6f6ed3d0691 127.0.0.1:17400@27400 slave 153afa1b9b14194de441fffa791f8d9001badc66 0 1606639411000 2 connected4029aeeb6b80e843279738d6d35eee7a1adcd2ff 127.0.0.1:17200@27200 master - 0 1606639411000 3 connected 10923-163833ceb11fe492f98432f124fd1dcb7b2bb1e769a96 127.0.0.1:17300@27300 slave 1179bb5f47e7f8221ba7917b5852f8064778e0db 0 1606639410000 1 connected1179bb5f47e7f8221ba7917b5852f8064778e0db 127.0.0.1:17000@27000 myself,master - 0 1606639410000 1 connected 0-5460153afa1b9b14194de441fffa791f8d9001badc66 127.0.0.1:17100@27100 master - 0 1606639412002 2 connected 5461-10922c34aeb59c8bedc11b4aeb720b70b0019e7389093 127.0.0.1:17500@27500 slave 4029aeeb6b80e843279738d6d35eee7a1adcd2ff 0 1606639413005 3 connected
- 接下来咱们验证一下当一个主节点挂掉会产生什么状况:
还是和主从复制的验证一样,间接Kill 过程:
kill掉 17000 之后,咱们能够发现 17300 被降级为主节点
127.0.0.1:17300> info replication# Replicationrole:masterconnected_slaves:0
此时的节点状况如下:
127.0.0.1:17100> cluster nodes4029aeeb6b80e843279738d6d35eee7a1adcd2ff 127.0.0.1:17200@27200 master - 0 1606640582000 3 connected 10923-16383153afa1b9b14194de441fffa791f8d9001badc66 127.0.0.1:17100@27100 myself,master - 0 1606640581000 2 connected 5461-1092266eaea82ccf69ef96dbc16aac39fd6f6ed3d0691 127.0.0.1:17400@27400 slave 153afa1b9b14194de441fffa791f8d9001badc66 0 1606640581000 2 connectedc34aeb59c8bedc11b4aeb720b70b0019e7389093 127.0.0.1:17500@27500 slave 4029aeeb6b80e843279738d6d35eee7a1adcd2ff 0 1606640582624 3 connected3ceb11fe492f98432f124fd1dcb7b2bb1e769a96 127.0.0.1:17300@27300 master - 0 1606640580619 7 connected 0-54601179bb5f47e7f8221ba7917b5852f8064778e0db 127.0.0.1:17000@27000 master,fail - 1606640370074 1606640367068 1 disconnected
- 如果这时候主节点复原呢?
和哨兵的模式一样,复原之后也变为slave
了。
集群模式优缺点:
长处:
- 无核心架构,数据依照slot散布在多个节点。
- 集群中的每个节点都是平等的关系,每个节点都保留各自的数据和整个集群的状态。每个节点都和其余所有节点连贯,而且这些连贯放弃沉闷,这样就保障了咱们只须要连贯集群中的任意一个节点,就能够获取到其余节点的数据。
- 可线性扩大到1000多个节点,节点可动静增加或删除
- 可能实现主动故障转移,节点之间通过gossip协定替换状态信息,用投票机制实现slave到master的角色转换
毛病:
- 客户端实现简单,驱动要求实现Smart Client,缓存slots mapping信息并及时更新,进步了开发难度。目前仅JedisCluster绝对成熟,异样解决还不欠缺,比方常见的“max redirect exception”
- 节点会因为某些起因产生阻塞(阻塞工夫大于 cluster-node-timeout)被判断下线,这种failover是没有必要的
- 数据通过异步复制,不保证数据的强一致性
- slave充当“冷备”,不能缓解读压力
- 批量操作限度,目前只反对具备雷同slot值的key执行批量操作,对mset、mget、sunion等操作反对不敌对
- key事务操作反对有线,只反对多key在同一节点的事务操作,多key散布不同节点时无奈应用事务性能
- 不反对多数据库空间,单机redis能够反对16个db,集群模式下只能应用一个,即db 0
Redis Cluster模式不倡议应用pipeline和multi-keys操作,缩小max redirect产生的场景。
cluster的相干疑难
为什么redis的槽要用 16384
?
值得快乐的是:这个问题作者出门答复了:
能了解作者意思的能够不必看上面的内容
地址:https://github.com/redis/redi...
The reason is:Normal heartbeat packets carry the full configuration of a node, that can be replaced in an idempotent way with the old in order to update an old config. This means they contain the slots configuration for a node, in raw form, that uses 2k of space with16k slots, but would use a prohibitive 8k of space using 65k slots.At the same time it is unlikely that Redis Cluster would scale to more than 1000 mater nodes because of other design tradeoffs.So 16k was in the right range to ensure enough slots per master with a max of 1000 maters, but a small enough number to propagate the slot configuration as a raw bitmap easily. Note that in small clusters the bitmap would be hard to compress because when N is small the bitmap would have slots/N bits set that is a large percentage of bits set.
- 首先咱们查看一下构造体,对于cluster的源代码:
cluster.h
代码如下:
typedef struct { char sig[4]; /* Signature "RCmb" (Redis Cluster message bus). */ uint32_t totlen; /* Total length of this message */ uint16_t ver; /* Protocol version, currently set to 1. */ uint16_t port; /* TCP base port number. */ uint16_t type; /* Message type */ uint16_t count; /* Only used for some kind of messages. */ uint64_t currentEpoch; /* The epoch accordingly to the sending node. */ uint64_t configEpoch; /* The config epoch if it's a master, or the last epoch advertised by its master if it is a slave. */ uint64_t offset; /* Master replication offset if node is a master or processed replication offset if node is a slave. */ char sender[CLUSTER_NAMELEN]; /* Name of the sender node */ unsigned char myslots[CLUSTER_SLOTS/8]; char slaveof[CLUSTER_NAMELEN]; char myip[NET_IP_STR_LEN]; /* Sender IP, if not all zeroed. */ char notused1[34]; /* 34 bytes reserved for future usage. */ uint16_t cport; /* Sender TCP cluster bus port */ uint16_t flags; /* Sender node flags */ unsigned char state; /* Cluster state from the POV of the sender */ unsigned char mflags[3]; /* Message flags: CLUSTERMSG_FLAG[012]_... */ union clusterMsgData data;} clusterMsg;
集群节点之间的通信内容无非就是IP信息,申请头,申请内容,以及一些参数信息,这里着重看一下参数myslots[CLUSTER_SLOTS/8]
define CLUSTER_SLOTS 16384 这里就是16384的起源
在redis节点发送心跳包时须要把所有的槽放到这个心跳包里,以便让节点晓得以后集群信息,16384=16k,在发送心跳包时应用char
进行bitmap压缩后是2k(2 * 8 (8 bit) * 1024(1k) = 2K
),也就是说应用2k的空间创立了16k的槽数。
尽管应用CRC16算法最多能够调配65535(2^16-1)个槽位,65535=65k,压缩后就是8k(8 * 8 (8 bit) * 1024(1k) = 8K
),也就是说须要须要8k的心跳包,作者认为这样做不太值得;并且个别状况下一个redis集群不会有超过1000个master节点,所以16k的槽位是个比拟适合的抉择。
参考资料:
https://juejin.cn/post/684490...
https://juejin.cn/post/684490...
为什么Redis集群有16384个槽