集群
结构上:单台redis会发生单点故障,同时需要承受所有请求。
容量上:单台redis内存有限,容易出现存储瓶颈,需要进行数据分片。
复制
数据库分类:
- 主数据库:可读可写,数据变化时会自动将数据同步给从数据库
- 从数据库:只读,接收主数据库同步来的数据
搭建集群相关命令/配置
# --port 指定redis端口
# --slaveof 指定主数据库的ip和端口
$ redis-server --port 6380 --slaveof 127.0.0.1 6379
# 查看集群信息
> INFO replication
# 运行时修改主数据库
> SLAVEOF 127.0.0.1 6379
# 从数据库转换成主数据库
> SLAVEOF NO ONE
# redis.conf
# 配置从数据库可写
slave-read-only no
# 集群同步过程中,默认情况下,从数据库会用同步前的数据对客户端响应,但也可以配置其阻塞
slave-serve-stale-data no
# 乐观复制策略的配置项
# 允许从数据库最长失去连接的时间(默认注释的配置)
min-slaves-max-log 10
# 仅当在线的从数据库达到的配置的数量后,主数据库才可写(默认注释的配置)
min-slaves-to-write 3
# 增量复制的配置项
# 积压队列大小
repl-backlog-size
# 所有从数据库与主数据库断开连接后,经过多长时间释放积压队列的内存空间
repl-backlog-ttl
原理
复制初始化:
- 从数据库启动后,会向主数据库发送SYNC命令
- 主数据库接收到SYNC后,在后台保存快照(RDB持久化),并将快照保存过程中接收到的命令缓存起来
- 快照完成后,主数据库将快照和缓存的命令发给从数据库
- 从数据库接收到快照和命令后,载入快照并执行缓存命令
复制同步:
- 初始化结束后,主数据库执行的任何改变数据的命令都会异步发给从数据库
复制策略:乐观复制策略
- 容忍一定时间内主从数据库的数据差异,但最终的数据是一致的
断线重连:
- 2.6版本及之前的版本,无论数据差异多大,都会做复制初始化,效率低
- 2.8版本及之后的版本,增加了
增量复制
,大大提高了效率
增量复制:
- 实现前提
- redis每次启动都会生成一个新的运行ID
- 复制同步阶段,主数据库每次同步命令给从数据库,都会将命令放入一个积压队列中,并记录当前积压队列中存放的命令的偏移量范围
- 从数据库接收到主数据库传来的命令时,会记录该命令的偏移量
- 增量复制过程:
- 主数据库会判断从数据库发来的运行ID是否和自己的运行ID相同
- 判断从数据库最后同步成功的偏移量是否在积压队列中,如果在则可以执行增量复制,将积压队列中的命令发给从数据库,否则,只能执行全量复制
从数据库持久化
由于持久化的过程相对耗时,为了提高性能,一般来说,从数据库会开启持久化,主数据库会禁用持久化。当从数据库崩溃重启后,主数据库会自动将数据同步过来,无需担心数据丢失。然而,当主数据库崩溃时,情况就变得复杂了,需要人工干预:
- 在从数据库中使用 SLAVEOF NO ONE 命令将从数据库提升成主数据库继续服务
- 启动之前崩溃的主数据库,然后使用 SLAVEOF 命令将其设置成新的主数据库的从数据库,即可将数据同步回来
手工维护从数据库或主数据库的重启以及数据恢复都比较麻烦,万幸,redis(2.8版本)为此提供了哨兵2.0来解决这一问题。
附录
# 积压队列大小计算方式
估计主从数据库断线的时间中主数据可能执行的命令的大小
参考
本文参考自李子骅老师的《Redis 入门指南》