Python Celery Redis : les 8 étapes clés pour passer de zéro à opérationnel
Python Celery Redis : l'essentiel en un article — vrai code, schémas et étapes concrètes, extraits d'un cours de 24 leçons.
Tout le monde peut apprendre Python Celery Redis — à condition de suivre les étapes dans le bon ordre. On a condensé un cours complet de 24 leçons en un parcours clair, avec les extraits de code les plus utiles.
tl;dr
- Pourquoi Celery
- Redis essentials
- Celery setup
- Tasks et workflows
- Celery Beat
~$ cat ./parcours.md # Python Celery Redis — 8 chapitres
01
Pourquoi Celery
→ Limites du synchrone→ Architecture Broker / Worker / Backend+ 1 autres leçons
02
Redis essentials
→ Types de donnees Redis→ Pub/Sub et Streams+ 1 autres leçons
03
Celery setup
→ Premier worker et premiere task→ Configuration et best practices+ 1 autres leçons
04
Tasks et workflows
→ Retries et timeouts→ Chain, Group, Chord+ 1 autres leçons
05
Celery Beat
→ Tasks periodiques→ Crontab schedules+ 1 autres leçons
06
Monitoring
→ Flower dashboard→ Logs structures et Sentry+ 1 autres leçons
07
Patterns avancés
→ Rate limiting et quotas→ Idempotence et deduplication+ 1 autres leçons
08
Projet final pipeline ML email
→ Projet - Cahier des charges→ Implementation des tasks+ 1 autres leçons
🏁
Projet final
→ Tu repars avec un projet concret et démontrable
Scheduling dynamique via DB
NOTEObjectif — Permettre aux utilisateurs/admins de modifier les schedules sans redeployer.
Probleme du beat_schedule en code
NOTESi tu veux ajouter/modifier un schedule en prod, il faut redeployer. Pour des tasks user-defined (newsletters, rapports clients), il faut un scheduler dynamique.
django-celery-beat (recommande)
pip install django-celery-beat # settings.py INSTALLED_APPS = [..., "django_celery_beat"] CELERY_BEAT_SCHEDULER = "django_celery_beat.schedulers:DatabaseScheduler" # Run migrations python manage.py migrate # Beat lit le schedule depuis la DB toutes les 5s celery -A myproject beat -l info
Tables creees
Creer un schedule via Python
from django_celery_beat.models import CrontabSchedule, PeriodicTask # 1. Definir le timing schedule, _ = CrontabSchedule.objects.get_or_create( minute="30", hour="9", day_of_week="mon-fri", day_of_month="*", month_of_year="*", timezone="Europe/Paris" ) # 2. Creer la task periodique PeriodicTask.objects.create( crontab=schedule, name="Newsletter Acme Corp", task="app.tasks.send_newsletter", args=json.dumps(["acme_corp"]), kwargs=json.dumps({"template": "weekly"}), enabled=True, one_off=False, )
API admin via Django admin
# L'admin Django expose deja les modeles # Tu peux directement aller a /admin/django_celery_beat/periodictask/ # pour ajouter, editer, desactiver via UI
API REST personnalisee
@app.post("/schedules") def create_schedule(data: ScheduleCreate, db: Session = Depends(get_db)): schedule = CrontabSchedule.objects.create( minute=data.minute, hour=data.hour, ... ) PeriodicTask.objects.create( name=data.name, crontab=schedule, task=data.task_name, args=json.dumps(data.args) ) return {"status": "created"} @app.delete("/schedules/{name}") def delete_schedule(name: str): PeriodicTask.objects.filter(name=name).delete()
Sans Django : celery-redbeat
pip install celery-redbeat # celery_app.py celery_app.conf.beat_scheduler = "redbeat.RedBeatScheduler" celery_app.conf.redbeat_redis_url = "redis://redis:6379/2" # Creer un schedule from redbeat import RedBeatSchedulerEntry from celery.schedules import crontab entry = RedBeatSchedulerEntry( name="my-task", task="app.tasks.my_task", schedule=crontab(hour=9, minute=0), app=celery_app, args=["arg1"] ) entry.save() # Supprimer entry.delete()
Cas d'usage : newsletters multi-tenant
# Modele DB class Newsletter(models.Model): name = models.CharField(max_length=200) schedule_cron = models.CharField(max_length=100) # "0 9 * * mon" enabled = models.BooleanField(default=True) def save(self, *args, **kwargs): super().save(*args, **kwargs) self.sync_celery_beat() def sync_celery_beat(self): m, h, dom, mon, dow = self.schedule_cron.split() schedule, _ = CrontabSchedule.objects.get_or_create( minute=m, hour=h, day_of_month=dom, month_of_year=mon, day_of_week=dow ) PeriodicTask.objects.update_or_create( name=f"newsletter_{self.id}", defaults={ "crontab": schedule, "task": "app.tasks.send_newsletter", "args": json.dumps([self.id]), "enabled": self.enabled } )
Projet - Cahier des charges
NOTEMission — Construire un systeme de recommandation produits envoye par email aux clients chaque semaine.
Specifications
NOTEFonctionnel :
- Pour chaque user actif : recuperer historique d'achat
- Generer 5 recommandations via ML (cosine similarity ou modele plus avance)
- Composer un email HTML personnalise
- Envoyer via SendGrid avec retry
- Tracker delivery, open, click
- Frequence : hebdomadaire, lundi 9h
- Scale : 100k+ users
- Idempotence : pas de double envoi
- Rate limit SendGrid : 100 emails/seconde
- Reprise sur erreur sans tout rejouer
Architecture cible
+---------------+
| Celery Beat | cron mon 9h
| (1 instance) |
+-------+-------+
|
v
+---------------+ +-----------+
| dispatch_ |---> | Redis |
| weekly_emails | | broker |
| (1 task) | +-----+-----+
+---------------+ |
v
+------------+------------+
| |
+-------v------+ +--------v-------+
| Worker emails| | Worker ML |
| (10 procs) | | (2 procs, GPU) |
+-------+------+ +--------+-------+
| |
v v
+-------+------+ +--------+-------+
| SendGrid | | Modele Recommandation|
| (rate limit) | | + DB historique|
+--------------+ +----------------+
|
v
+-------+------+
| Webhook |
| open/click |
+--------------+Structure du projet
recommender/ ├── docker-compose.yml ├── Dockerfile ├── requirements.txt ├── app/ │ ├── celery_app.py │ ├── config.py │ ├── tasks/ │ │ ├── orchestrator.py # dispatch_weekly_emails │ │ ├── ml.py # compute_recommendations │ │ ├── email.py # render + send │ │ └── tracking.py # webhooks │ ├── models/ # SQLAlchemy │ ├── ml/ │ │ └── recommender.py │ └── templates/ │ └── weekly.html └── tests/
Modeles DB
class User(Base): id: Mapped[int] = mapped_column(primary_key=True) email: Mapped[str] active: Mapped[bool] = mapped_column(default=True) last_recos_sent: Mapped[datetime | None] class Product(Base): id: Mapped[int] = mapped_column(primary_key=True) name: Mapped[str] category: Mapped[str] embedding: Mapped[list[float]] # vector pour ML class Order(Base): id: Mapped[int] = mapped_column(primary_key=True) user_id: Mapped[int] = mapped_column(ForeignKey("users.id")) product_id: Mapped[int] = mapped_column(ForeignKey("products.id")) created_at: Mapped[datetime] class EmailJob(Base): """Track envois pour idempotence""" id: Mapped[int] = mapped_column(primary_key=True) user_id: Mapped[int] = mapped_column(ForeignKey("users.id")) week_key: Mapped[str] # "2026-W21" status: Mapped[str] # pending|sent|failed|opened|clicked sendgrid_msg_id: Mapped[str | None] created_at: Mapped[datetime] = mapped_column(default=datetime.utcnow) __table_args__ = (UniqueConstraint("user_id", "week_key"),)
Configuration multi-queue
celery_app.conf.task_queues = (
Queue("orchestrator"),
Queue("ml"),
Queue("emails"),
Queue("tracking"),
)
celery_app.conf.task_routes = {
"app.tasks.orchestrator.*": {"queue": "orchestrator"},
"app.tasks.ml.*": {"queue": "ml"},
"app.tasks.email.*": {"queue": "emails"},
"app.tasks.tracking.*": {"queue": "tracking"},
}
celery_app.conf.beat_schedule = {
"weekly-recos": {
"task": "app.tasks.orchestrator.dispatch_weekly_emails",
"schedule": crontab(hour=9, minute=0, day_of_week="mon")
}
}SLOs cibles
NOTE
- Tous les emails envoyes en < 2h pour 100k users
- Taux d'echec final < 0.5%
- Latence webhook tracking < 1s
- Resilience : si SendGrid down 10min, reprise automatique
Resume
NOTEA retenir
- Separer ML (lourd), emails (debit), orchestrator (controle)
- EmailJob avec UniqueConstraint = idempotence
- Beat pour declenchement hebdo
- Tracking via webhook SendGrid
Persistance et eviction
NOTEObjectif — Configurer la persistance et l'eviction memoire en production.
RDB : snapshots
# redis.conf save 900 1 # snapshot si >=1 modif en 15min save 300 10 # snapshot si >=10 modifs en 5min save 60 10000 # snapshot si >=10000 modifs en 1min dbfilename dump.rdb dir /var/lib/redis
NOTERDB : snapshot binaire compact, restore rapide. Mais peut perdre quelques minutes en cas de crash.
AOF : append-only log
# redis.conf appendonly yes appendfilename "appendonly.aof" appendfsync always # lent mais 0 perte appendfsync everysec # defaut : 0-1s de perte appendfsync no # OS decide auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb
NOTEAOF : chaque ecriture logged. Plus de garanties, mais plus gros sur disque.
Hybride : RDB + AOF
# Recommande en prod : les deux actives save 900 1 appendonly yes appendfsync everysec # Au restart : Redis charge AOF (plus a jour)
maxmemory et eviction
# Limite memoire maxmemory 2gb # Politique quand plein maxmemory-policy allkeys-lru # supprime les moins recemment utilises (cache)
Politiques d'eviction
| Politique | Comportement |
|---|---|
| noeviction | Rejette les ecritures (defaut) |
| allkeys-lru | Supprime LRU sur toutes les cles |
| volatile-lru | LRU sur cles avec TTL |
| allkeys-lfu | Moins frequemment utilisees |
| allkeys-random | Aleatoire |
| volatile-ttl | Cle avec TTL la plus courte d'abord |
Backups
# Snapshot manuel redis-cli BGSAVE # asynchrone redis-cli SAVE # synchrone (bloquant !) # Copier le dump cp /var/lib/redis/dump.rdb /backup/dump-$(date +%F).rdb # Restore systemctl stop redis cp /backup/dump-2026-05-27.rdb /var/lib/redis/dump.rdb systemctl start redis
Replication master-replica
# Sur le replica replicaof master.redis.local 6379 # Verifier redis-cli INFO replication # role:slave # master_link_status:up # Failover automatique : Redis Sentinel # Sharding : Redis Cluster
va-plus-loin
Cet article couvre les extraits les plus utiles — le cours complet Python Celery Redis (8 chapitres, 24 leçons, exercices corrigés et projet final) t'emmène jusqu'au bout.
./acceder-au-cours-complet cours gratuit : Vibe CodingFAQ
Combien de temps pour apprendre Python Celery Redis ?
Avec une progression structurée (8 chapitres, 24 leçons courtes et pratiques), on atteint un niveau opérationnel en quelques semaines à raison de 30 à 60 minutes par jour. L'important est de pratiquer chaque notion immédiatement.
Faut-il des prérequis ?
Des bases en informatique suffisent. Si tu sais utiliser un terminal et lire du code simple, tu es prêt.
Par où commencer concrètement ?
Reproduis les commandes de cet article, puis suis le cours complet Python Celery Redis : il enchaîne les 24 leçons dans l'ordre, avec exercices et projet final.
./a-lire-aussi
→ Lance-toi en Portfolio IA SEO Vercel : ton premier pas concret aujourd'hui→ IA Stripe GitHub SaaS en pratique : le code et les commandes qui comptent vraiment→ Python Requests APIs expliqué simplement (avec schémas et vrai code)📬 Tu veux recevoir ce type de guide chaque semaine ? Abonne-toi gratuitement — code réel, zéro blabla.