OB有问必答 | OceanBase的内存管理是怎么做的?在实际的生产环境中是如何应用的?

内存管理是C高性能服务器的核心问题。一些通用的内存管理库,比如Google TCMalloc在内存申请/释放速度、小内存管理、锁开销等方面都已经做得相当卓越了。然而,我们并没有采用。这是因为通用内存管理库在性能上毕竟不如专用的内存池,更为严重的是,它鼓励了开发人员忽视内存管理的陋习,比如在服务器程序中滥用C标准模板库(STL)。

在分布式存储系统开发初期,内存相关的Bug相当常见,比如内存越界,服务器出现Core Dump,这些Bug都非常难以调试。因此,这个时期内存管理的首要问题并不是高效,而是可控性,并防止内存碎片。

OceanBase系统有一个全局的定长内存池,这个内存池维护了由64KB大小的定长内存块组成的空闲链表。OceanBase的全局内存池实现简单,但内存使用率比较低,即使申请几个字节的内存,也需要占用大小为64KB的内存块。

因此,全局内存池不适合管理小块内存,每个需要申请内存的模块,比如UpdateServer中的memtable,ChunkServer中的缓存,等等,都只能从全局内存池中申请大块内存,每个模块内部再实现专用的内存池。每个线程处理读写请求时需要使用临时内存,为了提高效率,每个线程会缓存若干个大小分别为64KB和2MB的内存块,每个线程总是首先尝试从线程局部缓存中申请内存,如果申请不到,再从全局内存池中申请。

OceanBase的内存管理虽然没有采用高深的技术,但是已经很好地满足了系统初期的两个最主要的需求:可控性以及没有内存碎片。

那么,在实际的生产环境中OceanBase的内存管理策略是什么?

接下来我们为大家介绍三种最主要的场景:

1、OLTP场景
业务特点:读写RT敏感、数据一致性敏感、SQL多以key-value类型为主、范围查询及连表查询较少且也都走最优索引、读写比相差不大、业务存在明显高峰期。

场景解读:一般OLTP场景对读写RT要求严格,GB级OB库一般要求RT保证在10ms以内,TB级OB库甚至要求更低比如5ms。日常交易或者说事务要求严格保证数据一致性,如发生RT抖动,锁冲突骤增、极易发生业务数据错误。日常读写流量比基本上在3:1~1:1之间,且日常流量一般存在峰值,跟社会生活正常作息时间正相关。涉及行业一般有金融、电商、物流、社会各类服务业等。

配置推荐:对于此类场景的特点,一般需要将OB内存切换时间调整到最小,在日常流量峰值期间尽可能避免集群发生合并,而将日常合并时间尽量调整到业务低峰期保证集群合并对集群性能影响最小,具体推荐配置参数如下:
memory_limit=0(默认即可,即OB使用物理机操作系统内存上限由memory_limit_percentage参数决定)
memory_limit_percentage=80/90(根据物理机可用内存大小决定,512G以下的使用80%,512及以上的采用90%)
freeze_trigger_percentage=60~75%(根据读写比例判断,建议写越高则取数越趋近于memory_limit_percentage值,目的是能更多的存放dml数据到内存,减少转储和合并)
minor_freeze_times=3-8(根据每日dml量决定,转储可快速释放内存但也存在轻微抖动,转储速度取决于存储介质,ssd>hdd>sata)

2、OLAP场景
业务特点:读写RT可容忍在百毫秒甚至秒级、数据一致性不敏感(可容忍毫秒级节点间数据不一致,且分析型业务聚合计算数据都是万到百万级别量级)、SQL多以条件范围排序、连表聚合计算为主(此类AP查询SQL在OB中只需走分区键索引或主键即可)、读写比往往是读远小于写、仅读业务存在高峰期、写业务峰值往往有周期性或间歇性(主要原因为大多数AP类业务都有实时、离线周期性同步任务)。涉及行业一般有金融、电商、彩票、服务业、咨询、科学计算领域等,较AP类业务更常见。

配置推荐:对于此类场景的特点,一般需要将OB内存切换时间调整到尽可能小的程度以保证数据同步性能不受合并影响,但同时也要考虑到AP场景物理机存储介质对合并影响的问题。日常合并次数减少带来的一个问题就是合并时间也会增加(相比于每日开多轮转储和不开转储的情况)。所以这类场景需要结合存储介质进行决策,如采用ssd介质可相对增加转储次数,尽量将合并控制在数据同步低峰期;如采用sata慢速存储介质,可优化合并线程数并减少转储次数(类似于历史库场景),尽可能增加合并速度,减少合并对写入的影响。具体推荐配置参数如下:
memory_limit=0(默认即可,即OB使用物理机操作系统内存上限由memory_limit_percentage参数决定)
memory_limit_percentage=80(建议使用80的配置,保证更多内存分配到cache和sql线程等动态伸缩内存中,保证读数据正常返回)
freeze_trigger_percentage=60%(这里建议调小合并阈值,保证剩余内存能支持冻结后内存未释放期间的批量写入,从而不影响到同步写数据任务)
minor_freeze_times=3-5(该场景下建议ssd和hdd存储介质开启转储,转储可快速释放内存但也存在轻微抖动,转储速度取决于存储介质,ssd>hdd>sata,sata盘在此场景中不建议开启转储)

3、历史库场景
业务特点:读RT与TP类型业务无太大差异,对数据一致性敏感,但对写RT不敏感,SQL类型与TP类业务相似,多为key-value查询,偶尔有统计及聚合类SQL但量不大。读业务存在高峰期,写业务无绝对峰值但存在规律性(同步数据任务为主)。涉及行业及使用场景场景的有金融行业的冷备库、电商行业订单类冷备库等,主要作用为存放有价值的冷数据,提供数据回溯、历史记录查询、历史数据统计等,需保证读RT在毫秒级,写流量持续稳定,存储数据量级一般在TB甚至PB级,故一般存储介质采用sata盘。

配置推荐:根据此类场景的特点,需要控制OB在内存切换时不影响读性能,同时由于存储介质带宽比较低,故还需控制合并效率,参数如下:
memory_limit=0(默认即可,即OB使用物理机操作系统内存上限由memory_limit_percentage参数决定)
memory_limit_percentage=80(根据物理机可用内存大小决定,512G以下的使用80%,512及以上的采用90%)
freeze_trigger_percentage=80%(这里建议将合并阈值调到跟memstore参数一致,保证每日合并次数尽可能少)
minor_freeze_times=0(该场景多为sata盘,sata盘在此场景中不建议开启转储)
sys_bkgd_io_percentage = 90(调整系统IO线程占比到90,保证合并时数据盘带宽能开到最大)
merge_thread_count= 48(默认为0,即由租户线程自动分配合并线程,将其调整到48,使更多线程参与到合并中保证合并时间不会太久)

总结来说,使用OceanBase的过程中需要根据使用场景以及物理机型去调整内存管理参数,使集群性能与业务要求达到最佳匹配,在充分发挥出OceanBase内存表查询低RT的优势的同时,保证了在高可用前提下设备的最大利用率,在性能和性价比之间达到最佳均衡。

上一篇:OB有问必答 | OceanBase存储引擎基于LSM Tree的理论做了哪些创新和实践?


下一篇:蚂蚁自研数据库OceanBase首次阐述战略:继续坚持自研开放之路 开源300万行核心代码