Redis 搭建集群
# 120.Redis 搭建集群
只有单个 Redis 的情况下,一旦发生单点故障,就容易导致数据丢失;并且单机也很难承受高并发的情况,此时我们可以搭建集群,实现负载均衡
# “复制”的概念
Redis 提供了复制(replication)功能,可以实现当一台数据库中的数据更新后,自动将更新的数据同步到其他数据库上。
在复制的概念中,Redis 数据库分为两类,一类是主数据库(master),另一类是从数据库(slave)。
从数据库不仅可以接收主数据库的同步数据,自己也可以同时作为主数据库存在,形成类似图的结构,如图所示,数据库 A 的数据会同步到 B 和 C 中,而 B 中的数据会同步到 D 和 E 中。向 B 中写入数据不会同步到 A 或 C 中,只会同步到 D 和 E 中。
# 通过“复制”搭建集群
接下来我们在 Windows 环境下搭建一个集群来(Linux 步环境下是差不多的)
我们先关闭所有 Redis,然后打开 cmd,启动 Redis:
$ redis-server
该实例默认监听 6379 端口
我们打开一个新的 cmd,启动一个新的 Redis 实例:
$ redis-server --port 6380 --slaveof 127.0.0.1 6379
port 参数表明该实例监听的是 6380 端口(不能是 6379,会冲突),后续的 slaveof 参数表明是本实例是另一个 Redis 实例的从数据库,然后是主数据库的 IP 和端口。
此时在主数据库中的任何数据变化都会自动地同步到从数据库中。
我们打开一个 redis-cli 实例 A,连接主数据库:
redis-cli -p 6379
再打开一个 redis-cli 实例 B,连接从数据库:
redis-cli -p 6380
这时我们使用 INFO 命令来分别在实例 A 和实例 B 中获取 Replication 节的相关信息:
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:1
slave0:ip=127.0.0.1,port=6380,state=online,offset=281,lag=1
master_repl_offset:281
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:280
2
3
4
5
6
7
8
9
10
可以看到,实例 A 的角色(上面输出中的第 3 行 role)是 master,即主数据库,同时已连接的从数据库(上面输出中的第 4 行 connected_slaves)的个数为 1。
同样在实例 B 中获取相应的信息为:
127.0.0.1:6380> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6379
master_link_status:up
master_last_io_seconds_ago:6
master_sync_in_progress:0
slave_repl_offset:351
slave_priority:100
slave_read_only:1
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
127.0.0.1:6380>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
这里可以看到,实例 B 的 role 是 slave(第 3 行),即从数据库,同时其主数据库的地址为 127.0.0.1,端口为 6379(第 4 行)。
在实例 A 中使用 SET 命令设置一个键的值:
redis A> SET foo bar
OK
2
此时在实例 B 中就可以获得该值了:
redis B> GET foo
"bar"
2
配置多台从数据库的方法也一样,在所有的从数据库的配置文件中都加上 slaveof 参数指向同一个主数据库即可。
# 从数据库的数据修改
默认情况下,从数据库是只读的,如果直接修改从数据库的数据会出现错误:
redis B> SET foo hi
(error) READONLY You can't write against a read only slave.
2
可以通过设置从数据库的配置文件中的 slave-read-only 为 no 以使从数据库可写,但是因为对从数据库的任何更改都不会同步给任何其他数据库,并且一旦主数据库中更新了对应的数据就会覆盖从数据库中的改动,所以通常的场景下不应该设置从数据库可写,以免导致易被忽略的潜在应用逻辑错误。
# 动态调整主从关系
除了通过配置文件或命令行参数设置 slaveof 参数,还可以在运行时使用 SLAVEOF 命令修改:
redis> SLAVEOF 127.0.0.1 6379
如果该数据库已经是其他主数据库的从数据库了,SLAVEOF 命令会停止和原来数据库的同步转而和新数据库同步。
此外对于从数据库来说,还可以使用 SLAVEOF NO ONE 命令来使当前数据库停止接收其他数据库的同步并转换成为主数据库。
# 故障恢复
当从数据库崩溃时,直接重启恢复即可,主数据库会自动将数据同步过来;
而当主数据库崩溃时,就有点麻烦了,我们可以将调整一个从数据库为主数据库(使用 SLAVEOF NO ONE 命令),然后将主数据库恢复,并设置其为新的主数据库的从库。
由于需要手工操作,比较麻烦;后续我们介绍哨兵,自动切换主从数据库。