1、查看当前所有数据节点内存使用情况(maxMemSize 是程序的实际最大内存限制,oom的情况下memoryUsed应该已经基本打满至maxMemSize了)
select site, maxMemSize, memoryUsed\1024\1024\1024 as memoryUsed, memoryAlloc\1024\1024\1024 as memoryAlloc from rpc(getControllerAlias(),getClusterPerf)
程序的实际最大内存限制,取决于license里授权的内存大小和.cfg配置文件中的maxMemSize值中的较小值。如果不符合您的预期,可以确认一下license授权和内存配置参数。
a. 查看授权的内存大小(社区版license限制4G;可以在官网申请企业版试用license,更多节点、CPU核数、内存。)
license()
b. 查看.cfg配置文件中maxMemSize参数
getConfigure(`maxMemSize)
2、释放所有节点的缓存(定义变量占用的内存不会释放)
pnodeRun(clearAllCache)
3、查看变量占用内存大小
pnodeRun(objs) //查询每个节点定义变量占用内存(不共享的),bytes字段 pnodeRun(objs{true}) //查询每个节点定义变量占用内存(共享的),bytes字段
查看每个数据节点上定义的变量和占用的内存:使用undef()、undef all、变量名=NULL释放非共享变量占用内存;使用 undef("sharedTable", SHARED)释放共享变量占用内存;使用dropStreamTable()删除流数据表。如果流数据表启用了持久化,该函数也会将磁盘上持久化的数据删除。
4、查看流引擎占用内存大小
getStreamEngineStat().CrossSectionalEngine // 查看CrossSectionalEngine 的内存
getStreamEngineStat().ReactiveStreamEngine // 查看ReactiveStreamEngine 的内存
getStreamEngineStat().AsofJoinEngine // 查看AsofJoinEngine 的内存: memoryUsed字段,单位Byte,其他引擎查询方式类似
查看每个流计算引擎占用的内存大小,这里的内存主要是引擎中用于保存状态而使用的内存。
删除引擎即可释放引擎占用的内存:a.使用dropStreamEngine()释放指定的流数据引擎的定义; b.使用变量名=NULL 从内存中释放流数据引擎的句柄的定义(若内存中存在这个变量则需要这一步)
5、查看正在运行的作业
pnodeRun(getRecentJobs) //查看后台在运行的作业 pnodeRun(getConsoleJobs) //查看前台在运行的作业
排查是否有正在运行且可能消耗大量内存的作业
6、流订阅也会占用内存
subscribeTable中handler使用自定义函数定义时,在流计算过程中调用handler而占用的内存目前不方便查询。如果在经过1-5点确认和释放后,仍还有大量内存无法定位到具体的用途,则可能是使用自定义函数的handler占用了这部分内存,可以通过unsubscribeTable反订阅掉相关的订阅,来释放这部分内存。getStreamingStat().pubTables可以查看subscribeTable提交的所有订阅关系。
流计算内存优化:
1、引擎流水线级联
流引擎均实现了数据表(table)的接口,因此只要将后一个引擎作为前一个引擎的输出,即可实现多个引擎流水线处理。相较于通过中间表来串联多个引擎的实现方法,使用引擎级联可以大大减少对中间表的内存管理。
级联的实现脚本可参考:多个引擎级联使用 问题中的第二个回答
2、引擎参数调优
如果通过getStreamEngineStat()查看流引擎占用内存过大,可以通过调整createEngine时的部分参数来适当减少引擎的内存占用。
以asofjoin引擎为例,其主要的内存占用为存放在内存中的历史数据。如果在订阅过程中发现asofjoin引擎的内存过大,可以通过参数garbageSize,清理不再需要的历史数据。garbageSize的大小需要根据实际情况设置,大致可以按照每个小时每个key会有多少条数据设置。
原理如下:首先garbageSize是针对key的,即每个key分组内数据到了才清理。garbageSize过小,会频繁清理历史数据带来不必要的开销;garbageSize过大,可能会一直达不到garbageSize这个阈值而无法触发清理,造成asofjoin中不再需要的历史数据一直没有被清理。所以建议按照一个小时清理一次,估计一下具体情况每个小时每个key会有多少数据,来设置garbageSize值。
3、handler自定义函数优化