Redis学习之集群
前言
在前面,我们学习了Redis的基本操作,Jedis的使用以及Redis的持久化方案,接下来我们来学习Redis的集群管理。
复制
当数据存储在一台服务器上时,如果该服务器挂了,那么数据就会丢失了,所以Redis提供了复制的功能来实现将一台服务器上的数据自动地同步到其他的服务器上。
在复制的操作中,数据库可以分为两类:主数据库(master)和从数据库(slave),主数据库用于读写操作,而从数据库一般只用于读操作,并且接受主数据库同步过来的数据。
在Redis中,启用复制功能非常简单,只需要在从数据库中配置slaveof MASTER_HOST MASTER_PORT
即可,此外无需进行任何其他的配置,Redis会自动将从数据库的变化自动同步到主数据库中
当然,如果主库配置了密码,则需要在从库中配置masterauth PASSWORD
来配置密码,否则,从库无法从主库中同步数据。
配置完成之后,可以登录从库,通过命令:info replication
查看复制的信息,如下
# Replication
role:slave
master_host:127.0.0.1
master_port:8080
master_link_status:up
# 其他信息
slave_read_only:1
master_replid:c1fafc68662e4b495e7a8619a1408ded499dba4e
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:14
# 其他信息
在主库中查看对应的信息
# Replication
role:master
connected_slaves:1
slave0:ip=127.0.0.1,port=6379,state=online,offset=210,lag=1
master_replid:c1fafc68662e4b495e7a8619a1408ded499dba4e
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:210
second_repl_offset:-1
从上面的信息可以看到,6379端口的Redis已经是端口8080的从服务器了,此时,登录6379服务器,可以获取8080的数据,并且8080的数据变化会自动同步到6379中。
由于默认情况下,Redis的从库只支持只读操作,如果想直接写入从库,可以开启从库的slave-read-only yes/no
,但要注意,从库的变化不会同步到主库中,所以,一般情况下,我们是不配置从库的写操作的。
如果想要断开主从关系,可以通过slaveof no one
命令来在运行时实现目的,也可以通过slaveof HOST PORT
来实现断开当前主库,并连接到其他主库。
原理
当一个从库启动后,会想主库发送SYNC命令,主库收到后,会在后台保存快照,并且将快照期间的命令缓存起来,快照完成后,将快照以及期间的缓存命令发送给从库,从库从该文件中将数据载入内存。
在Redis2.8之后,支持增量数据传输,可以极大提高传输的性能。
图结构
从数据库不仅可以接收主数据库的同步数据,自己也可以同时作为主数据库存在,形成类似图的结构,同时,如果从数据库开启写入模式,则从数据库写入的数据会同步到从数据库的从数据库,但不会写入到其同级或者父级节点。
持久化
可以通过设置主数据库不启用持久化,从数据库启用持久化的功能,来使得主数据库的性能达到最大。
当主数据库崩溃之后,想通过从数据库来恢复数据,需要一下步骤
- 在从数据库中使用
slaveof no one
将从数据库提升为主数据库 - 启动之前崩溃的主数据库,然后使用
slaveof HOST PORT
将其设置为新的主数据库的从数据库
一定要避免直接重启主数据库,不然此时由于主数据库没有持久化,数据是空的,会将该状态直接传递给从数据库,从而导致所有的数据都丢失了。
无硬盘复制
Redis 2.8之后,提供了无硬盘复制选项,开启之后,主从之间同步数据时,直接通过网络传输,而不会写入到硬盘中,从而避免因为硬盘的性能问题带来额外开销。repl-disless-sync yes/no
哨兵
Redis通过引入哨兵工具来实现自动化的系统监控和故障恢复功能。
哨兵是一个独立的进程,在一主多从的系统中,可以使用多个哨兵进行监控任务以保证系统足够稳健。
启用方式
编写一个配置文件,命名为sentinel.conf
名字随意
内容为
sentinel monitor mymaster HOST PORT NUM
其中的mymaster可以随意,符合命名规范即可,HOST是主库的地址,PORT是主库的端口,后面的NUM是当主库挂了的时候,从库需要多少个从库投票才能成为主库的数量。
然后通过redis-sentinel /PATH/TO/SENTINEL_CONFIG
工具来启动即可
需要注意的是,如果主库有配置密码,需要加入以下内容
sentinel auth-pass mymaster PASSWORD
启动后输出内容如下
19825:X 26 Sep 15:13:33.288 # Sentinel ID is 75c6f08db6fa065e59f161dde3a4be78fb886dfa
19825:X 26 Sep 15:13:33.288 # +monitor master mymaster 127.0.0.1 8080 quorum 1
19825:X 26 Sep 15:13:33.288 * +slave slave 127.0.0.1:8089 127.0.0.1 8089 @ mymaster 127.0.0.1 8080
19825:X 26 Sep 15:13:33.294 * +slave slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 8080
可以看到,启动哨兵之后,哨兵会自动监控主数据库以及发现从数据库
此时我们模拟以下主库挂了的情况,通过cli向主库发送shutdown
命令,稍等片刻后可以看到以下输出内容
19825:X 26 Sep 15:14:38.007 # +sdown master mymaster 127.0.0.1 8080
19825:X 26 Sep 15:14:38.007 # +odown master mymaster 127.0.0.1 8080 #quorum 1/1
19825:X 26 Sep 15:14:38.007 # +new-epoch 1
19825:X 26 Sep 15:14:38.007 # +try-failover master mymaster 127.0.0.1 8080
19825:X 26 Sep 15:14:38.011 # +vote-for-leader 75c6f08db6fa065e59f161dde3a4be78fb886dfa 1
19825:X 26 Sep 15:14:38.011 # +elected-leader master mymaster 127.0.0.1 8080
19825:X 26 Sep 15:14:38.011 # +failover-state-select-slave master mymaster 127.0.0.1 8080
19825:X 26 Sep 15:14:38.111 # +selected-slave slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 8080
19825:X 26 Sep 15:14:38.111 * +failover-state-send-slaveof-noone slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 8080
19825:X 26 Sep 15:14:38.166 * +failover-state-wait-promotion slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 8080
19825:X 26 Sep 15:14:38.270 # +promoted-slave slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 8080
19825:X 26 Sep 15:14:38.270 # +failover-state-reconf-slaves master mymaster 127.0.0.1 8080
19825:X 26 Sep 15:14:38.321 * +slave-reconf-sent slave 127.0.0.1:8089 127.0.0.1 8089 @ mymaster 127.0.0.1 8080
19825:X 26 Sep 15:14:39.276 * +slave-reconf-inprog slave 127.0.0.1:8089 127.0.0.1 8089 @ mymaster 127.0.0.1 8080
19825:X 26 Sep 15:14:39.276 * +slave-reconf-done slave 127.0.0.1:8089 127.0.0.1 8089 @ mymaster 127.0.0.1 8080
19825:X 26 Sep 15:14:39.337 # +failover-end master mymaster 127.0.0.1 8080
19825:X 26 Sep 15:14:39.337 # +switch-master mymaster 127.0.0.1 8080 127.0.0.1 6379
19825:X 26 Sep 15:14:39.337 * +slave slave 127.0.0.1:8089 127.0.0.1 8089 @ mymaster 127.0.0.1 6379
19825:X 26 Sep 15:14:39.337 * +slave slave 127.0.0.1:8080 127.0.0.1 8080 @ mymaster 127.0.0.1 6379
19825:X 26 Sep 15:15:09.367 # +sdown slave 127.0.0.1:8080 127.0.0.1 8080 @ mymaster 127.0.0.1 6379
可以看到,此时哨兵发现主库挂了,于是哨兵请求查询是否主库挂了,得到其他节点的印证后,哨兵开始选举新的主库(6379),并且将原本的主库设置为新的主库的从库,具体过程可以参考上面的日志。
我在操作上面的案例的时候,出现了一个奇怪的问题
由于一开始只有主库设置了密码,从库没有设置,当主库挂了之后,从库会使用auth命令去连接新的主库,而此时由于新的主库并没有设置密码,所以会出现错误,从而导致从库无法连接到新的从库中
解决方法是,要么每个从库都设置密码,当然,密码是一样的,要么都不设置密码,我这里采用第一种方法。
总结
本小节主要学习Redis的复制以及哨兵管理,其中的复制功能,能够将Redis进行多份复制,读写分离,从而使得整体的性能极大地提高,而通过哨兵,可以有效地监控以及管理节点,当有节点挂了的时候,哨兵会进行一系列的选举等操作,来保证整体的可用。