集群
先来简单了解下redis中提供的集群策略, 虽然redis有持久化功能能够保障redis服务器宕机也能恢复并且只有少量
的数据损失,但是由于所有数据在一台服务器上,如果这台服务器出现硬盘故障,那就算是有备份也仍然不可避免数据丢失的问题。
在实际生产环境中,我们不可能只使用一台redis服务器作为我们的缓存服务器,必须要多台实现集群,避免出现单点故障;
主从复制
复制的作用是把redis的数据库复制多个副本部署在不同的服务器上,如果其中一台服务器出现故障,也能快速迁
移到其他服务器上提供服务。 复制功能可以实现当一台redis服务器的数据更新后,自动将新的数据同步到其他服务器上
主从复制就是我们常见的master/slave模式, 主数据库可以进行读写操作,当写操作导致数据发生变化时会自动将
数据同步给从数据库。而一般情况下,从数据库是只读的,并接收主数据库同步过来的数据。 一个主数据库可以有多个从数据库
配置
在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上的所有数据都复制一份。具体步骤
在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,不会在自己本地落地磁盘了