尽管队列看起来是空的,但 Celery Redis 实例已满

Posted

技术标签:

【中文标题】尽管队列看起来是空的,但 Celery Redis 实例已满【英文标题】:Celery Redis instance filling up despite queue looking empty 【发布时间】:2019-12-25 13:39:14 【问题描述】:

我们有一个 Django 应用程序需要使用 Celery 获取大量数据。每隔几分钟就有 20 名左右的芹菜工人在跑步。我们在 Google Kubernetes Engine 上运行,带有一个使用 Cloud memorystore 的 Redis 队列。

根据 Flower 的说法,我们用于 celery 的 Redis 实例正在填满,即使队列为空。这会导致 Redis DB 最终被填满并且 Celery 抛出错误。

在 Flower 中,我看到任务进出,我已经将工作人员增加到现在队列总是空的程度。

如果我运行redis-cli --bigkeys 我会看到:


# Scanning the entire keyspace to find biggest keys as well as
# average sizes per key type.  You can use -i 0.1 to sleep 0.1 sec
# per 100 SCAN commands (not usually needed).

[00.00%] Biggest set    found so far '_kombu.binding.my-queue-name-queue' with 1 members
[00.00%] Biggest list   found so far 'default' with 611 items
[00.00%] Biggest list   found so far 'my-other-queue-name-queue' with 44705 items
[00.00%] Biggest set    found so far '_kombu.binding.celery.pidbox' with 19 members
[00.00%] Biggest list   found so far 'my-queue-name-queue' with 727179 items
[00.00%] Biggest set    found so far '_kombu.binding.celeryev' with 22 members

-------- summary -------

Sampled 12 keys in the keyspace!
Total key length in bytes is 271 (avg len 22.58)

Biggest   list found 'my-queue-name-queue' has 727179 items
Biggest    set found '_kombu.binding.celeryev' has 22 members

4 lists with 816144 items (33.33% of keys, avg size 204036.00)
0 hashs with 0 fields (00.00% of keys, avg size 0.00)
0 strings with 0 bytes (00.00% of keys, avg size 0.00)
0 streams with 0 entries (00.00% of keys, avg size 0.00)
8 sets with 47 members (66.67% of keys, avg size 5.88)
0 zsets with 0 members (00.00% of keys, avg size 0.00)

如果我使用 LRANGE 检查队列,我会看到很多这样的对象:

"\"body\": \"W1syNDQ0NF0sIHsicmVmZXJlbmNlX3RpbWUiOiBudWxsLCAibGF0ZXN0X3RpbWUiOiBudWxsLCAicm9sbGluZyI6IGZhbHNlLCAidGltZWZyYW1lIjogIjFkIiwgIl9udW1fcmV0cmllcyI6IDF9LCB7ImNhbGxiYWNrcyI6IG51bGwsICJlcnJiYWNrcyI6IG51bGwsICJjaGFpbiI6IG51bGwsICJjaG9yZCI6IG51bGx9XQ==\", \"content-encoding\": \"utf-8\", \"content-type\": \"application/json\", \"headers\": \"lang\": \"py\", \"task\": \"MyDataCollectorClass\", \"id\": \"646910fc-f9db-48c3-b5a9-13febbc00bde\", \"shadow\": null, \"eta\": \"2019-08-20T02:31:05.113875+00:00\", \"expires\": null, \"group\": null, \"retries\": 0, \"timelimit\": [null, null], \"root_id\": \"beeff557-66be-451d-9c0c-dc622ca94493\", \"parent_id\": \"374d8e3e-92b5-423e-be58-e043999a1722\", \"argsrepr\": \"(24444,)\", \"kwargsrepr\": \"'reference_time': None, 'latest_time': None, 'rolling': False, 'timeframe': '1d', '_num_retries': 1\", \"origin\": \"gen1@celery-my-queue-name-worker-6595bd8fd8-8vgzq\", \"properties\": \"correlation_id\": \"646910fc-f9db-48c3-b5a9-13febbc00bde\", \"reply_to\": \"e55a31ed-cbba-3d79-9ffc-c19a29e77aac\", \"delivery_mode\": 2, \"delivery_info\": \"exchange\": \"\", \"routing_key\": \"my-queue-name-queue\", \"priority\": 0, \"body_encoding\": \"base64\", \"delivery_tag\": \"a83074a5-8787-49e3-bb7d-a0e69ba7f599\""

我们使用 django-celery-results 来存储结果,所以这些结果不应该放在那里,我们使用一个单独的 Redis 实例作为 Django 的缓存。

如果我用 FLUSHALL 清除 Redis,它会慢慢再次填满。

我有点不知道下一步该去哪里。我不太了解 Redis - 也许我可以做一些事情来检查数据以查看填充的内容?也许是Flower没有正确报告?尽管我们使用 Django DB 获取结果,但 Celery 可能会保留已完成的任务?

感谢任何帮助。

【问题讨论】:

想知道您是否找到了解决方案? 【参考方案1】:

听起来 Redis 没有设置为删除已完成的项目或报告和删除失败的项目——即它可能会将任务列入清单,但不会取消。

查看 pypi 包:rq、django-rq、django-rq-scheduler

你可以在这里阅读一些关于它应该如何工作的信息:https://python-rq.org/docs/

【讨论】:

【参考方案2】:

这似乎是 Celery 的一个已知(或有意)问题,提出了各种解决方案/解决方法: https://github.com/celery/celery/issues/436

【讨论】:

以上是关于尽管队列看起来是空的,但 Celery Redis 实例已满的主要内容,如果未能解决你的问题,请参考以下文章

java中的队列有哪些,有啥区别

Celery 队列和 Redis 队列

停止 Redis 后如何继续执行 celery 队列,然后再启动它?

定时任务、Celery、消息队列

python 关于celery的异步任务队列的基本使用(celery+redis)采用配置文件设置

基于celery及redis封装sanic的api