xiaoyi's blog
首页
  • 后端文章

    • PHP
  • 学习笔记

    • 《Git》学习笔记
  • MySQL
  • NoSQL
  • 中间件
  • Linux
  • Nginx
  • 网络
  • Mac
  • 学习笔记

    • 《Nginx》学习笔记
  • 学习
  • 博客搭建
  • 技术文档
  • GitHub技巧
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
  • 网站
  • 资源
  • 分类
  • 标签
  • 归档
GitHub

xuexuguang

后端新秀
首页
  • 后端文章

    • PHP
  • 学习笔记

    • 《Git》学习笔记
  • MySQL
  • NoSQL
  • 中间件
  • Linux
  • Nginx
  • 网络
  • Mac
  • 学习笔记

    • 《Nginx》学习笔记
  • 学习
  • 博客搭建
  • 技术文档
  • GitHub技巧
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
  • 网站
  • 资源
  • 分类
  • 标签
  • 归档
GitHub
  • MySQL

  • NoSQL

    • Redis的事务与订阅
    • 主从复制高可用Redis集群
      • 缓存方案对比
      • Redis架构与原理解析
      • 持久化
        • RDB
        • AOF
        • 小结
      • 主从复制
        • 基本原理
        • 同步流程
        • 主从搭建
      • 无磁盘化复制
      • 缓存清理
        • 主动删除
        • 惰性删除
        • 淘汰策略
      • 哨兵模式
      • 集群原理及解决方案
        • 特点
        • 集群容错
        • 配置
      • Slot槽节点
        • 分配
        • 存储
      • 参考链接
  • 数据库中间件

  • 数据库
  • NoSQL
xuexuguang
2020-12-03

主从复制高可用Redis集群

# 缓存方案对比

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

# Redis架构与原理解析

image-20201203184416514

多路复用:redis的多路复用器是是同步非阻塞模型,可以高效的处理多个客户端的连接,通过将请求投递到队列

文件事件分配器:通过从队列读取消息,分发到连接应答器

连接应答器:读取事件分配器分发的任务,递交命令请求处理器处理

# 持久化

redis通过持久化来保证数据的可靠性,主要包括rdb和aof两种方式;

# RDB

每隔一段时间,通过将内存中的数据作为快照存储到磁盘的临时文件,发生宕机的时候,读取磁盘快照的方式来恢复数据。

# 优缺点

优点 缺点
数据的全量备份 发生故障时,会丢失最后一次的备份数据
数据作为文件,可以远程传输 子进程所占用的内存比会和父进程一模一样,如会造成CPU负担
子进程备份的时候,主进程不会有任何io操作(不会有写入修改或删除),保证备份数据的的完整性 由于定时全量备份是重量级操作,所以对于实时备份,就无法处理了

# 配置

save 9000 1 # 如果1个缓存更新,则15分钟后备份
save 300 10 # 如果10个缓存更新,则5分钟后备份
1
2

# AOF

RDB会丢失最后一次备份的rdb文件,但是其实也无所谓,其实也可以忽略不计,毕竟是缓存,丢了就丢了,但是如果追求数据的完整性,那就考虑使用AOF,aof有如下的特点:

  1. 以日志的形式来记录用户请求的写操作。读操作不会记录,因为写操作才会存存储;
  2. 文件以追加的形式而不是修改的形式;
  3. 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
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 小结

到底采用RDB还是AOF呢?

  1. 如果你能接受一段时间的缓存丢失,那么可以使用RDB
  2. 如果你对实时性的数据比较care,那么就用AOF

# 主从复制

# 基本原理

image-20201214113835998

主从复制架构是一主一从或者一主多从,支持主节点复制数据到从,不支持从复制到主。通过主从的形式来提高数据的处理能力。

# 同步流程

  1. master节点开启持久化机制
  2. slave节点ping master节点确认互通
  3. master节点内存数据落到磁盘的rdb上
  4. 通过内网传输到slave节点上
  5. slave节点下载rdb到磁盘后,加载到内存
  6. master节点后续新的写操作,同步传输到slave节点,slave节点更新内存数据

主从同步的时候,有以下几点注意:

  • 数据同步过程中,读写不会进行阻塞,原因是由于对外提供的是老数据,数据同步完成后,会使用新数据提供服务
  • slave节点宕机后,会进行增量数据恢复
  • master节点必须开启持久化,否则重启后会导致数据清空

# 主从搭建

配置从节点的redis的配置

# 配置master节点的ip和端口
replicaof <master> <masterport>
# master的密码
masterauth <master-password>
# 是否只读
replica-read-only yes
1
2
3
4
5
6

重启redis

service redis restart
1

# 无磁盘化复制

主要是通过socket的方式传输rdb数据,数据不会落到磁盘上。适用于网络性能好,磁盘吞吐量较低的情况下

repl-diskless-sync yes
1

# 缓存清理

设置了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节点来保证服务的可用性。

image-20201215102752537

配置哨兵

在多台机器配置哨兵,监控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
1
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 
1

哨兵信息检查

# 查看mymaster下的master节点信息
sentinel master mymaster
# 查看mymaster下的slaves节点信息
sentinel slaves mymaster
# 查看mymaster下的哨兵节点信息
sentinel sentinels mymaster
1
2
3
4
5
6

注:master宕机之后,重启之后,会变更为slave,这点跟keepalive的nginx的master是相反的。

master宕机后如果没有设置密码,会出现数据不一致的问题,因为没有进行auth所以无法进行数据同步。一般master数据无法同步给slave的方案检查为如下:

  1. 网络通信问题,要保证互相ping通,内网互通。
  2. 关闭防火墙,对应的端口开发(虚拟机中建议永久关闭防火墙,云服务器的话需要保证内网互通)。
  3. 统一所有的密码,不要漏了某个节点没有设置

# 集群原理及解决方案

主从复制以及哨兵,他们可以提高读的并发,但是单个master容量有限,数据达到一定程度会有瓶颈。这个时候可以通过水平扩展为多master集群。

redis-cluster可以支撑多个master-slave,支持海量数据,实现高可用与高并发。

哨兵模式其实也是一种集群,他能够提高读请求的并发,但是容错方面可能会有一些问题,比如master同步数据给slave的时候,slave上的数据就没有master新,数据同步需要时间的,1-2秒的数据会丢失。master恢复并转换成slave后,新数据则丢失;

image-20201215142517282

# 特点

  1. 每个节点知道彼此之间的关系,也会知道自己的角色,当然他们也会知道自己存在于一个集群环境中,他们彼此之间可以交互和通信,那么这些关系都会保存到某个配置文件中。
  2. 客户端要和集群建立连接的话,只需要和其中一个建立关系就行。
  3. 某个节点挂了,也是通过超过半数的节点来进行的检测,客观下线后主从切换。
  4. 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
1
2
3
4
5
6
7
8

启动redis的实例

# 启动过程有问题,删除rdb文件
service redis start
1
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
1
2
3

检查集群信息

redis-cli --cluster check 192.168.25.64:6380
1

# Slot槽节点

slot主要是用于存储redis的数据

# 分配

image-20201216102449247

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

# 存储

image-20201216102613004

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

# 参考链接

  • Linux IO模式及 select、poll、epoll详解
  • Redis的持久化详解
  • 主从模式
  • Redis哨兵模式的安装
  • laravel集成哨兵模式
  • Redis Cluster及hash slot 算法
  • Redis 缓存雪崩、击穿、穿透
  • 看完这篇Redis缓存三大问题,保你面试能造火箭,工作能拧螺丝
编辑
上次更新: 2020/12/31, 06:55:18
Redis的事务与订阅

← Redis的事务与订阅

最近更新
01
MVC对比
12-31
02
负载均衡
12-31
03
数据库缓存优化
12-31
更多文章>
Theme by Vdoing | Copyright © 2020-2020 Evan Xu | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式