Planlagte og periodiske jobs med Celery Beat
Kør tilbagevendende jobs med Celery Beat, og koordinér cron-lignende planer sikkert på tværs af flere workers.
Planlagte og periodiske jobs med Celery Beat er en gratis Bootcamp i FastAPI-backendudvikling-lektion på CoddyKit. Dette er lektion 4 af 4. Du kan læse alle 3 lektioner i dette læringsspor gratis i deres fulde længde — derefter låser CoddyKit PRO alle lektioner op samt praktiske øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. Den er en del af læringsforløbet i Bootcamp i FastAPI-backendudvikling, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. Bootcamp i FastAPI-backendudvikling-kurset indeholder 4 lektioner i alt.
Hvorfor Celery Beat?
Din FastAPI-app kan uden problemer starte enkeltstående baggrundsopgaver med Celery, men noget arbejde skal køre efter en tidsplan: send en opsummeringsmail hver morgen, udløb forladte indkøbskurve hvert 10. minut, eller genberegn analyser hver nat.
Celery Beat er en planlægningsproces. Den udfører ikke selv opgaver — den vågner ved hvert tidsinterval, afgør hvilke opgaver der skal køres, og lægger dem på brokeren (Redis/RabbitMQ). Dine normale celery worker-processer henter dem og kører dem.
- Beat = uret, der udgiver opgaver, som skal køres.
- Worker = den kraft, der kører dem.
Denne adskillelse er hele grunden til, at periodiske job kan skaleres: én Beat, mange workers.
Definering af tidsplanen
Tidsplaner ligger på Celery-appen under conf.beat_schedule. Hver post knytter et navn til en ordbog med stien til opgaven, en tidsplan (sekunder, timedelta eller en crontab) og valgfrie args/kwargs.
Den enkleste tidsplan er et fast interval. Herunder kører oprydningsopgaven hvert 30. sekund. Strengen med opgavens sti skal stemme nøjagtigt overens med workerens registrerede navn.
from celery import Celery
from datetime import timedelta
app = Celery("jobs", broker="redis://localhost:6379/0")
@app.task(name="tasks.cleanup_sessions")
def cleanup_sessions():
# delete expired sessions from the DB
return "cleaned"
app.conf.beat_schedule = {
"cleanup-every-30s": {
"task": "tasks.cleanup_sessions",
"schedule": timedelta(seconds=30),
},
}Crontab-tidsplaner med crontab()
Faste intervaller er grove. Til egentlig kalenderlogik — "hver hverdag kl. 07:30" — skal du bruge celery.schedules.crontab. Den afspejler Unix-crons felter: minute, hour, day_of_week, day_of_month, month_of_year.
crontab(minute=0, hour=0)— midnat hver dag.crontab(minute="*/15")— hvert 15. minut.crontab(hour=7, minute=30, day_of_week="1-5")— kl. 07:30 mandag–fredag.
Felter, der ikke er angivet, får som standard værdien * (alle værdier), præcis som en crontab-linje.
from celery.schedules import crontab
app.conf.beat_schedule = {
"morning-digest": {
"task": "tasks.send_digest",
"schedule": crontab(hour=7, minute=30, day_of_week="1-5"),
},
"quarter-hour-sync": {
"task": "tasks.sync_inventory",
"schedule": crontab(minute="*/15"),
},
}Angivelse af argumenter og indstillinger pr. post
Hver tidsplanpost kan indeholde argumenter og indstillinger for det enkelte kald. Brug args (positionsargumenter) eller kwargs (navngivne argumenter) til at konfigurere den samme opgave forskelligt i forskellige poster. Ordbogen options lader dig sende en periodisk opgave til en bestemt queue, angive expires eller tilsidesætte prioriteten.
expires er vigtigt for periodiske job: Hvis Beat lægger en opgave i kø, men workers er overbelastede, kasseres en udløbet meddelelse i stedet for at blive kørt for sent og hobe sig op.
from celery.schedules import crontab
app.conf.beat_schedule = {
"warm-cache-eu": {
"task": "tasks.warm_cache",
"schedule": crontab(minute="*/5"),
"kwargs": {"region": "eu-west"},
"options": {"queue": "cache", "expires": 120},
},
"warm-cache-us": {
"task": "tasks.warm_cache",
"schedule": crontab(minute="*/5"),
"kwargs": {"region": "us-east"},
"options": {"queue": "cache", "expires": 120},
},
}Registrering af tidsplaner med en dekorator
I stedet for én stor ordbog med beat_schedule kan du registrere poster tæt på opgaverne ved hjælp af signalet on_after_configure og app.add_periodic_task. Det holder tidsplanen sammen med den kode, den udløser, og undgår forældede strengstier.
add_periodic_task(schedule, signature, name=...) tager først intervallet eller crontab'en og derefter opgavesignaturen. Du kan sende task.s(arg) for at indbygge argumenter.
from celery import Celery
from celery.schedules import crontab
app = Celery("jobs", broker="redis://localhost:6379/0")
@app.task
def rotate_logs(target):
return f"rotated {target}"
@app.on_after_configure.connect
def setup_periodic_tasks(sender, **kwargs):
sender.add_periodic_task(
crontab(hour=3, minute=0),
rotate_logs.s("app.log"),
name="nightly-log-rotation",
)Tidszoner: fejl nummer 1 i tidsplaner
Som standard fortolker Celery crontab-tider i UTC. Hvis du skriver crontab(hour=7) i forventning om lokal tid kl. 07:00, bliver opgaven kørt på det forkerte klokkeslæt. Angiv altid tidszonen eksplicit, og vælg den bevidst.
timezone— den zone, som crontab-tider evalueres i.enable_utc=True— behold interne tidsstempler i UTC (anbefalet), mens crontab'er stadig evalueres i den valgtetimezone.
Fastlås tidszonen i konfigurationen, så alle udviklere og servere er enige, uanset værtens lokale TZ.
app.conf.update(
timezone="Europe/Istanbul",
enable_utc=True,
)
# crontab(hour=9, minute=0) now means 09:00 Europe/Istanbul,
# stored/transmitted internally as UTC.Kørsel af Beat og den permanente tidsplansfil
Du starter planlæggeren som sin egen proces. Standardplanlæggeren gemmer tilstanden for "seneste kørsel" i en lille fil, så den ikke kører alt igen efter en genstart.
celery -A app beat -l info— kør Beat.--schedule /var/run/celerybeat-schedule— hvor shelve-tilstandsfilen ligger.- Du kan køre worker og Beat sammen under udvikling med
celery -A app worker -B, men brug aldrig-Bi produktion — det binder uret til én workers livscyklus.
I produktion skal du køre præcis én Beat-proces. To Beats betyder, at alle periodiske opgaver køres to gange.
Reglen om én planlægger på tværs af workers
Du kan skalere workers vandret til dusinvis af pods, og Celery håndterer det: brokeren fordeler hver meddelelse i køen til præcis én worker. Men Beat er uret, og du må kun køre ét ur.
Hvis to Beat-processer kører, afgør hver af dem uafhængigt, at en opgave skal køres, og udgiver den derfor, så abonnenter ser dublerede kørsler. Almindelige måder, det sker ved et uheld:
- To replikaer af en pod, som begge starter
beat. - Brug af
worker -B, hvorefter worker-installationen skaleres til 2 eller flere replikaer.
Løsning: en dedikeret Beat-Deployment med replicas: 1, adskilt fra den worker-Deployment, du skalerer frit.
Idempotens: design opgaver, så de overlever dubletter
Selv med én Beat opstår der dubletter — en Beat-genstart på det forkerte sekund, en levering igen fra en broker, der leverer mindst én gang, eller en operatørfejl. Det robuste forsvar er at gøre periodiske opgaver idempotente: at køre dem to gange har samme effekt som at køre dem én gang.
Et enkelt mønster er en kortvarig distribueret lås i Redis ved hjælp af SET NX med en udløbstid. Den, der får låsen, udfører arbejdet; samtidige eller dublerede kørsler springes sikkert over.
import redis
r = redis.Redis(host="localhost", port=6379, db=0)
@app.task(name="tasks.charge_subscriptions")
def charge_subscriptions():
# acquire a lock valid for 300s; only one runner proceeds
got = r.set("lock:charge_subscriptions", "1", nx=True, ex=300)
if not got:
return "skipped: already running"
try:
# ... perform the billing run exactly once ...
return "charged"
finally:
r.delete("lock:charge_subscriptions")Databaseunderstøttede tidsplaner med django-celery-beat / RedBeat
Standardfilplanlæggeren betyder, at ændring af en tidsplan kræver redigering af kode og genstart af Beat. Til dynamiske tidsplaner har du brug for et backend-lager, som du kan redigere under kørsel.
- RedBeat — gemmer tidsplaner i Redis; velegnet til en Redis-baseret FastAPI-stack. Angiv
beat_scheduler = "redbeat.RedBeatScheduler". - django-celery-beat — gemmer poster i SQL-tabeller, som kan redigeres via en administrationsgrænseflade.
RedBeat leverer også en Redis-baseret lås, så hvis du ved en fejl starter to Beats, er det kun én, der er den aktive planlægger — et sikkerhedsnet for reglen om ét ur.
app.conf.update(
redbeat_redis_url="redis://localhost:6379/1",
beat_scheduler="redbeat.RedBeatScheduler",
beat_max_loop_interval=5,
)En selvstændig kontrol af, om en cron-opgave skal køres
For at opbygge en intuition for, hvad Beat gør ved hvert tidsinterval, får du her en lille selvstændig simulering: Givet en liste med cron-lignende job (interval i sekunder og et tidsstempel for seneste kørsel) afgør den, hvilke der skal køres nu. Dette er den centrale løkke, Beat udfører — sammenlign "nu" med "næste kørsel" — uden en broker.
def due_jobs(now, jobs):
fired = []
for name, interval, last_run in jobs:
if now - last_run >= interval:
fired.append(name)
return fired
jobs = [
("cleanup", 30, 0),
("digest", 3600, 3500),
("sync", 900, 100),
]
now = 1000
print(due_jobs(now, jobs)) # ['cleanup', 'sync']Hurtigt tjek: undgå dublerede periodiske kørsler
Du udruller en FastAPI- og Celery-stack til Kubernetes. For at håndtere belastningen skalerer du din worker-Deployment til 4 replikaer, og hver worker startes med celery -A app worker -B. Periodiske opgaver begynder at køre 4 gange hver. Hvad er den korrekte løsning?
Opsummering
Du kan nu planlægge tilbagevendende arbejde med Celery Beat:
- Beat planlægger, workers udfører — Beat publicerer forfaldne opgaver til message broker'en; én Beat-instans og mange workers.
- Planer findes i
beat_scheduleeller viaadd_periodic_task; brugtimedeltatil intervaller ogcrontab()til kalenderlogik. - Argumenter/indstillinger pr. post parametriserer opgaver og indstiller
queue/expiresfor at undgå ophobning af forældede opgaver. - Tidszoner er som standard UTC — angiv
timezoneogenable_utceksplicit. - Kun ét ur — brug aldrig
worker -Bi produktion; kør én dedikeret Beat-replika. - Idempotens (Redis-
SET NX-låse) beskytter mod duplikerede eller genleverede kørsler. - RedBeat / django-celery-beat giver redigerbare, persistente og låsebeskyttede planer under kørsel.
Lær Bootcamp i FastAPI-backendudvikling med en AI-underviser — gratis
Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.
- Kurser
- 21
- Lektioner
- 84
Ofte stillede spørgsmål
Er lektionen “Planlagte og periodiske jobs med Celery Beat” gratis?
Ja — alle 3 lektioner i læringssporet Bootcamp i FastAPI-backendudvikling, inklusive “Planlagte og periodiske jobs med Celery Beat”, kan læses gratis i deres fulde længde her på webstedet. Derefter låser CoddyKit PRO alle lektioner op samt interaktive øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. Bootcamp i FastAPI-backendudvikling-kurset indeholder 4 lektioner i alt.
Hvad lærer jeg i “Planlagte og periodiske jobs med Celery Beat”?
Kør tilbagevendende jobs med Celery Beat, og koordinér cron-lignende planer sikkert på tværs af flere workers. Du øver dig i Bootcamp i FastAPI-backendudvikling med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.
Skal jeg have erfaring for at begynde på Bootcamp i FastAPI-backendudvikling?
Der kræves ingen tidligere erfaring. Bootcamp i FastAPI-backendudvikling på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 4 af 4.
Hvor lang tid tager lektionen “Planlagte og periodiske jobs med Celery Beat”?
De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.
Kan jeg skrive og køre kode i denne Bootcamp i FastAPI-backendudvikling-lektion?
Ja. Alle Bootcamp i FastAPI-backendudvikling-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.
Alle lektioner i dette kursus
- Letvægtsaflastning med BackgroundTasks
- Forbindelse af Celery-workers til en FastAPI-app
- Retries, idempotens og dead-letter-håndtering
- Planlagte og periodiske jobs med Celery Beat