RocketMQ在消息读写上的处理是其性能的关键,重度依赖底层操作系统的特性。os.sh中提供了一组默认的操作系统参数配置,这里一条条来分析下。

命令

sudo sysctl -w vm.extra_free_kbytes=2000000

这个参数应该也是用来控制空闲内存大小的。但是很多发行版没有这个参数,一般根据部署环境看是否支持,不支持的话不进行设置应该也没关系。

sudo sysctl -w vm.min_free_kbytes=1000000

设置系统需要保留的最小内存大小。当系统内存小于该数值时,则不再进行内存分配。这个命令默认被注释掉,根据文档看,如果设置了不恰当的值,比如比实际内存大,则系统可能直接就会崩溃掉。实际数值应该根据RocketMQ部署机器的内存进行计算,经验数值大概是机器内存的5% - 10%。

这个数值设置的过高,则内存浪费。若设置的过低,那么在内存消耗将近时,RocketMQ的Page Cache写入操作可能会很慢,导致服务不可用。

sudo sysctl -w vm.overcommit_memory=1

控制是否允许内存overcommit。设为1,则是允许。当应用申请内存时,系统都会认为存在足够的内存,准许申请。

sudo sysctl -w vm.drop_caches=1

设置为1会释放page cache。这个操作是一次性的,在执行该命令时释放page cache,没有持续性作用。

sudo sysctl -w vm.zone_reclaim_mode=0

该配置用于控制zone内存使用完之后的处理策略,设为0则禁止zone reclaim。对于大量使用缓存的应用来说,一般都需要禁止掉。

sudo sysctl -w vm.max_map_count=655360

Rocket使用MMAP映射文件到内存,因此需要设置映射文件的数量,避免MMAP操作失败。

sudo sysctl -w vm.dirty_background_ratio=50

设置内存中的脏数据占比,当超过该值时,内核后台线程将数据脏数据刷入磁盘。

sudo sysctl -w vm.dirty_ratio=50

设置内存的脏数据占比,当超过该至时,应用进程会主动将数据刷入磁盘。

sudo sysctl -w vm.dirty_writeback_centisecs=360000

内核线程会定期启动将内存中的旧数据刷入磁盘,通过此参数可以控制启动间隔。

sudo sysctl -w vm.page-cluster=3

设置一次读操作会加载几个数据页。

sudo sysctl -w vm.swappiness=1

vm.swappiness用于控制使用系统swap空间比例,一般设置为0是禁止使用swap,设为1估计是某些系统不支持设置为0.

RocketMQ的数据存储基于MMAP,大量使用内存,因此需要禁止swap,否则性能会急剧下降。

echo 'ulimit -n 655350' >> /etc/profile

设置可以打开的文件符号数。RocketMQ的存储都是基于文件的,因此稍稍设大默认值。

echo '* hard nofile 655350' >> /etc/security/limits.conf

设置一个进程能够打开的文件数。

echo 'deadline' > /sys/block/${DISK}/queue/scheduler

RocketMQ使用MMAP映射文件到内存,在存在新消息的时候都是追加顺序写,投递消息的时候则是根据Offset从CommitLog进行随机读取,Deadline调度方法会在调度时间内合并随机读为书序读,因此对RocketMQ性能有帮助。

总结

RocketMQ的存储模型以来在MMAP纸上,因此os.sh大部分参数控制都与内存管理相关。这些参数对Broker的性能有明显影响。默认提供的数值可以作为一个参考,实际还是可以根据这些参数的定义与实际机器配置来测试得到更优的配置。

参考