一、reids持久化
1、持久化的取舍和选择
(1)持久化的作用
redis所有数据保持在内存中,对数据的更新将异步地保存到磁盘上。
(2)持久化方式 RDB快照
RDB文件(二进制)
Redis创建RDB文件,启动时自带载入RDB文件
触发机制-主要三种方式
save(同步) 创建RDB 阻塞 文件策略:如存在老的RDB文件,新替换老 复杂度:O(n)
bgsave(异步) 1、basave 2、fork子进程 3、create RDB 4、bgsave successfully(异步响应客户端在fork之后)
自动 配置 secondes 900 changes 1 seconds 300 changes 10 seconds 60 changes 10000 满足任一条件
最佳配置
dbfilename dump-{$port}.rdb
dir /bigdiskpath
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
- RDB是Redis内存到硬盘的快照,用于持久化
- save通常会阻塞Redis
- bgsave不会阻塞Redis,但是会fork新进程
- save自动配置满足任一就会被执行
(3)持久化方式 AOF 写日志
RDB的现存问题:耗时耗性能
三种策略:
always 写命令刷新的缓冲区 每条命令 fsync到硬盘 优点 不丢数据 缺点 IO开销大
everysec 写命令刷新缓冲区,每秒把缓冲区 fsync到硬盘 优点 IO开销可控 缺点 丢失一秒数据
no 写命令到缓冲区 OS决定fsync到硬盘 优点 不用管 缺点 不可空
推荐 everysec
AOF重写:
- 减少硬盘占用量
- 加速恢复速度
AOF 重写实现的两种方式 bgrewriteof AOF重写配置
重写配置 auto-aof-rewrite-min-size AOF文件重写需要的尺寸 auto-aof-rewrite-percentage AOF文件增长率
aof_current_size AOF当前尺寸 aof_base_size AOF上次启动和重写的尺寸
同时满足 自动出发机制
aof_current_size > auto-aof-rewrite-min-size
aof_current_size - aof_base_size/aof_base_size > auto-aof-rewrite-percentage
推荐配置
appendonly yes
appendfilename "appendonly-${port}.aof"
appendfsync everysec
dir /bigdiskpath
no-appendfsync-on-rewrite yes
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
(4)RDB和AOF的抉择
RDB 启动优先级
命令 | RDB | AOF |
---|---|---|
启动优先级 | 低 | 高 |
体积 | 小 | 大 |
恢复速度 | 快 | 慢 |
数据安全性 | 丢数据 | 根据策略决定 |
轻重 | 重 | 轻 |
- RDB最佳策略
关 集中管理 主关从开
AOF最佳策略
开:缓存和存储 AOF重写集中管理 everysec
最佳策略
小分片 缓存或者存储 监控(硬盘、内存、负载、网络) 足够的内存
2、fork子进程的开销和优化
(1)fork操作
fork特性
- 同步操作
- 与内存量息息相关:内存越大,耗时越长
- info: latestt_fork_usec
改善fork
- 有限使用物理机或者搞笑支持fork操作的虚拟化计数
- 控制redis实例最大可用内存:maxmemory
- 合理配置Linux内存分配策略:vm.overcommit_memory=1
- 降低fork频率
(2)子进程开销和优化
CPU
开销:RDB和AOF文件生成,属于CPU密集型
优化:不做CPU绑定,不和CPU密集型部署
内存
开销:fork内存开销,copy-on-write
优化:echo never > /sys/kernel/mm/transparent_hugepage/enable
硬盘
开销:AOF和RDB文件写入,可以结合iostat,iotop分析
优化:不要和高硬盘负载服务部署一起:存储服务,队列服务等 no-appendfsync-on-rewrite=yes
根据写入量决定磁盘类型 单机多实例持久化目录可以考虑分盘
(3)AOF追加阻塞
阻塞定位:Redis日志 info Persistence
二、Redis的主从复制原理
1、redis的复制
单机的问题:机器故障 容量瓶颈 QPS瓶颈
主从复制的作用:数据副本 扩展读性能
- 一个master可以有多个slave
- 一个slave只能有一个master
- 数据流向是单向的,master到slave
实现方式:slaveof命令 配置
命令实现:slaveof 127.0.0.1 6379 复制 slaveof no one 取消复制
修改配置:
slaveof ip port
slave-read-only yes
比较
方式 | 命令 | 配置 |
---|---|---|
优点 | 不需要重启 | 统一配置 |
缺点 | 不便于管理 | 需要重启 |
info replaction 查看主从复制的信息
2、redis的全量复制和部分复制
run_id:redis每次启动的时候都会有一个随机的id来保障redis的标识,重启后消失
复制偏移量:master_repl_offset 记录写入了多少字节
全量复制:psync -> fullresync -> save masterInfo -> bgsave -> send RDB -> send buffer -> flush old data -> load RDB
全量复制的开销:bgsave的时间 RDB文件网络传输时间 从节点清空数据时间 从节点加载RDB时间 可能AOF重写时间
部分复制:connection lost -> master -> connection to master -> psync -> continue
3、redis的故障处理
主从结构故障转移:slave宕掉 客户端重新连接另一个slave master宕掉 使用sentinel自动故障转移
开发运维中的问题:
- 读写分离:流量分摊到从节点
可能遇到的问题: 复制数据延迟 读到过期数据 从节点故障
- 主从配置不一致:
例如maxmemory不一致,丢失数据;例如数据结构优化参数,内存不一致
- 规避全量复制
第一次全量复制,不可避免 小主节点,低峰
节点运行ID不匹配 主节点重启 故障转移,例如哨兵或集群
复制积压缓冲区不足 网络中断,部分复制无法满足 增大复制缓冲区配置rel_backlog_size,网络增加
- 规避复制风暴
单节点复制风暴 主节点重启,多从节点复制 更换复制拓补
单机器复制风暴 机器宕机后,大量全量复制 主节点分散多机器
二、Redis的高可用sentinel
1、redis sentinel的架构
主从复制的问题:手动故障转移 写能力和存储能力受限
- 客户端从sentinel获取redis信息
- redis sentinel故障转移
- 多个sentinel发现并确认master有问题
- 选举出一个sentinel作为领导
- 选出一个slave作为master
- 通知其余slave作为新的master的slave
- 通知客户端主从变化
- 等待心动额master复活成为新的master的slave
2、redis sentinel的安装和配置
- 配置并开启主从节点
- 配置并开启sentinel监控主节点。(sentinel是特殊的redis)
- 多机器
- 详细配置节点
主节点
port 7000
daemonize yes
pidfile /var/run/redis-7000.pid
logfile "7000.log"
dir "/opt/soft/redis/data/"
从节点
port 7001
daemonize yes
pidfile /var/run/redis-7000.pid
logfile "7000.log"
dir "/opt/soft/redis/data/"
slaveof 127.0.0.1 7000
sentinel主要配置
port ${port}
daemonize yes
dir "/opt/soft/redis/data/"
logfile "${port}.log"
sentinel monitor mymaster 127.0.0.1 7000 2
sentinel down-after-milliseconds mymaster 300000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
客户端接入流程
Sentinel地址集合 =》 mastername =》 不是代理模式
3、redis 高可用实现
客户端高可用观察
服务端日志分析:数据节点和Sentinel节点
三个定时任务
(1)、每10秒每个sentinel对master和slave执行info
- 发现每个slave节点
- 确认主从关系
(2)、每2秒每个sentinel通过master节点的channel交换信息(pub/sub)
- 通过__sentinel__:hello频道交互
- 交互节点的看法和自身信息
(3)、每1秒每个sentinel对其他sentinel和redis执行ping
- 心跳检测,失败判定依据
a、主观下线和客观下线
主观下线:每个sentinel节点对Redis节点失败的偏见
客观下线:所有sentinel节点对Redis节点失败达成共识
b、领导者选举
原因:只要一个sentinel节点完成故障转移
选举:通过sentinel is-master-down-by-addr命令都希望成为领导者
- 每个主观下线的sentinel节点向其他sentinel节点发送命令,要求将它设置成为领导者
- 收到命令的sentinel节点如果没有同意通过其他Sentinel节点发送的命令,那么就将同意该请求,否则拒绝
- 如果该sentinel节点发现自己的票数已经超过sentinel集合半数,并且超过quorum,那么它将成为领导者
- 如果过程中有多个sentinel节点成为了领导者,那么将等待一段时间重新进行选举
c、故障转移
- 从slave节点中选出一个合适的节点作为新的master节点
- 从上面的slave节点执行slaveof no one 命令让其成为master节点
- 向剩余的slave节点发送命令,让他们成为新的master节点的slave节点,复制规则和parallel-syncs参数有关
- 更新对原来的master节点配置为slave,并保持着对其关注,当其恢复后命令让他取复制新的master节点
选择合适的slave节点
选择slave-pripority最高的slave节点,如果存在则返回,不存在则继续
选择复制偏移量将达的slave节点,如果存在则返回,不存在则继续
选择runId最小的节点
4、redis 高可用实战
(1)、节点运维
机器下线:例如过保等情况
机器性能不足:例如CPU、内存、硬盘、网络等
节点自身故障:例如服务不稳定
从节点:临时下线还是永久下线,例如是否做一些清理工作,但是要考虑读写分离的情况
主节点:sentinel failover进行替换
(2)、高可用读写分离
从节点的作用
副本:高可用的基础
扩展:读能力
Redis Sentinel是Redis的高可用实现方案
- 故障发现、故障自动转移、配置中心、客户端通知
- Redis Sentinel从Redis2.8才开始正式生成可用
- 尽可能在不同物理机上部署Redis Sentinel的节点
- RedisSentinel中的Sentinel节点个数应该大于等于3,且最好为奇数
- Redis Sentinel中的数据节点与普通数据节点没有区别
- 客户端初始化时连接的时Sentinel节点集合,不再是具体的Redis节点,但Sentinel只是配置中心不是代理
- Redis Sentinel通过三个定时任务实现了Sentinel节点对于主节点、从节点、其余Sentinel节点的监控
- Redis Sentinel在对节点做失败判定时分为主观下线和客观下线
- 看懂Redis Sentinel故障转移日志对于Redis Sentinel以及问题排查非常有帮助
- Redis Sentinel实现读写分离高可用可以依赖Sentinel节点的消息通知,获取Redis数据节点的状态变化
三、Redis的高可用 Cluster
1、呼唤集群
并发量超过10万QPS,数据量超过单机内存
解决方法:分布式(简单的认为加机器)
顺序分区:1-100 =》 1-33,34-66,67-100
哈希分区:1-100 =》 hash(key)%3 0,1,2
哈希分布分为 节点取余分区,一致性哈希分区,虚拟槽分区
(1)节点取余分区,添加一个节点 迁移率80%,多倍扩容迁移率50%
客户端分片:哈希+取余
节点伸缩:数据节点关系变化,导致数据迁移
迁移数量和添加节点数量有关:建议翻倍扩容
(2)一致性哈希
客户端分片:哈希+顺时针(优化取余)
节点伸缩:只影响临近节点,但是还是有数据迁移
翻倍伸缩:保证最小数据迁移和负载均衡
(3)虚拟槽分区
预设虚拟槽:每个槽映射一个数据子集,一般比节点数大
良好的哈希函数:CRC16
服务端管理节点:槽,数据
2、基本架构
Redis Cluster架构: 节点 meet 指派槽 复制 高可用 分片
(1)安装配置
配置开启节点 =》 meet =》 指派槽 =》 主从
port ${port}
daemonize yes
dir "/opt/redis/redis/data"
dbfilename "dump-${port}.rdb"
logfile "${port}.file"
cluster-enabled yes
cluster-config-file nodes-${port}.conf
cluster-require-full-coverage no
cluster meet ip port
Cluster节点主要配置
cluster-enabled yes
cluster-node-timeout 15000
cluster-config-file "nodes.conf"
cluster-require-full-coverage yes
分配槽: cluster addslots slot
设置主从:cluster replicate node-id
(2)redis-trib安装
下载编译安装Ruby => 安装rubygem redis => 安装redis-trib.rb
配置开启Redis
一键开启:./redis-trib.rb create --replicas 1 127.0.0.1:8000 127.0.0.1:8001...
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。