BOOKS DEEP-READ · SRE · CH 24

Distributed Periodic Scheduling: Turning Cron Into a Service That Won't Double-Run

Site Reliability Engineering · Ch 24 · Google (Štěpán Davidovič) · 2016

中文 →

What is this chapter about?

Think of the standing order on your bank account that pays the rent on the 8th of every month. Paying twice is a mess; not paying at all is also a mess. On servers, the little butler that does "run this thing every day at such-and-such time" is called cron. SRE Chapter 24 is about what happens to that butler when the job no longer belongs to one machine, but to a whole datacenter.

A strange thing first

On a single machine, cron is the most boring tool in the box — nobody has worried about it for decades. But once you have a hundred machines, the utterly ordinary sentence "run this once a day at 2am" stops being guaranteed. Either it never ran that day and nobody noticed, or it ran twice and paid everyone twice.

Why the old world is hard

There are only two naive options, and both fail. Give the alarm clock to one designated machine: the day that machine dies, the alarm and the whole list of alarms die with it — and they die silently, because an alarm that never rang doesn't page anyone. You may not find out until Monday. Put the same alarm on every machine: at the appointed second, a hundred machines all start working, and the same job gets done a hundred times.

The fix: elect someone on duty, then keep one shared ledger

First, the machines elect one of themselves to be on duty — nobody may self-appoint; it takes a majority to agree. Only the one on duty starts jobs. The others don't start anything, but they must write the same ledger, so any of them can take over at a moment's notice.

How the ledger is kept is the whole trick. For every job, the one on duty writes two lines: before starting, "I am about to do this"; after starting, "I started it, its name is X." Why bother with the first line? Because the one on duty can collapse at exactly the moment of starting. The stand-in opens the ledger, sees the first line but not the second, and knows this job may or may not have happened — it is stuck in a window nobody can read. So the stand-in goes and asks the workshop, "is there a job called X running in there?" If the answer comes back, fine. If it doesn't, all that's left is the rule you agreed on in advance.

The cut you have to make: rather skip than repeat

Google's rule is: rather miss a run than run it twice. The reasoning is practical — a missed run is visible (a gap in the data, an alert) and you can just run it again; a duplicate run (two emails, two charges) often cannot be taken back.

The price is stated plainly too: it means your job really will occasionally not run, so you must add an alert for "this didn't happen" — otherwise you have only traded noise for silence.

One more thing: stop crowding the top of the hour

Almost everyone writes "midnight" in their schedule. So at the stroke of the hour thousands of jobs ask the datacenter for machines at once, a flash flood — and the other 59 minutes sit idle. Which is why this cron lets you say "pick any moment inside this window for me," flattening the peak.

Remember one thing

The moment a scheduled job leaves a single machine it stops being a small tool and becomes a service that has to elect a leader and keep a shared ledger. And it cannot have it both ways: you must choose in advance between missing and repeating, then put an alert on whichever one you didn't choose.

Want the crash-window timeline, where the state lives, and what Kubernetes admits in public? → Switch to the deep read