请注意,虽然这个问题有点Redis的具体问题,但主要问题是通用的: 一个进程需要这么多的硬盘IO写带宽,其他进程不能写任何东西 。
我们在基于Ubuntu的Xen XCP主机中安装了一个Ubuntu VM(安装在两个硬盘上的软件RAID1中)。 该虚拟机在大约2K命令/秒的负载下运行Redis服务器。
问题:当所述Redis服务器执行BGREWRITEAOF ,它将阻塞其客户端大约10秒钟。
细节:
只有AOF持久性被使用,没有RDB。 Redis被configuration为每秒一次fsync AOF文件。
在BGREWRITEAOF Redis分支上执行subprocess中的所有磁盘密集型工作。 同时,主进程不断追加数据到它的AOF文件。
BGREWRITEAOF大约需要10秒钟(1.5GB的数据,150MB / s的磁盘写入速度)。 进行重写的subprocess消耗所有HDD IO写入吞吐量。
父进程尝试fsync ,需要超过两秒的时间,数据保护启动,并阻止write被调用,阻塞父进程,直到BGREWRITEAOF完成磁盘。
这是一个详细的信息和讨论 ,导致我上面的事件解释。
问题:对我来说,一个进程被允许占用太多磁盘IO以至于其他所有内容都被阻塞。 有什么我可以在系统级别上解决这个问题吗? 如果BGREWRITEAOF需要多一点时间,只要允许父进程在重写处于活动状态时保存其数据,那么我就行了。
请注意,我知道解决方法,如移动AOF持久性到奴隶,使用no-appendfsync-on-rewrite Redisconfiguration选项等; 这个问题是专门解决问题,而不是解决问题。
AFAICS您可以尝试更改IO调度程序。 尝试使用这个命令:
echo cfq > /sys/block/$DEVICE/queue/scheduler
$ DEVICE是您的RAID1磁盘。 此命令为您的设备安装“完全公平队列”调度程序。
我会build议改变你的I / O调度器,并应用一些调光技术。 虽然我没有一个全面的调整指南,但是这个问题中的一些答案和build议也可以帮助你。
考虑将I / O电梯更改为截止时间或noopalgorithm,然后重新testing。 您可以使用另一个答案中详细描述的技术来实现这个更改。 向GRUB内核命令添加一个条目,使其在重新启动时保持不变(add: elevator=deadline )
也许关于底层硬件或主机系统设置的一些细节将有所帮助。 存储子系统上是否有电池供电或闪存支持的写入caching? 这可以有所作为 。
最后,你可以尝试一些简单的基准testing/监测工具,看看发生了什么。 例如,如果您有权访问iostat ,则可以在testing应用程序时在另一个terminal窗口中运行它。
例如, iostat -x 1将以1秒的采样运行,并提供读/写速度和I / O服务时间和等待时间的一些指示。 我也喜欢collectl为此目的。