主从复制高可用Redis集群
# 缓存方案对比
EhCache | memcached | Redis | |
---|---|---|---|
优点 | 基于java开发,与java项目的整合度更好;基于jvm缓存;轻巧方便 | kv存储;多核多线程;内存使用率高; | 丰富的数据结构;持久化;主从同步,故障转移;内存数据库; |
缺点 | 不支持集群,分布式支持不友好, | 无法容灾,数据无法持久化; | 单线程、单核; |
适合场景 | 适合单体应用,并发量较小的场景 | 适合缓存热数据 | 适合缓存、有存储需求的 |
# Redis架构与原理解析

多路复用:redis的多路复用器是是同步非阻塞模型,可以高效的处理多个客户端的连接,通过将请求投递到队列
文件事件分配器:通过从队列读取消息,分发到连接应答器
连接应答器:读取事件分配器分发的任务,递交命令请求处理器处理
# 持久化
redis通过持久化来保证数据的可靠性,主要包括rdb和aof两种方式;
# RDB
每隔一段时间,通过将内存中的数据作为快照存储到磁盘的临时文件,发生宕机的时候,读取磁盘快照的方式来恢复数据。
# 优缺点
优点 | 缺点 |
---|---|
数据的全量备份 | 发生故障时,会丢失最后一次的备份数据 |
数据作为文件,可以远程传输 | 子进程所占用的内存比会和父进程一模一样,如会造成CPU负担 |
子进程备份的时候,主进程不会有任何io操作(不会有写入修改或删除),保证备份数据的的完整性 | 由于定时全量备份是重量级操作,所以对于实时备份,就无法处理了 |
# 配置
save 9000 1 # 如果1个缓存更新,则15分钟后备份
save 300 10 # 如果10个缓存更新,则5分钟后备份
2
# AOF
RDB会丢失最后一次备份的rdb文件,但是其实也无所谓,其实也可以忽略不计,毕竟是缓存,丢了就丢了,但是如果追求数据的完整性,那就考虑使用AOF,aof有如下的特点:
- 以日志的形式来记录用户请求的写操作。读操作不会记录,因为写操作才会存存储;
- 文件以追加的形式而不是修改的形式;
- redis的aof恢复其实就是把追加的文件从开始到结尾读取执行写操作;
# 优缺点
优点 | 缺点 |
---|---|
AOF更加耐用,可以以秒级别为单位备份,如果发生问题,也只会丢失最后一秒的数据,大大增加了可靠性和数据完整性。所以AOF可一次使用fsync操作 | 相同的数据,同一份数据,AOF比RDB大 |
以log日志形式追加,如果磁盘满了,会执行 redis-check-aof 工具 | 针对不同的同步机制,AOF会比RDB慢,因为AOF每秒都会备份做写操作,这样相对与RDB来说就略低。每秒备份fsync没毛病,但是每次写入就做一次备份fsync的话,那么redis的性能就会下降 |
当数据太大的时候,redis可以在后台自动重写aof。当redis继续把日志追加到老的文件中去时,重写也是非常安全的,不会影响客户端作 | AOF发生过bug,就是数据恢复的时候数据不完整,这样显得AOF会比较脆弱,容易出现bug,因为AOF没有RDB那么简单,但是呢为的产生,AOF就不会根据旧的指令去重构,而是根据当时缓存中存在的数据指令去做重构,这样就 |
AOF 日志包含的所有写操作,会更加便于redis的解析恢复 |
# 配置
# AOF默认关闭,yes可以开启
appendonly no
# AOF的文件名
append filename "appendonly.aof"
# no:不同步
# everysec:每秒备份,推荐使用
# always:每次操作都会备份,安全并且数据完整,但是慢性能差
appendf sync everysec
# 重写的时候是否要同步,no可以保证数据安全
no-appendfsync-on-rewrite no
# 重写机制:避免文件越来越大,自动优化压缩指令,会fork一个新的进程去完成重写动作,新进程里的内存数据会被重写
#当前AOF文件的大小是上次AOF大小的100%,并且文件体积达到64m,满足两者则触发重写
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
2
3
4
5
6
7
8
9
10
11
12
13
14
# 小结
到底采用RDB还是AOF呢?
- 如果你能接受一段时间的缓存丢失,那么可以使用RDB
- 如果你对实时性的数据比较care,那么就用AOF
# 主从复制
# 基本原理

主从复制架构是一主一从或者一主多从,支持主节点复制数据到从,不支持从复制到主。通过主从的形式来提高数据的处理能力。
# 同步流程
- master节点开启持久化机制
- slave节点ping master节点确认互通
- master节点内存数据落到磁盘的rdb上
- 通过内网传输到slave节点上
- slave节点下载rdb到磁盘后,加载到内存
- master节点后续新的写操作,同步传输到slave节点,slave节点更新内存数据
主从同步的时候,有以下几点注意:
- 数据同步过程中,读写不会进行阻塞,原因是由于对外提供的是老数据,数据同步完成后,会使用新数据提供服务
- slave节点宕机后,会进行增量数据恢复
- master节点必须开启持久化,否则重启后会导致数据清空
# 主从搭建
配置从节点的redis的配置
# 配置master节点的ip和端口
replicaof <master> <masterport>
# master的密码
masterauth <master-password>
# 是否只读
replica-read-only yes
2
3
4
5
6
重启redis
service redis restart
# 无磁盘化复制
主要是通过socket的方式传输rdb数据,数据不会落到磁盘上。适用于网络性能好,磁盘吞吐量较低的情况下
repl-diskless-sync yes
# 缓存清理
设置了expire的key缓存过期了,但是服务器的内存还是会被占用,这是因为redis所基于的两种删除策略:
# 主动删除
定时随机的检查过期的key,如果过期则清理删除。(每秒检查次数在redis.conf中的hz配置)
# 惰性删除
当客户端请求一个已经过期的key的时候,那么redis会检查这个key是否过期,如果过期了,则删除,然后返回一个nil
# 淘汰策略
maxmemory:当内存已使用率到达,则开始清理缓存
策略 | 说明 |
---|---|
noeviction | 旧缓存永不过期,新缓存设置不了,返回错误 |
allkeys-lru | 清除最少用的旧缓存,然后保存新的缓存(推荐使用) |
allkeys-random | 所有的缓存中随机删除(不推荐) |
volatile-lru | 在那些设置了expire过期时间的缓存中,清除最少用的旧缓存,然后保存新的缓存 |
volatile-random | 在那些设置了expire过期时间的缓存中,随机删除缓存 |
volatile-ttl | 在那些设置了expire过期时间的缓存中,删除即将过期的 |
# 哨兵模式
哨兵是由多个节点组成的,用于监控redis各个节点的状态,宕机之后选取新的master节点来保证服务的可用性。

配置哨兵
在多台机器配置哨兵,监控redis的master、slave
## 通用配置
# 关闭受保护模式,方便哨兵各个节点相互访问
protected-mode no
port 26379
daemonize yes
pidfile /var/run/redis-sentinel pid
Logfile /usr/Local/redis/sentinel/Redis-sentinel Log dir /usr/Local/redis/sentinel
## 核心配置
# 该行的意思是:监控的master的名字叫做mymaster (可以自定义),地址为192.168.1.191:6379,行尾最后的一个2代表在sentinel集群中,多少个sentinel认为master死了,才能真正认为该master不可用了。
sentinel monitor mymaster 192.168.1.191 6379 2
# 密码为redis的密码
sentinel auth-pass mymaster <password>
# master在30s内无法ping通,会被sentinel认定为失效
sentinel down-after-mitliseconds mymaster 30000
# salve节点被选取为新的master节点后,支持同时给几个salve进行数据同步
sentinel parallel-syncs mymaster 1
# 主备切换的超时时间,哨兵要去做故障转移,这个时候哨兵也是一个进程,如果他没有去执行,超过这个时间后,会由其他的哨兵负责处理
sentinel failover-timeout mymaster 180000
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
启动哨兵
/usr/local/bin/redis-sentinel sentinel.conf
哨兵信息检查
# 查看mymaster下的master节点信息
sentinel master mymaster
# 查看mymaster下的slaves节点信息
sentinel slaves mymaster
# 查看mymaster下的哨兵节点信息
sentinel sentinels mymaster
2
3
4
5
6
注:master宕机之后,重启之后,会变更为slave,这点跟keepalive的nginx的master是相反的。
master宕机后如果没有设置密码,会出现数据不一致的问题,因为没有进行auth所以无法进行数据同步。一般master数据无法同步给slave的方案检查为如下:
- 网络通信问题,要保证互相ping通,内网互通。
- 关闭防火墙,对应的端口开发(虚拟机中建议永久关闭防火墙,云服务器的话需要保证内网互通)。
- 统一所有的密码,不要漏了某个节点没有设置
# 集群原理及解决方案
主从复制以及哨兵,他们可以提高读的并发,但是单个master容量有限,数据达到一定程度会有瓶颈。这个时候可以通过水平扩展为多master集群。
redis-cluster可以支撑多个master-slave,支持海量数据,实现高可用与高并发。
哨兵模式其实也是一种集群,他能够提高读请求的并发,但是容错方面可能会有一些问题,比如master同步数据给slave的时候,slave上的数据就没有master新,数据同步需要时间的,1-2秒的数据会丢失。master恢复并转换成slave后,新数据则丢失;

# 特点
- 每个节点知道彼此之间的关系,也会知道自己的角色,当然他们也会知道自己存在于一个集群环境中,他们彼此之间可以交互和通信,那么这些关系都会保存到某个配置文件中。
- 客户端要和集群建立连接的话,只需要和其中一个建立关系就行。
- 某个节点挂了,也是通过超过半数的节点来进行的检测,客观下线后主从切换。
- Redis中存在很多的插槽,又可以称之为槽节点,用于存储数据
# 集群容错
构建Redis集群,至少需要3个节点作为master,以此组成一个高可用的集群,此外每个master都需要配备一个slave,所以整个集群需要6个节点,这也是最经典的集群,也可以称之为三主三从,容错性更佳。
# 配置
redis.conf的配置
# 开启集群模式
cluster-enabled yes
# 每一个节点需要有一个配置文件,需要6份。每个节点处于集群的角色都需要告知其他所有节点
cluster-config-file nodes-201.conf
# 超时时间,超时则认为master宕机,随后主备切换
cluster-node-timeout 5000
# 开启AOF
appendonly yes
2
3
4
5
6
7
8
启动redis的实例
# 启动过程有问题,删除rdb文件
service redis start
2
创建集群
# 新版的redis集群创建使用redis-cli,主节点和从节点比例为1
# slots:槽,用于装数据,主节点有,从节点没有
redis-cli --cluster -a <password> create ip1:port1 ip2:port2 ip3:port3 ip4:port4 ip5:port5 ip6:port6 --cluster-replicas 1
2
3
检查集群信息
redis-cli --cluster check 192.168.25.64:6380
# Slot槽节点
slot主要是用于存储redis的数据
# 分配

槽总数为16348,会被平均的分配到master的各个节点上
# 存储

集群模式下redis的key通过对key进行hash求模,最终计算得到数据落到哪个master的节点上。取数据的时候,会重定向到对应的节点上。