arkanttus

arkanttus

Bad distribution of jobs across nodes

I’m using Oban PRO and I’m facing a job distribution issue.
When executing some queries on the database, I noticed that some nodes were executing much more jobs than others. For example, during one day, there was a node that executed 1M jobs, while another executed only 100k. This caused a CPU and memory increase in nodes was running more jobs.

My configs:

  • Oban 2.17.12
  • Oban Pro 1.4.10
  • Queue :foo with limit: 20, EngineSmart, partitioned and plugins: Reindexer, DynamicLifeline and DynamicPartitioner
  • 10 nodes (pods) in Kubernetes
  • Some jobs are running in priority 0 and others in priority 1 or 2, depending on the args in the job

Here is my complete config:

peer: Oban.Peers.Postgres,
repo: MyRepo,
notifier: Oban.Notifiers.PG,
shutdown_grace_period: my_timeout,
stage_interval: :timer.seconds(2),
prefix: "partitioned_oban",
engine: Oban.Pro.Engines.Smart,
plugins: [
   {Oban.Plugins.Reindexer, schedule: my_schedule, timezone: my_timezone, timeout: :timer.minutes(2)},
   {Oban.Pro.Plugins.DynamicLifeline, rescue_interval: :timer.minutes(5)},
   {
	  Oban.Pro.Plugins.DynamicPartitioner,
	  buffer: 2,
	  schedule: my_schedule,
	  timezone: my_timezone,
	  retention: [completed: 1, cancelled: 1, discarded: 30]
   }
],
queues: [
  foo_jobs: 20,
  rate_limited_foo_jobs: [
    local_limit: 20,
    rate_limit: [
      allowed: 10,
      period: 60
    ]
  ]
]

First Post!

sorentwo

sorentwo

Oban Core Team

Thanks for posting your question on the forum! :slightly_smiling_face:

This could be because of a lock race between the two nodes. The node that’s processing more jobs is acquiring the lock first, so it takes the jobs first, and because of the limit the second node isn’t getting as many jobs. It’s most likely that the leader node is the one running more jobs, as it receives the notification about available jobs first (the message is local, there’s nothing over the wire for the local node with the PG notifier).

Fairness between nodes isn’t enforced, e.g. there isn’t a round robin that ensures each node takes some number of jobs before allowing another node. If fairness is essential, then you can explore using separate queues for each node (foo_jobs_1 and foo_jobs_2), then consistently hashing new jobs into one queue or the other.

A couple of side note about DynamicPartitioner:

  • Unless you’re processing a tremendous number of jobs each day (tens of millions), it may cause more trouble than benefit. It has performance tradeoffs for unique jobs in particular because of how Postgres does partitioning.
  • Be careful with retaining 30 days of jobs because it requires a separate table for each day. Queries for workflows, batches, chains, etc. that need to check each table have to query 30+ tables as a result.

Where Next?

Popular in Questions Top

sen
Hi All, I set a environment variables in dev.exs , like below code. when i start server, how can i set the ${enable} value? thanks. d...
New
nobody
How to bind a phoenix app to a specific ip address? could not find anything about that, nowhere, unfortunately, but for me this is quite...
New
beno
I will often find my self writing things similar to: case some_value do nil -> something() "" -> something() _ -> somethi...
New
Darmani72
If I have a post route which an argument: post /my_post_route/:my_param1, MyController.my_post_handler How would get the post params ...
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
komlanvi
Hi everyone, I was playing with phoenix liveView but I run into an issue. I have a form and want to validate each input text when the te...
New
yawaramin
In the Dialyzer docs ( dialyzer — OTP 29.0.2 (dialyzer 6.0.1) ), there is a way to turn off a specific warning for a function: -dialyzer...
New
jaysoifer
Is there a way to rollback a specific migration and only that one (“skipping” all the other ones)? Would mix ecto.rollback -v 200809061...
New

Other popular topics Top

sen
Hi All, I set a environment variables in dev.exs , like below code. when i start server, how can i set the ${enable} value? thanks. d...
New
danschultzer
None of the current solutions worked well for me, so I went ahead and built a user management system from scratch. This project took far...
548 29603 241
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
greenz1
I have a phoenix application from which a user can download multiple(5-6) files of size 1MB. I couldn’t find anything related to sending ...
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set? Thanks.
New
belgoros
I’m not a pro in using Regex and can’t figure out why the following behaviour happens, especially if we take into account the difference ...
New
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers’ Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
boundedvariable
I am going through the kafka architecture. All the features what the kafka is providing are already in Erlang. I would like hear your opi...
New
joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 records...
New

Latest on Elixir Forum

Elixir Forum

We're in Beta

About us Mission Statement