redis(4)--redis集群之主从复制

时间:2023-01-02 04:34:55

集群

先来简单了解下redis中提供的集群策略, 虽然redis有持久化功能能够保障redis服务器宕机也能恢复并且只有少量
的数据损失,但是由于所有数据在一台服务器上,如果这台服务器出现硬盘故障,那就算是有备份也仍然不可避免数据丢失的问题。

在实际生产环境中,我们不可能只使用一台redis服务器作为我们的缓存服务器,必须要多台实现集群,避免出现单点故障;

主从复制

复制的作用是把redis的数据库复制多个副本部署在不同的服务器上,如果其中一台服务器出现故障,也能快速迁
移到其他服务器上提供服务。 复制功能可以实现当一台redis服务器的数据更新后,自动将新的数据同步到其他服务器上

主从复制就是我们常见的master/slave模式, 主数据库可以进行读写操作,当写操作导致数据发生变化时会自动将
数据同步给从数据库。而一般情况下,从数据库是只读的,并接收主数据库同步过来的数据。 一个主数据库可以有多个从数据库
redis(4)--redis集群之主从复制

 

配置

在redis中配置master/slave是非常容易的,只需要在从数据库的配置文件中加入slaveof 主数据库地址 端口。 而master 数据库不需要做任何改变
准备三台服务器,分别安装redis , server1(192.168.25.129) server2(192.168.25.130) server3(192.168.25.131)
\1. 在server2的redis.conf文件中增加 slaveof server1-ip 6379 (即:slaveof 192.168.25.129 6379)

 在server3的redis.conf文件中增加 slaveof server1-ip 6379 (即:slaveof 192.168.25.129 6379)
\2. 启动server1,然后启动server2,server3
\3. 访问server2的redis客户端,输入 INFO replication

127.0.0.1:6379> info replication
# Replication
role:slave
master_host:192.168.25.129
master_port:6379
master_link_status:down
master_last_io_seconds_ago:-1
master_sync_in_progress:0
slave_repl_offset:1
master_link_down_since_seconds:1556958915
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

则证明从服务器没有起来,可以yum install telnet安装telnet命令,安装成功后,用telnet 192.168.25.129 6379 试一下能不能访问,如果不能访问则查看主节点配置(server1 的redis.config)

vim redis.config 查找下图标黄的配置

# Examples:
#
# bind 192.168.1.100 10.0.0.1
# bind 127.0.0.1 ::1
#
# ~~~ WARNING ~~~ If the computer running Redis is directly exposed to the
# internet, binding to all the interfaces is dangerous and will expose the
# instance to everybody on the internet. So by default we uncomment the
# following bind directive, that will force Redis to listen only into
# the IPv4 lookback interface address (this means Redis will be able to
# accept connections only from clients running into the same computer it
# is running).
#
# IF YOU ARE SURE YOU WANT YOUR INSTANCE TO LISTEN TO ALL THE INTERFACES
# JUST COMMENT THE FOLLOWING LINE.
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bind 127.0.0.1

# Protected mode is a layer of security protection, in order to avoid that
# Redis instances left open on the internet are accessed and exploited.
#
# When protected mode is on and if:
#
# 1) The server is not binding explicitly to a set of addresses using the
#    "bind" directive.
# 2) No password is configured.
#
# The server only accepts connections from clients connecting from the
# IPv4 and IPv6 loopback addresses 127.0.0.1 and ::1, and from Unix domain
# sockets.
#
# By default protected mode is enabled. You should disable it only if
# you are sure you want clients from other hosts to connect to Redis
# even if no authentication is configured, nor a specific set of interfaces
# are explicitly listed using the "bind" directive.
protected-mode yes

# Accept connections on the specified port, default is 6379 (IANA #815344).
# If port 0 is specified Redis will not listen on a TCP socket.
port 6379

# TCP listen() backlog.
#
# In high requests-per-second environments you need an high backlog in order
# to avoid slow clients connections issues. Note that the Linux kernel

  

  redis3.2版本后新增protected-mode配置,默认是yes,即开启。设置外部网络连接redis服务,设置方式如下:

  1、关闭protected-mode模式,此时外部网络可以直接访问

  2、开启protected-mode保护模式,需配置bind ip或者设置访问密码

  

  而bind 127.0.0.1 限制访问地址,设置为 0.0.0.0 表示都可以访问,如果是127.0.0.1 表示localhost访问 

  修改后配置从新启动主、从服务器。可以看到:

  

127.0.0.1:6379> info replication
# Replication
role:slave
master_host:192.168.25.129
master_port:6379
master_link_status:up
master_last_io_seconds_ago:7
master_sync_in_progress:0
slave_repl_offset:57
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

 

\4. 通过在master机器上输入命令,比如set foo bar 、 在slave服务器就能看到该值已经同步过来了

 在server1主节点上,设置key,并且get key

127.0.0.1:6379> set lf 1994
OK
127.0.0.1:6379> get lf
"1994"
在server2、server3从节点上get key,一样可以拿到值

127.0.0.1:6379> get lf
"1994"

 

原理

全量复制

Redis全量复制一般发生在Slave初始化阶段,这时Slave需要将Master上的所有数据都复制一份。具体步骤

redis(4)--redis集群之主从复制

 在server2上设置监听:replconf listening-port 6379

 返回ok后,再输入:sync进行监听:

 在server1主节点,设置一个key和value 

127.0.0.1:6379> set hello helloword
OK

 观察server2

127.0.0.1:6379> replconf listening-port 6379
OK
127.0.0.1:6379> sync
Entering slave output mode...  (press Ctrl-C to quit)
SYNC with master, discarding 88 bytes of bulk transfer...
SYNC done. Logging commands from master.
"PING"
"SELECT","0"
"set","hello","helloword"
"PING"
"PING"
"PING"
"PING"
"PING"

  

完成上面几个步骤后就完成了slave服务器数据初始化的所有操作,savle服务器此时可以接收来自用户的读请求。
master/slave 复制策略是采用乐观复制,也就是说可以容忍在一定时间内master/slave数据的内容是不同的,但是两者的数据会最终同步。
具体来说,redis的主从同步过程本身是异步的,意味着master执行完客户端请求的命令后会立即返回结果给客户端,然后异步的方式把命令同步给slave。
这一特征保证启用master/slave后 master的性能不会受到影响。

但是另一方面,如果在这个数据不一致的窗口期间,master/slave因为网络问题断开连接,而这个时候,master是无法得知某个命令最终同步给了多少个slave数据库。
不过redis提供了一个配置项来限制只有数据至少同步给多少个slave的时候,master才是可写的:
min-slaves-to-write 3 表示只有当3个或以上的slave连接到master,master才是可写的
min-slaves-max-lag 10 表示允许slave最长失去连接的时间,如果10秒还没收到slave的响应,则master认为该slave以断开

增量复制

从redis 2.8开始,就支持主从复制的断点续传,如果主从复制过程中,网络连接断掉了,那么可以接着上次复制的地方,继续复制下去,而不是从头开始复制一份
master node会在内存中创建一个backlog,master和slave都会保存一个replica offset还有一个master id,offset就是保存在backlog中的。如果master和slave网络连接断掉了,slave会让master从上次的replica offset开始继续复制
但是如果没有找到对应的offset,那么就会执行一次全量同步

无硬盘复制

前面我们说过,Redis复制的工作原理基于RDB方式的持久化实现的,也就是master在后台保存RDB快照,slave接收到rdb文件并载入,但是这种方式会存在一些问题
\1. 当master禁用RDB时,如果执行了复制初始化操作,Redis依然会生成RDB快照,当master下次启动时执行该RDB文件的恢复,但是因为复制发生的时间点不确定,所以恢复的数据可能是任何时间点的。
就会造成数据出现问题

\2. 当硬盘性能比较慢的情况下(网络硬盘),那初始化复制过程会对性能产生影响因此2.8.18以后的版本,Redis引入了无硬盘复制选项,
可以不需要通过RDB文件去同步,直接发送数据,通过以下配置来开启该功能
repl-diskless-sync yes
master**在内存中直接创建rdb,然后发送给slave,不会在自己本地落地磁盘了