Redis的主从复制

791 阅读7分钟

微信公众号:51码农网
网站:www.51manong.com
51码农网,程序员社群学习打卡网站 抱团学习 共同进步[1]
51码农网,让程序员的坚持学习变得简单一些[1]

Redis的主从复制

主从复制的概念解读

持久化保证了即使redis服务重启也不会丢失数据,因为redis服务重启后会将硬盘上持久化的数据恢复到内存中,但是当redis服务器的硬盘损坏了可能会导致数据丢失,不过通过redis的主从复制机制就可以避免这种单点故障。

1.Redis 使用异步复制。 从 Redis 2.8 开始, 从服务器会以每秒一次的频率向主服务器报告复制流(replication stream)的处理进度。

2.一个主服务器可以有多个从服务器。

3.一个redis可以即是主又是从,不仅主服务器可以有从服务器, 从服务器也可以有自己的从服务器, 多个从服务器之间可以构成一个图状结构。

4.复制功能不会阻塞主服务器: 即使有一个或多个从服务器正在进行初次同步, 主服务器也可以继续处理命令请求。

5.复制功能也不会阻塞从服务器: 只要在 redis.conf 文件中进行了相应的设置, 即使从服务器正在进行初次同步, 服务器也可以使用旧版本的数据集来处理命令查询

实现主从复制的好处

实现了主从复制之后,一方面能够实现数据的读写分离,降低主服务器的压力,另一个可以实现数据的备份。可以通过复制功能来让主服务器免于执行持久化操作: 只要关闭主服务器的持久化功能, 然后由从服务器去执行持久化操作即可

Redis从服务器的只读特性

从 Redis 2.6 开始, 从服务器支持只读模式, 并且该模式为从服务器的默认模式。

只读模式由 redis.conf 文件中的 slave-read-only 选项控制, 也可以通过 CONFIG SET parameter value 命令来开启或关闭这个模式。

1slave-read-only yes

只读从服务器会拒绝执行任何写命令, 所以不会出现因为操作失误而将数据不小心写入到了从服务器的情况。

1127.0.0.1:6380set hlx 890
2(errorREADONLY You can't write against a read only slave.

即使从服务器是只读的, DEBUG 和 CONFIG 等管理式命令仍然是可以使用的, 所以我们还是不应该将服务器暴露给互联网或者任何不可信网络。 不过, 使用 redis.conf 中的命令改名选项, 我们可以通过禁止执行某些命令来提升只读从服务器的安全性。

你可能会感到好奇, 既然从服务器上的写数据会被重同步数据覆盖, 也可能在从服务器重启时丢失, 那么为什么要让一个从服务器变得可写呢?

原因是, 一些不重要的临时数据, 仍然是可以保存在从服务器上面的。 比如说, 客户端可以在从服务器上保存主服务器的可达性(reachability)信息, 从而实现故障转移(failover)策略。

实现Redis的主从复制

假设3个redis实例,实例A是主服务器master,实例B和实例C是实现A的从服务器slave,他们对应的端口分别是6379/6380/6381

1主服务器  A    端口 6379  ip:192.168.232.128
2从服务器  B    端口 6380  ip:192.168.232.128
3从服务器  C    端口 6381  ip:192.168.232.128

1.复制redis.conf 复制2份,redis.conf6380 redis.conf6381
复制后的结果如下:

1[erayt@ERAYT-01 bin]$ ls
2appendonly.aof  redis-benchmark  redis-check-dump  redis.conf      redis.conf6381  redis-server
3log-redis.log   redis-check-aof  redis-cli         redis.conf6380  redis-sentinel

2.主redis无需配置,从redis的配置修改如下:

1slaveof <masterip> <masterport>
2slaveof 127.0.0.1 6379

上边的配置说明当前【从服务器】对应的【主服务器】的IP是192.168.232.128,端口是6379。

3.启动3个Redis实例,分别进入3个实例的监控台

1[erayt@ERAYT-01 bin]$ ./redis-server redis.conf
2[erayt@ERAYT-01 bin]$ ./redis-server redis.conf6380
3[erayt@ERAYT-01 bin]$ ./redis-server redis.conf6381

进入3个实例的监控台

1[erayt@ERAYT-01 bin]$ ./redis-cli -p 6379
2[erayt@ERAYT-01 bin]$ ./redis-cli -p 6380
3[erayt@ERAYT-01 bin]$ ./redis-cli -p 6381

4.输入INFO replication命令查看当前实例的状态

主服务器 A 6379

 1127.0.0.1:6379> INFO replication
2# Replication
3role:master
4connected_slaves:2
5slave0:ip=127.0.0.1,port=6380,state=online,offset=491,lag=0
6slave1:ip=127.0.0.1,port=6381,state=online,offset=491,lag=0
7master_repl_offset:491
8repl_backlog_active:1
9repl_backlog_size:1048576
10repl_backlog_first_byte_offset:2
11repl_backlog_histlen:490

从服务器 B 6380

 1127.0.0.1:6380INFO replication
2Replication
3role:slave
4master_host:127.0.0.1
5master_port:6379
6master_link_status:up
7master_last_io_seconds_ago:1
8master_sync_in_progress:0
9slave_repl_offset:631
10slave_priority:100
11slave_read_only:1
12connected_slaves:0
13master_repl_offset:0
14repl_backlog_active:0
15repl_backlog_size:1048576
16repl_backlog_first_byte_offset:0
17repl_backlog_histlen:0
18127.0.0.1:6380>

从服务器 C 6381

 1127.0.0.1:6381INFO replication
2Replication
3role:slave
4master_host:127.0.0.1
5master_port:6379
6master_link_status:up
7master_last_io_seconds_ago:6
8master_sync_in_progress:0
9slave_repl_offset:701
10slave_priority:100
11slave_read_only:1
12connected_slaves:0
13master_repl_offset:0
14repl_backlog_active:0
15repl_backlog_size:1048576
16repl_backlog_first_byte_offset:0
17repl_backlog_histlen:0
18127.0.0.1:6381

5.主机存储信息,看从节点是否get到

1127.0.0.1:6379set hlx manong
2OK
3
4127.0.0.1:6380get hlx
5"manong"

主服务器和从服务器实现了数据同步

Redis主从复制的一些概念

1、主服务器 ID (master run id),每次启动redis都会分配一个id,重启之后runid变化。

1[erayt@ERAYT-01 bin]$ ./redis-cli -p 6379 info server | grep run
2run_id:c8d4ed4955c8242d6608127d4c6e5a93251cfd36

2、复制偏移量(replication offset),请求master数据额偏移量,部分复制的时候,根据这个进行复制

1[erayt@ERAYT-01 bin]$ ./redis-cli -p 6379 info replication | grep offset
2slave0:ip=127.0.0.1,port=6380,state=online,offset=7940,lag=0
3slave1:ip=127.0.0.1,port=6381,state=online,offset=7940,lag=0
4master_repl_offset:7940
5repl_backlog_first_byte_offset:2

3、repl_backlog_size,复制缓冲区大小,默认为1M,部分复制的时候,如果offset在这个范围内,则开始部分复制,否者要进行全量复制。可以修改这个大小以达到更好地复制机制。

Redis全量复制的原理

1.无论是初次连接还是重新连接, 当建立一个从服务器时, 从服务器都将向主服务器发送一个 SYNC 命令。

2.接到 SYNC 命令的主服务器将开始执行 BGSAVE , 并在保存操作执行期间, 将所有新执行的写入命令都保存到一个缓冲区里面。

3.当 BGSAVE 执行完毕后, 主服务器将执行保存操作所得的 .rdb 文件发送给从服务器, 从服务器接收这个 .rdb 文件, 并将文件中的数据载入到内存中。

4.之后主服务器会以 Redis 命令协议的格式, 将写命令缓冲区中积累的所有内容都发送给从服务器。

即使有多个从服务器同时向主服务器发送 SYNC , 主服务器也只需执行一次 BGSAVE 命令, 就可以处理所有这些从服务器的同步请求。

从服务器可以在主从服务器之间的连接断开时进行自动重连, 在 Redis 2.8 版本之前, 断线之后重连的从服务器总要执行一次完整重同步(full resynchronization)操作, 但是从 Redis 2.8 版本开始, 从服务器可以根据主服务器的情况来选择执行完整重同步还是部分重同步(partial resynchronization)。

部分重同步

从 Redis 2.8 开始, 在网络连接短暂性失效之后, 主从服务器可以尝试继续执行原有的复制进程(process), 而不一定要执行完整重同步操作。

这个特性需要主服务器为被发送的复制流创建一个内存缓冲区(in-memory backlog), 并且主服务器和所有从服务器之间都记录一个复制偏移量(replication offset)和一个主服务器 ID (master run id), 当出现网络连接断开时, 从服务器会重新连接, 并且向主服务器请求继续执行原来的复制进程:

如果从服务器记录的主服务器 ID 和当前要连接的主服务器的 ID 相同, 并且从服务器记录的偏移量所指定的数据仍然保存在主服务器的复制流缓冲区里面, 那么主服务器会向从服务器发送断线时缺失的那部分数据, 然后复制工作可以继续执行。
否则的话, 从服务器就要执行完整重同步操作。

Redis 2.8 的这个部分重同步特性会用到一个新增的 PSYNC master_run_id offset 内部命令, 而 Redis 2.8 以前的旧版本只有 SYNC 命令, 不过, 只要从服务器是 Redis 2.8 或以上的版本, 它就会根据主服务器的版本来决定到底是使用 PSYNC master_run_id offset 还是 SYNC :

如果主服务器是 Redis 2.8 或以上版本,那么从服务器使用 PSYNC master_run_id offset 命令来进行同步。
如果主服务器是 Redis 2.8 之前的版本,那么从服务器使用 SYNC 命令来进行同步。

Redis学习文档网站

推荐一个redis网站:http://redisdoc.com/topic/

关注微信公众号: 51码农网