python-3.x - 使用 task.forget() 时 Redis 内存使用量继续攀升
问题描述
我有一个 mysql 数据库,它存储了 2 年的数千个库存 OHLC 数据。数据以 pandas 数据帧的形式从 MySQL 读取,然后以大批量作业的形式提交给 celery,最终导致“使用内存>'maxmemory'时不允许使用 OOM 命令”。
我添加了以下 celery 配置选项。这些选项使我的脚本运行时间更长,但是 redis 不可避免地会达到 2gb 内存,并且 celery 会引发 OOM 错误。
result_expires = 30
ignore_result = True
worker_max_tasks_per_child = 1000
从 redis 方面,我尝试使用 allkeys-lru 和 volatile-lru 来使用 maxmemory 策略。两者似乎都没有区别。
当芹菜遇到OOM错误时,redis cli显示最大内存使用量并且没有键?
# Memory
used_memory:2144982784
used_memory_human:2.00G
used_memory_rss:1630146560
used_memory_rss_human:1.52G
used_memory_peak:2149023792
used_memory_peak_human:2.00G
used_memory_peak_perc:99.81%
used_memory_overhead:2144785284
used_memory_startup:987472
used_memory_dataset:197500
used_memory_dataset_perc:0.01%
allocator_allocated:2144944880
allocator_active:1630108672
allocator_resident:1630108672
total_system_memory:17179869184
total_system_memory_human:16.00G
used_memory_lua:37888
used_memory_lua_human:37.00K
used_memory_scripts:0
used_memory_scripts_human:0B
number_of_cached_scripts:0
maxmemory:2147483648
maxmemory_human:2.00G
maxmemory_policy:allkeys-lru
allocator_frag_ratio:0.76
allocator_frag_bytes:18446744073194715408
allocator_rss_ratio:1.00
allocator_rss_bytes:0
rss_overhead_ratio:1.00
rss_overhead_bytes:37888
mem_fragmentation_ratio:0.76
mem_fragmentation_bytes:-514798320
mem_not_counted_for_evict:0
mem_replication_backlog:0
mem_clients_slaves:0
mem_clients_normal:2143797684
mem_aof_buffer:0
mem_allocator:libc
active_defrag_running:0
lazyfree_pending_objects:0
并且有零键?
127.0.0.1:6379[1]> keys *
(empty list or set)
当我在 200*5 请求的子集中运行相同的代码(然后终止)时,一切都会成功运行。Redis 内存使用量上限约为 100mb,当 python 进程终止时,所有内存使用量都会按预期下降。这让我相信我可能会实现一个处理程序来一次执行 200*5 个请求,但是我怀疑 python 进程(我的脚本)终止实际上是在 celery/redis 中释放内存......
我想避免对它进行子集化,并一次性处理 MySQL 中的所有内容。大约 5000 个 pandas 数据帧 * 总共 5 个任务。
我不明白为什么当我在检索结果后立即忘记所有结果时,redis 中的内存使用量会继续增长?
这是我的代码中如何完成此操作的示例:
def getTaskResults(self, caller, task):
#Wait for the results and then call back
#Attach this Results object in the callback along with the data
ready = False
while not ready:
if task.ready():
ready = True
data = pd.read_json(task.get())
data.sort_values(by=['Date'], inplace=True)
task.forget()
return caller.resultsCB(data, self)
这可能是我对 redis 的无知,但是如果没有键,它是如何消耗所有内存的,或者我如何验证在 redis 中实际消耗的内存是什么?
由于我将每次调用 celery 的 taskID 存储在一个对象中,我已经确认在添加 task.forget 后尝试执行 task.get 会引发错误。
解决方案
推荐阅读
- c++ - 函数和非捕获 lambda 之间的区别
- java - CDS size impact on startup performance
- javascript - 为什么javascript显示未定义?
- sql - 获取重复记录的行值作为列
- c# - 如何使用多个依赖属性绑定到计算属性
- php - 如何完全绕过结帐页面并直接进入“下订单”
- html - 在浏览器中播放来自 web.api 的音频
- sql - 在 oracle 数据库中,我们如何同时在两个表上维护相同的代理键(序列值)
- c - c中的指针数组,访问原始数组
- elasticsearch - 如何让elasticsearch一次返回10000多个结果?ES 似乎没有遵守 index.max_result_window 设置