Slide 1

Slide 1 text

No content

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

Alexander Baygeldin, Evil Martians Prioritization justice: lessons from making background jobs fair at scale πŸ•πŸ•πŸ•

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³

Slide 7

Slide 7 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ• πŸ• πŸ•

Slide 8

Slide 8 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ• πŸ• πŸ•

Slide 9

Slide 9 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ• πŸ•

Slide 10

Slide 10 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ• πŸ• πŸ•

Slide 11

Slide 11 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ• πŸ• πŸ•

Slide 12

Slide 12 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ• πŸ• Latency = the time between placing the order and starting to prepare it

Slide 13

Slide 13 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ• πŸ• πŸ§‘πŸ³ πŸ§‘πŸ³

Slide 14

Slide 14 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ• πŸ• πŸ§‘πŸ³ πŸ§‘πŸ³ 🧒 🧒 part-time chefs

Slide 15

Slide 15 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ• πŸ• πŸ§‘πŸ³ πŸ§‘πŸ³ 🧒 🧒 πŸ§‘πŸ³ 🧒 πŸ§‘πŸ³ 🧒 πŸ§‘πŸ³ 🧒 πŸ§‘πŸ³ 🧒 πŸ§‘πŸ³ 🧒 πŸ§‘πŸ³ 🧒 πŸ§‘πŸ³ 🧒 πŸ§‘πŸ³ 🧒 part-time chefs

Slide 16

Slide 16 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ• πŸ• πŸ§‘πŸ³ πŸ§‘πŸ³ 🧒 🧒 πŸ§‘πŸ³ 🧒 πŸ§‘πŸ³ 🧒 πŸ§‘πŸ³ 🧒 πŸ§‘πŸ³ 🧒 πŸ§‘πŸ³ 🧒 πŸ§‘πŸ³ 🧒 πŸ§‘πŸ³ 🧒 πŸ§‘πŸ³ 🧒 part-time chefs At some point improving Quality of Service at more operational cost leads to diminishing returns

Slide 17

Slide 17 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ• πŸ• πŸ•

Slide 18

Slide 18 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ• πŸ• πŸ•

Slide 19

Slide 19 text

πŸ• πŸ• πŸ• πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³

Slide 20

Slide 20 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ The greater the latency, the greater the need to treat customers fairly πŸ• πŸ•

Slide 21

Slide 21 text

G = n βˆ‘ i=1 n βˆ‘ j=1 xi βˆ’ xj 2n2 Β― x = n βˆ‘ i=1 n βˆ‘ j=1 xi βˆ’ xj 2n n βˆ‘ i=1 xi π’₯ (x1 , x2 , …, xn ) = (βˆ‘n i=1 xi )2 n β‹… βˆ‘n i=1 xi 2 = x2 x2 = 1 1 + Μ‚ cv 2 Jain's index? Gini index? Some other guy's index?

Slide 22

Slide 22 text

How do we know if we're not? β˜‘ FIFO queue β˜‘ High latency β˜‘ Greedy users Are we OK?

Slide 23

Slide 23 text

Customer feedback!

Slide 24

Slide 24 text

πŸ• πŸ• πŸ• πŸ• πŸ• πŸ• πŸ•

Slide 25

Slide 25 text

πŸ• πŸ• πŸ• πŸ• πŸ• πŸ• πŸ•

Slide 26

Slide 26 text

πŸ• πŸ• πŸ• πŸ• πŸ• πŸ• πŸ•

Slide 27

Slide 27 text

πŸ• πŸ• πŸ• πŸ• πŸ• πŸ• πŸ•

Slide 28

Slide 28 text

πŸ• πŸ• πŸ• πŸ• πŸ• πŸ• πŸ•

Slide 29

Slide 29 text

πŸ• πŸ• πŸ• πŸ• πŸ• πŸ• πŸ•

Slide 30

Slide 30 text

πŸ• πŸ• πŸ• πŸ• πŸ• πŸ• πŸ•

Slide 31

Slide 31 text

πŸ• πŸ• πŸ• πŸ• πŸ• πŸ• πŸ•

Slide 32

Slide 32 text

πŸ• πŸ• πŸ• πŸ• πŸ• πŸ• πŸ•

Slide 33

Slide 33 text

πŸ• πŸ• πŸ• πŸ• πŸ• πŸ• πŸ•

Slide 34

Slide 34 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ• πŸ• πŸ•

Slide 35

Slide 35 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ• πŸ• πŸ•

Slide 36

Slide 36 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ• πŸ• πŸ• 🎲

Slide 37

Slide 37 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ• πŸ• πŸ• 🎲 πŸ• πŸ• πŸ• πŸ• πŸ•

Slide 38

Slide 38 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ• πŸ• πŸ• 🎲 πŸ• πŸ• πŸ• πŸ• πŸ•

Slide 39

Slide 39 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ BRPOP queue:tenant_1 queue:tenant_2 ... queue:tenant_N 2 timeout per-tenant queues

Slide 40

Slide 40 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ LMOVE queue:tenant_1 queue:sq||tenant_1 RIGHT LEFT LMOVE queue:tenant_2 queue:sq||tenant_2 RIGHT LEFT ... LMOVE queue:tenant_N queue:sq||tenant_N RIGHT LEFT worker's "in-progress" queues per-tenant queues

Slide 41

Slide 41 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ Solid Queue SELECT job_id FROM solid_queue_ready_executions WHERE queue_name = 'tenant_N' ORDER BY priority ASC, job_id ASC LIMIT ? FOR UPDATE SKIP LOCKED;

Slide 42

Slide 42 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ GoodJob πŸ‘ WITH rows AS MATERIALIZED ( SELECT id, active_job_id FROM good_jobs WHERE queue_name = 'tenant_N' AND () ORDER BY priority DESC NULLS LAST, created_at ASC LIMIT ? ) SELECT id FROM rows WHERE pg_try_advisory_lock() LIMIT 1

Slide 43

Slide 43 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³

Slide 44

Slide 44 text

Thinking about building your own background job processor Actually building one

Slide 45

Slide 45 text

(with what we have) 1. Shu ff l e-sharding 2. Interruptible iteration 3. Throttling 4. Per-tenant queues Let's fix this!

Slide 46

Slide 46 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ• πŸ• πŸ• πŸ• πŸ• πŸ•

Slide 47

Slide 47 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ Alex πŸ• A to I J to R S to Z Amy πŸ• Joe πŸ• Sam πŸ• Sam πŸ• Amy πŸ•

Slide 48

Slide 48 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ Alex πŸ• A to I J to R S to Z Amy πŸ• Joe πŸ• Sam πŸ• Sam πŸ• Amy πŸ•

Slide 49

Slide 49 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ A to I J to R S to Z Amy πŸ• Amy πŸ• πŸ’€ Sam πŸ•

Slide 50

Slide 50 text

πŸ§‘πŸ³ 🐷 Pentagon πŸ• πŸ§‘πŸ³ πŸ§‘πŸ³ A to I J to R S to Z Amy πŸ• Amy πŸ• Sam πŸ• 🐷 Pentagon πŸ•

Slide 51

Slide 51 text

πŸ§‘πŸ³ 🐷 Pentagon πŸ• πŸ§‘πŸ³ πŸ§‘πŸ³ A to I J to R S to Z Amy πŸ• Amy πŸ• Sam πŸ• 🐷 Pentagon πŸ•

Slide 52

Slide 52 text

πŸ§‘πŸ³ 🐷 Pentagon πŸ• πŸ§‘πŸ³ πŸ§‘πŸ³ A to I J to R S to Z Amy πŸ• 🐷 Pentagon πŸ• πŸ’€ Joe πŸ•

Slide 53

Slide 53 text

Shuffle-sharding (tl;dr: good when you have enough workload to fi ll all shards) No hogging? No, but it's times less likely. Perfectly fair? No, but it a ff ects fewer people when it's not fair. Full resource utilization? Noβ€”underutilization is possible with too many shards. Does it scale? Yes, but it needs at least one worker per shard.

Slide 54

Slide 54 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ• πŸ• πŸ•

Slide 55

Slide 55 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ• πŸ• πŸ• πŸ• πŸ• πŸ•

Slide 56

Slide 56 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ• πŸ• πŸ•

Slide 57

Slide 57 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ• πŸ• πŸ• πŸ’€ πŸ’€ πŸ’§

Slide 58

Slide 58 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ• πŸ• πŸ• πŸ’€ πŸ’€ πŸ’§

Slide 59

Slide 59 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ• πŸ• πŸ• πŸ• πŸ• πŸ•

Slide 60

Slide 60 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ• πŸ• πŸ• πŸ• πŸ• πŸ• πŸ• πŸ•

Slide 61

Slide 61 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ• πŸ• πŸ• πŸ• πŸ•

Slide 62

Slide 62 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ• πŸ• πŸ• πŸ• πŸ•

Slide 63

Slide 63 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ• πŸ• πŸ• πŸ• πŸ• πŸ• πŸ• πŸ• πŸ• πŸ• πŸ•

Slide 64

Slide 64 text

Interruptible iteration (tl;dr: good when the workload comes in large batches) No hogging? Noβ€”it could happen if one tenant enqueues multiple batches. Perfectly fair? Noβ€”it stops being fair when someone hogs the queue. Full resource utilization? Yes, but must be greater than . Does it scale? Yesβ€”using cursors to track progress is cheap.

Slide 65

Slide 65 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ•

Slide 66

Slide 66 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ• πŸ• πŸ• πŸ•

Slide 67

Slide 67 text

πŸͺ£ 🚿 πŸ•³

Slide 68

Slide 68 text

πŸͺ£ 🚿 πŸ•³ πŸ’§ πŸ’§ πŸ’§ πŸ’§ πŸ’§ πŸ’§ πŸ’§ πŸ’§ πŸ’§ over time, the bucket leaks allowing further orders bucket has a limited capacity each new order fi lls the bucket

Slide 69

Slide 69 text

πŸͺ£ 🚿 πŸ•³ πŸ’§ πŸ’§ πŸ’§ πŸ’§ πŸ’§ πŸ’§ πŸ’§ πŸ’§ πŸ’¦ πŸ’¦ uh-oh, over fl ow! over time, the bucket leaks allowing further orders bucket has a limited capacity each new order fi lls the bucket

Slide 70

Slide 70 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ• πŸ• πŸ• πŸ•

Slide 71

Slide 71 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ• πŸ• πŸ• πŸ• excess orders are put here

Slide 72

Slide 72 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ• πŸ• πŸ• πŸ• 🎲

Slide 73

Slide 73 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ• πŸ• πŸ• πŸ• 🎲 default queue (80% chance to be processed) throttled queue (20% chance to be processed)

Slide 74

Slide 74 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ• πŸ• πŸ• πŸ• 🎲 default queue (80% chance to be processed) throttled queue (20% chance to be processed) πŸ•

Slide 75

Slide 75 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ• πŸ• 🎲 default queue (80% chance to be processed) throttled queue (20% chance to be processed) πŸ•

Slide 76

Slide 76 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ• πŸ• 🎲 πŸ• orders stuck in the throttled queue :(

Slide 77

Slide 77 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ• πŸ• 🎲 πŸ•

Slide 78

Slide 78 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ• 🎲 πŸ• no longer throttled (100% chance to be processed)

Slide 79

Slide 79 text

Throttling (tl;dr: good when the workload is well distributed over time) No hogging? Yesβ€”everyone will get at least a little work done. Perfectly fair? Noβ€”especially if the workload is bursty by nature. Full resource utilization? Yes, but it requires weighted queues support. Does it scale? Yesβ€”especially with leaky buckets.

Slide 80

Slide 80 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ• πŸ•

Slide 81

Slide 81 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ• πŸ•

Slide 82

Slide 82 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ• πŸ‘¨πŸ’Ό πŸ• πŸ“’

Slide 83

Slide 83 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ• πŸ‘¨πŸ’ΌπŸ“’ πŸ•

Slide 84

Slide 84 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ• πŸ‘¨πŸ’ΌπŸ“’ πŸ• πŸ’€

Slide 85

Slide 85 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ‘¨πŸ’ΌπŸ“’ πŸ• β€Ό

Slide 86

Slide 86 text

πŸ• πŸ• πŸ“’ πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ‘¨πŸ’Ό πŸ• πŸ• πŸ•

Slide 87

Slide 87 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ‘¨πŸ’ΌπŸ“’ πŸ• πŸ• πŸ• πŸ’€ bottleneck!

Slide 88

Slide 88 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ“’ πŸ• πŸ• πŸ• πŸ‘¨πŸ’Ό πŸ§™

Slide 89

Slide 89 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ“’ πŸ• πŸ• πŸ• πŸ§™

Slide 90

Slide 90 text

πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ“’ πŸ• πŸ• πŸ• πŸ§™

Slide 91

Slide 91 text

πŸ• πŸ• πŸ• 🎲 πŸ• πŸ• πŸ• πŸ• πŸ• πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ§‘πŸ³ πŸ“’ πŸ• πŸ• πŸ• πŸ§™

Slide 92

Slide 92 text

Per-tenant queues + custom scheduler (tl;dr: good when the workload is heavy enough to forget about the bottleneck) No hogging? Yesβ€”it's basically communism. Perfectly fair? Yesβ€”as fair as you care to make it. Full resource utilization? Yesβ€”with zero changes to the underlying infra. Does it scale? It depends... on how e ff i cient your scheduler is.

Slide 93

Slide 93 text

(where fairness matter) ✨ AI work fl ows * ⬇ Data imports πŸ–Ό Media processing πŸ“Š Reports generation Examples! ... and more! ` * less so with async-job

Slide 94

Slide 94 text

So, which one? Shu ff l e- sharding Interruptible iteration Throttling Per-tenant queues No hogging? ❌ ❌ βœ… βœ… Perfectly fair? ❌ ❌ ❌ βœ… Full resource utilization? 🟧 🟧 βœ… βœ… Does it scale? βœ… βœ… βœ… 🟧

Slide 95

Slide 95 text

(part 1) βš– sidekiq-fairplay gem βš– πŸ§‘βš– sidekiq-fairplay gem πŸ§‘βš– 🀝 sidekiq-fairplay gem 🀝 Resources

Slide 96

Slide 96 text

(part 2) β€’ Workload Isolation with Queue Sharding (by Mike Perham) β€’ Workload Isolation Using Shu ff l e- Sharding (by Colm MacCΓ‘rthaigh) Resources

Slide 97

Slide 97 text

(part 3) β€’ job-iteration gem (from Shopify) β€’ Sidekiq Iterable Jobs: With Great Power.... (by Jon Sully) β€’ Active Job Continuations Resources

Slide 98

Slide 98 text

(part 4) β€’ β€œFair” multi-tenant prioritization of Sidekiq jobsβ€”and our gem for it! (by Andrey Novikov) β€’ The unreasonable e ff ectiveness of leaky buckets (and how to make one) (by Julik Tarkhanov) Resources

Slide 99

Slide 99 text

(part 5) β€’ faqueue: researching background jobs fairness (by Vladimir Dementyev) β€’ fairway gem Resources

Slide 100

Slide 100 text

No content

Slide 101

Slide 101 text

put this in your address bar

Slide 102

Slide 102 text

No content