单机Redis的瓶颈
- 容量瓶颈( 单台Redis提供的容量有限 )
- QPS瓶颈( 单台Redis能提供的有限 )
- 机械故障( 单台redis无法保证高可用 )
主从复制的约定
- 一个master可以有多个slave
- 一个slave只能用一个master
- 数据流向是单向的,master到slave (所以要求一般slave是read-only的,不然就无法保证主从一致性了)
主从配置的两种方式
slaveof命令(运行中执行)
例如,机器A的ip为ipA, 机器B的ip为ipB,机器A上的redis作为slave,机器B的redis作为master,如果希望机器A对机器B的redis进行一个主从配置/复制同步的话,那么就在机器A上执行: slaveof ipB:port
(机器A的redis执行完该命令之后,会对机器A的redis进行一个清楚,然后进行数据同步)
如果不再让机器A作为机器B的slave的话,可以执行 slaveof no one
来断开主从关系(即使断开了主从关系,过去同步的数据依然不会清楚)
配置(启动执行)
可以在配置文件中加入如下命令:
1 | slaveof ip port // 表示作为哪一个节点的从节点 |
(ps:在master的配置文件中,requirepass [password] 来设置密码)
(pps: 在redis中,auth password 用于验证身份, info replication查看主从状态)
方式 | 命令 | 配置 |
---|---|---|
优点 | 无需重启 | 统一配置,方便管理 |
缺点 | 不方便管理 | 需要重启 |
*Redis主从模式下的几个问题
1. 读写分离
读写分离:读流量分摊到从节点
读写分离的问题:
复制数据延迟(解决延迟代价很高)
读到过期的数据
redis在清理过期数据时,有一个方式是懒惰删除,即在获取这个key的时候检查是否过期,若过期则删除,而又由于从节点无法主动删除数据(read-only), 所以如果master没有及时把过期数据告诉slave的话可能会造成脏读,redis3.2之后解决了这个问题。
从节点故障
将从节点上的客户端进行迁移,成本较高。
2. 主从配置不一致
例如maxmemory不一致,导致主从不一致
3. 规避全量复制
第一次全量复制
第一次全量复制不可能避免(减少分片maxmemory, 在低峰的时候进行)
节点运行ID不匹配
redis每次启动时,会有一个run_id,slave会保存master的run_id, 如果master的run_id发生了变化的话,那么就会触发一个全量复制。
复制积压缓冲区不足
4. 规避复制风暴
主从复制流程
run_id :
Redis每次启动时,都有一个随机ID来标识Redis,这个随机ID就是上面通过info命令查看得到的run_id, 查看master节点上的run_id和偏移量:
1 | [root@localhost ~]# redis-cli info server | grep run_id |
offset:
偏移量(offset)就是数据写入量的字节数。
在master节点的Redis上写入数据时,master就会记录写了多少数据,并记录在偏移量中。
在master上的操作,会同步到salve机器上,slave上的Redis也会记录偏移量。
当两台机器上的偏移量相同时,代表数据同步完成
偏移量是部分复制很重要的依据
查看Redis的偏移量
1 | 127.0.0.1:6379> info replication # 查看复制信息 |
master的run_id的改变会触发全量复制
主从的offset相等则说明一致
psync [run_id] [offset]
表示需要让run_id的redis将offset之后的数据同步给当前节点..
全量复制
- master的全部数据同步到slave
- master在进行同步期间写的数据也同步到slave
流程:
1. slave -> master:
slave向master发送一个psync ? -1
的命令, 因为第一次不知道master节点的run_id和offset,所以传的是?和-1
2. master -> slave:
返回 master 的 run_id 和 offset
3. slave保存master传来的信息
4. master 进行一个bgsave,生成RDB文件
5. master -> slave:
传输RDB文件(全量备份),传输期间会把“write”的信息存到一个buffer中(repl_back_buffer),这部分就是在传输期间会导致不一致的数据,在传输完RDB之后会传输这部分消息
6. master -> slave:
传输buffer中的数据(增量备份)
7. salve清除旧的数据,写入新数据
全量复制的开销
- bgsave的开销 (master)
- RDB文件进行网络传输的时间 (master)
- slave清空数据(slave)
- slave加载RDB数据(slave)
- 可能的AOF重写时间 (slave加载完RDB之后,如果开启了AOF,那么会进行一个AOF重写)
部分复制
全量复制开销太大, 在没有必要使用全量复制的时候就可以使用部分复制来做.
部分复制其实还是psync [run_id] [offset]
, 通知run_id对应的redis把offset之后的数据都同步过来。。master节点在收到这个指令之后,会去查看能否响应这个offset之后的数据(看这个offset是否在维护的范围内),如果可以响应,那么就将offset后的部分数据同步给slave..