标签归档:bgsave

重启redis时没有用root用户,结果dump.rdb文件停止更新,bgsave命令报错

原因:
1.dump.rdb文件所在的文件夹权限没有开通导致dump.rdb文件停止更新此时修改redis数据时会报错原因是默认配置 stop-writes-on-bgsaveerror yes当bgsave出错时数据将不能修改如下操作后可以更新数据: config set stop-writes-on-bgsaveerror nodump.rdb文件也恢复更新
2.当redis的内存占用比较大时在上述操作后dump.rdb文件仍然停止更新并且slave服务器也不能同步原因是操作系统的vm.overcommit_memory配置(配置说明在最后)如下操作:
echo 1 > /proc/sys/vm/overcommit_memory
后dump.rdb文件恢复更新。slave也可以同步数据了。
3.当使用root用户启动redis时没有上述问题

vm.overcommit_memory 表示内核在分配内存时候做检查的方式。这个变量可以取到0,1,2三个值。对取不同的值时的处理方式都定义在内核源码 mm/mmap.c 的 __vm_enough_memory 函数中。
取 1 的时候 : 此时宏为 OVERCOMMIT_ALWAYS函数直接 return 0分配成功。
取 2 的时候:  此时宏为 OVERCOMMIT_NEVER内核计算:内存总量×vm.overcommit_ratio/100+SWAP 的总量如果申请空间超过此数值则分配失败。vm.overcommit_ratio 的默认值为50。
取 0 的时候: 此时宏为 OVERCOMMIT_GUESS内核计算:NR_FILE_PAGES 总量+SWAP总量+slab中可以释放的内存总量如果申请空间超过此数值则将此数值与空闲内存总量减掉 totalreserve_pages(?) 的总量相加。如果申请空间依然超过此数值则分配失败。
以上为粗略描述在实际计算时如果非root进程则在计算时候会保留3%的空间而root进程则没有该限制。详细过程可看源码。

Redis Bgrewriteaof 命令 – 异步执行一个 AOF(AppendOnly File) 文件重写操作

Redis Bgrewriteaof 命令用于异步执行一个 AOF(AppendOnly File) 文件重写操作。重写会创建一个当前 AOF 文件的体积优化版本。

即使 Bgrewriteaof 执行失败,也不会有任何数据丢失,因为旧的 AOF 文件在 Bgrewriteaof 成功之前不会被修改。

注意:从 Redis 2.4 开始, AOF 重写由 Redis 自行触发, BGREWRITEAOF 仅仅用于手动触发重写操作。

语法

redis Bgrewriteaof 命令基本语法如下:

	
  1. redis 127.0.0.1:6379> BGREWRITEAOF

可用版本

>= 1.0.0

返回值

反馈信息。

实例

	
  1. redis 127.0.0.1:6379>
  2. Background append only file rewriting started

Redis Save 与 BGSAVE 的区别

一,save保存数据到磁盘的方式:

Redis Save 命令执行一个同步保存操作,将当前 Redis 实例的所有数据快照(snapshot)以 RDB 文件的形式保存到硬盘。

语法
redis Save 命令基本语法如下:

redis 127.0.0.1:6379> SAVE

返回值

保存成功时返回 OK 。

 

二,BGSAVE保存数据到磁盘的方式:

BGSAVE 命令执行之后立即返回 OK ,然后 Redis fork 出一个新子进程,原来的 Redis 进程(父进程)继续处理客户端请求,而子进程则负责将数据保存到磁盘,然后退出。

客户端可以通过 LASTSAVE 命令查看相关信息,判断 BGSAVE 命令是否执行成功。

 

时间复杂度:

O(N), N 为要保存到数据库中的 key 的数量。

案例:

redis> BGSAVE
Background saving started

 

 

三,结论

SAVE  保存是阻塞主进程,客户端无法连接redis,等SAVE完成后,主进程才开始工作,客户端可以连接

BGSAVE  是fork一个save的子进程,在执行save过程中,不影响主进程,客户端可以正常链接redis,等子进程fork执行save完成后,通知主进程,子进程关闭。很明细BGSAVE方式比较适合线上的维护操作,两种方式的使用一定要了解清楚在谨慎选择。

1.Master写内存快照,save命令调度rdbSave函数,会阻塞主线程的工作,当快照比较大时对性能影响是非常大的,会间断性暂停服务,所以Master最好不要写内存快照。

 

2.Master AOF持久化,如果不重写AOF文件,这个持久化方式对性能的影响是最小的,但是AOF文件会不断增大,AOF文件过大会影响Master重启的恢复速度。

 

3.Master调用BGREWRITEAOF重写AOF文件,AOF在重写的时候会占大量的CPU和内存资源,导致服务load过高,出现短暂服务暂停现象。

下面是我的一个实际项目的情况,大概情况是这样的:一个Master,4个Slave,没有Sharding机制,仅是读写分离,Master负责写入操作和AOF日志备份,AOF文件大概5G,Slave负责读操作,当Master调用BGREWRITEAOF时,Master和Slave负载会突然陡增,Master的写入请求基本上都不响应了,持续了大概5分钟,Slave的读请求过也半无法及时响应,Master和Slave的服务器负载图如下:

 

Master Server load:

 

Slave server load: 

 

上面的情况本来不会也不应该发生的,是因为以前Master的这个机器是Slave,在上面有一个shell定时任务在每天的上午10点调用BGREWRITEAOF重写AOF文件,后来由于Master机器down了,就把备份的这个Slave切成Master了,但是这个定时任务忘记删除了,就导致了上面悲剧情况的发生,原因还是找了几天才找到的。

 

no-appendfsync-on-rewrite的配置设为yes可以缓解这个问题,设置为yes表示rewrite期间对新写操作不fsync,暂时存在内存中,等rewrite完成后再写入。最好是不开启Master的AOF备份功能。

 

4.Redis主从复制的性能问题,第一次Slave向Master同步的实现是:Slave向Master发出同步请求,Master先dump出rdb文件,然后将rdb文件全量传输给slave,然后Master把缓存的命令转发给Slave,初次同步完成。第二次以及以后的同步实现是:Master将变量的快照直接实时依次发送给各个Slave。不管什么原因导致Slave和Master断开重连都会重复以上过程。Redis的主从复制是建立在内存快照的持久化基础上,只要有Slave就一定会有内存快照发生。虽然Redis宣称主从复制无阻塞,但由于磁盘io的限制,如果Master快照文件比较大,那么dump会耗费比较长的时间,这个过程中Master可能无法响应请求,也就是说服务会中断,对于关键服务,这个后果也是很可怕的。

 

以上1.2.3.4根本问题的原因都离不开系统io瓶颈问题,也就是硬盘读写速度不够快,主进程 fsync()/write() 操作被阻塞。

 

5.单点故障问题,由于目前Redis的主从复制还不够成熟,所以存在明显的单点故障问题,这个目前只能自己做方案解决,如:主动复制,Proxy实现Slave对Master的替换等,这个也是Redis作者目前比较优先的任务之一,作者的解决方案思路简单优雅,详情可见
Redis Sentinel design draft http://redis.io/topics/sentinel-spec

 

总结:

1.Master最好不要做任何持久化工作,包括内存快照和AOF日志文件,特别是不要启用内存快照做持久化。

2.如果数据比较关键,某个Slave开启AOF备份数据,策略为每秒同步一次。

3.为了主从复制的速度和连接的稳定性,Slave和Master最好在同一个局域网内。

4.尽量避免在压力较大的主库上增加从库

5.为了Master的稳定性,主从复制不要用图状结构,用单向链表结构更稳定,即主从关系为:Master<–Slave1<–Slave2<–Slave3…….,这样的结构也方便解决单点故障问题,实现Slave对Master的替换,也即,如果Master挂了,可以立马启用Slave1做Master,其他不变。