在从节点1和从节点2上分别进行配置
vim /usr/local/redis/etc/redis.conf
配置IP和端口
replicaof 192.168.0.180 6379
配置密码
masterauth 123456
之后重启redis
测试:
主节点上执行set a a
两台从节点上get a发现都能获取到值。
若在从节点上设置值,会有如下错误:
(error) READONLY You can't write against a read only replica.
此时主节点执行info replication,会得到如下结果:
# Replication
role:master
connected_slaves:2
slave0:ip=192.168.0.182,port=6379,state=online,offset=2736,lag=1
slave1:ip=192.168.0.181,port=6379,state=online,offset=2736,lag=1
master_replid:9aaf7cbbcfb924c8a793e1b69f0597a57768844b
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:2736
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:2736
注释:
Replication是注释。
connected_slaves:表示从节点数量
slave0和slave1:描述两个从节点的基本信息。
master_replid: 主服务器的复制 ID
master_replid2: 用于支持部分同步复制的第二复制 ID
master_repl_offset: 主服务器的复制偏移量,复制的进度。
repl_backlog_active: 启用复制 backlog 功能
repl_backlog_size: 复制 backlog 的大小为1048576字节
repl_backlog_first_byte_offset: 复制 backlog 中第一个字节的偏移量
repl_backlog_histlen: 复制 backlog 的历史长度为2736字节
backlog
复制积压缓冲区,当主节点有连接的slave时创建,主节点响应写请求时,会先写到自己的backlog buffer中。
可以简单的理解为,避免数据改动一个字节就频繁同步从节点,而是积累到一定的批次做缓冲。
从节点执行得到如下结果
# Replication
role:slave
master_host:192.168.0.180
master_port:6379
master_link_status:up
master_last_io_seconds_ago:3
master_sync_in_progress:0
slave_repl_offset:518
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:f1f768608ae81b330bb152f69a4a624bf3a9657e
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:518
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:518
role:slave: 表示这是一个从节点。
master_host:192.168.0.180: 指定了主节点的IP地址。
master_port:6379: 指定了主节点的端口号。
master_link_status:up: 表示从节点与主节点的连接状态为正常(已连接)。
master_last_io_seconds_ago:3: 上次与主节点进行IO操作的时间,这里是3秒前。
master_sync_in_progress:0: 没有正在进行的同步操作。
slave_repl_offset:518: 从节点当前复制偏移量为518。
slave_priority:100: 从节点的复制优先级为100。
slave_read_only:1: 从节点设置为只读模式(read-only)。
connected_slaves:0: 连接的从节点数为0,即没有其他从节点连接到这个从节点。
master_replid:f1f768608ae81b330bb152f69a4a624bf3a9657e: 主节点的复制ID。
master_replid2:0000000000000000000000000000000000000000: 第二复制ID。
master_repl_offset:518: 主节点当前复制偏移量为518。
second_repl_offset:-1: 第二复制偏移量为-1。
repl_backlog_active:1: 复制后备日志(repl backlog)处于激活状态。
repl_backlog_size:1048576: 复制后备日志的大小为1048576字节(1MB)。
repl_backlog_first_byte_offset:1: 复制后备日志的第一个字节偏移量为1。
repl_backlog_histlen:518: 复制后备日志历史长度为518。
可以理解为爹子孙三代。
这个用法与一主二从没有什么区别,可以接着一主二从的基础上,在从节点2上临时设置slave of 192.168.0.181 6379
(从1为从2主节点)即可。
注意密码问题,由于命令行不支持masterauth命令,所以可能需要在从节点配置文件中先把主节点密码设置到位。
$redis_master = new Redis();
$redis_master->connect('192.168.0.180', 6379);
$redis_master->auth('123456');
$redis_slave = new Redis();
$redis_slave->connect('192.168.0.181', 6379);
$redis_master->set('k', 'v');
print_r($redis_master->get('k'));
如果是从库写,也会报如上一样的错误:
Fatal error: Uncaught RedisException: READONLY You can't write against a read only replica. in E:\Host\test\t1.php:10 Stack trace: #0 E:\Host\test\t1.php(10): Redis->set('k', 'v') #1 {main} thrown in E:\Host\test\t1.php on line 10
对于Laravel框架:
config/database.php中的redis段,添加
'slave' => [
'client' => 'predis',
'host' => 'your_slave_redis_host',
'password' => 'your_slave_redis_password',
'port' => 6379,
'database' => 0,
],
使用主节点
Redis::connection('default')->set('key', 'value');
使用从节点
Redis::connection('slave')->get('key');
经过实测,若一个redis实例被做为从节点,那么原先的老数据会被清空,这可能会造成数据丢失。
Redis的特性,主从复制性能不会差,除非遇到大key。所以这里讨论的是,从节点1和主节点进度相同,从节点2和主节点进度不同的问题。
可以模拟从节点2挂掉,直接关停从节点2,主节点多写几个key,从节点1正常同步。此时启动从节点2,经过实测,发现进度得到了同步。
这意味Redis会自动处理进度不一致的问题,达到的是最终一致性。
经过实测,从节点不会自动变成主节点,从节点上的数据可以正常读取,仍旧不能写入。
比较好的一点是,虽然数据层,从节点强依赖主节点,但是主节点挂掉后,从节点没有挂掉,勉强使用。
此时从节点不进行任何操作,若主节点恢复,则整个主从架构正常运行。
官网有说:Redis主从复制的内部过程,是异步进行的(异步非阻塞,高性能)。由于Redis是单线程,通俗讲就是同时只能执行一个任务,却进行了异步实现,这个问题值得理解。
通过查阅资料,得知单线程异步是通过事件循环机制来处理。
单线程环境下:当一个异步操作被启动后,程序会继续执行其它任务,但异步操作的结果或者状态变化会被放入事件队列中,等待事件循环处理。当事件循环处理到该事件时,会调用相应的回调函数来处理操作的结果或者状态变化。在这种情况下,不需要额外创建新的线程。
按照我的理解,通俗讲,整个过程就是一个循环机制,不停的循环,获取事件队列上的数据,一是可以让待执行的异步任务再下一轮循环中去执行,二是可以再本次循环中执行同步的任务,直到任务为空从而停止,不需要额外现成的依赖。
纯缓存模式下:主节点崩溃,但是服务器设定了一些运维策略,可以自动重启进程。但Redis主节点启动时,将以空数据集重新启动。其它从节点缓存的数据,也将会被销毁。
所以:
复制与不带持久性配置的master一起使用时,应该禁用实例的自动重启。
或者,做好主节点的AOF与RDB配置。
RDB:配置save ‘’,并注释掉其它save项。
AOF:配置appendonly no
可修改为纯缓存模式,亲测确实会丢失数据。