一、RDB的问题
1. 耗时耗性能:
1)一次性将内存中的数据全部dump到硬盘的一个文件里
2) fork() 子线程耗内存,copy-on-write策略。
3)IO
2. 不可控,容易丢失数据
时间戳 | save |
---|---|
T1 | 执行多个写命令 |
T2 | 满足RDB自动创建的条件 |
T3 | 再次执行多个写命令 |
T4 | 宕机 (T3的多个命令产生的数据都丢了) |
二、什么是AOF
AOF 是Append Only File的缩写:向文件中追加命令。
三、AOF三种策略
appendfsync always 每条命令都会写入AOF文件。IO开销大,SATA硬盘只有几百TPS
#每秒都刷到硬盘中在高写入量的时候适当地保护硬盘,但是可能造成数据丢失
appendfsync everysec
appendfsync no 不用管,由OS决定什么时候刷新到硬盘中,不可控
四、AOF重写
随着命令的逐渐写入,时间的逐步推移,并发量的变大,AOF文件也会越来越大,此时用AOF恢复数据的话会变慢。
原生AOF | 重新AOF |
---|---|
set hello world set hello java set hello here |
mset hello world java here |
incr counter incr counter ... |
set counter 10000 0000 |
rpush mylist a rpush mylist b rpush mylist c |
rpush mylist a b c |
过期数据 | 删除过期数据 |
通过化简AOF文件,减少硬盘占用量,加速恢复速度
AOF 实现重新的两种方式
1. bgrewriteaof命令
异步执行,fork子进程,OK结果
2.AOF 自动重写配置
配置名称 | 含义 |
---|---|
auto-aof-rewrite-percentage 100 | AOF文件增长率(第一次64m,第二次128m ...) |
auto-aof-rewrite-min-size 64mb | AOF重写需要的尺寸 |
appendonly no # 开启AOF
appendfilename "appendonly-${port}.aof" # 生成的AOF文件名
appendfsync everysec #AOF 策略,默认每秒AOF一次
# AOF重写时不向AOF文件追加新的命令(流程3-2,5-2 ❌掉),no数据会丢失
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100 # 增长率
auto-aof-rewrite-min-size 64mb # 最小需要重写的尺寸
RDB与AOF对比
对比项 | RDB | AOF |
---|---|---|
启动优先级(同时开启) | 低 | 高 |
体积 | 小 | 大 |
恢复速度 | 快 | 慢 |
数据安全性 | 丢数据 | 根据策略决定 |
轻重 | 重 | 轻 |
RDB最佳策略
策略 | 说明 |
---|---|
“关” | 主从复制中的全量复制是需要主节点执行一次bgsave 然后把RDB文件传给从节点 |
集中管理 | 按天、小时、星期备份的话,RDB是一个不错的选择。 |
主从,从开? | 从备份,注意性能 |
AOF最佳策略
策略 | 说明 |
---|---|
“开” :缓存和存储 | 缓存场景:完全拿Redis当缓存,即便数据丢了也无所谓, 只需要下次加载的时候从数据源重新加载进Redis即可。 访问本身对数据源的压力没多大,缓存只是起到一定的缓存作用, 这个时候可以不用AOF。毕竟AOF相较于RDB有一定开销。 |
AOF重写集中管理 | 单机多部署的情况下,如果AOF重写集中发生,可能内存爆满,产生故障。(发生大量的fork()产生很多子进程),一般机器内存会分配60% ~ 70%左右 给Redis做缓存,剩余20% ~ 30%+ 的内存给fork。 |
everysec | 建议使用 |
小分片 | 使用maxMemory对Redis进行规划。eg: 4G。 这使得fork()、RDB传输 产生较小的开销。 但在分布式情况下产生更多的Redis进程,对CPU占用多 |
监控 | 硬盘、内存、负载、网络 (根据监控信息调整redis配置) |
内存足够 | 内存要多 |
开发运维常见问题
1. fork操作
1)同步操作:synchronized,慢的话会阻塞Redis主进程
2)内存页的拷贝,而不是完全内存的拷贝
3)与内存量息息相关:内存越大,耗时越长(与机器类型有关,VM慢,物理机快)
4)info:latest_fork_usec
改善fork
- 优先使用物理机或者高效支持fork操作的虚拟化技术
- 控制Redis实例最大可用内存:maxmemory
- 合理配置Linux内存分配策略:vm.overcommit_memory=1
- 降低fork频率:例如放宽AOF重新自动触发时机,不必要的全量复制
2. 进程外开销 (子进程开销和优化):偏运维调优
1. CPU :
- 开销:RDB和AOF文件生成,属于CPU密集型
- 优化:不做CPU绑定(与父进程抢CPU不好),不和CPU密集型应用一起部署。
2. 内存
- 开销: fork内存开销,。理论上消耗父进程同等大小内存。但是Linux有 copy-on-write机制:父子进程共享共同的物理内存页。但是当父进程有写请求的时候会创建副本,这时候才会消耗一个内存,而整个期间父子进程共享内存快照。AOF重写和
- 优化:
3. 硬盘
- 开销:AOF和RDB文件写入,可以结合iostat 和 iotop分析
- 优化:1.不要和高硬盘负载的服务部署在一起:存储服务,消息队列等
- no-appendfsync-on-rewrite = yes
- 根据写入量决定磁盘类型:eg:ssd等
- 单机多实持久化文件目录可以考虑分盘
3. AOF追加阻塞
4. 单机多部署实例
AOF追加阻塞流程图AOF阻塞定位
- 查看Redis日志文件
Asynchronous AOF fsync is taking too long (disk is busy ?)
Writing AOF buffer without wating for fsync to complete
this may slow down Redis.
- 命令:$info persistence
127.0.0.1:6379> info persistence
# Persistence
loading:0
rdb_changes_since_last_save:0
rdb_bgsave_in_progress:0
rdb_last_save_time:1557920803
rdb_last_bgsave_status:ok
rdb_last_bgsave_time_sec:-1
rdb_current_bgsave_time_sec:-1
rdb_last_cow_size:0
aof_enabled:1
aof_rewrite_in_progress:0
aof_rewrite_scheduled:0
aof_last_rewrite_time_sec:-1
aof_current_rewrite_time_sec:-1
aof_last_bgrewrite_status:ok
aof_last_write_status:ok
aof_last_cow_size:0
aof_current_size:211
aof_base_size:211
aof_pending_rewrite:0
aof_buffer_length:0
aof_rewrite_buffer_length:0
aof_pending_bio_fsync:0
aof_delayed_fsync:0 #此项为:历史累加的阻塞次数。无法查看某段时间内的次数
127.0.0.1:6379>
网友评论