Problem
Problem
Geçtiğimiz yıl, Portekiz’de büyüyen bir berber dükkanları ağı için bir rezervasyon sistemi geliştirmek üzere işe alındım. İlk ihtiyaçlar basit görünüyordu: müşterilerin çevrimiçi randevu almasını sağlamak. Ancak sistem 5 dükkandan 50+ dükkana ölçeklendiğinde, beklenenden çok daha karmaşık bir mimari yapı oluşturma zorlukları ile karşılaştık.
İlk Mimari: MVP
İlk Mimari: MVP
Laravel ve PostgreSQL kullanarak geleneksel bir istek-cevap modeliyle başladık:
Client → API → Database → Email Queue → Email Service
Basit. Küçük trafik için işe yaradı. Ancak yük altında çökmeye başladı.
Problem: Her rezervasyon:
- Veritabanı yazma
- Berber için e-posta bildirimi
- Müşteri için e-posta onayı
- 3 farklı entegrasyonla takvim senkronizasyonu
- SMS hatırlatma planlama
Hepsi senkron olarak. Tek bir yavaş işlem tüm isteği engelledi.
Ölçekleme Problemi
Ölçekleme Problemi
6. ayda, elimizde:
- 50 berber dükkanı
- 3.000 günlük rezervasyon
- Cevap süreleri 200 ms’den 2-3 saniyeye düştü
- Müşterilerin onaylarını 30+ saniye sonra aldığı
Senkron model artık geçerli değildi.
Çözüm: Her Şeyi Asenkron Yapmak
Çözüm: Her Şeyi Asenkron Yapmak
Sistemi RabbitMQ ile mesaj kuyruklama kullanarak yeniden yapılandırdık:
Client → API (Hızlı) ↓
Queue → Workers (Paralel İşleme)
├→ Email Worker
├→ SMS Worker
├→ Calendar Sync Worker
├→ Analytics Worker
└→ Notification Worker
Sonuç: API cevap süresi 2.5 saniyeden 180 ms’ye düştü. Müşteriler anında onay aldı.
Ana Teknik Kararlar
Ana Teknik Kararlar
1. Eşzamanlılık için Veritabanı Tasarımı
1. Eşzamanlılık için Veritabanı Tasarımı
Randevu slotları için optimist locking uyguladık:
CREATE TABLE appointments (
id BIGINT PRIMARY KEY,
barber_id BIGINT,
time_slot_id BIGINT,
customer_id BIGINT,
version INT DEFAULT 1,
status ENUM('pending', 'confirmed', 'completed', 'cancelled'),
created_at TIMESTAMP,
updated_at TIMESTAMP,
UNIQUE KEY(time_slot_id, version)
);
Neden? Çift rezervasyon engeli için pahalı kilitler olmadan. version sütunu, atomik güncellemelerin yalnızca başka bir süreç kaydı değiştirmediğinde başarılı olmasını sağlar.
2. Zaman Dilimi Karmaşıklığını Yönetme
2. Zaman Dilimi Karmaşıklığını Yönetme
Bizi şaşırtan bir sorun: farklı zaman dilimlerinde randevu alan uluslararası müşteriler.
// Her şeyi içsel olarak UTC olarak sakla
$appointment = Appointment::create([
'scheduled_at' => $request->scheduled_at->setTimezone('UTC'),
'barber_timezone' => $barber->timezone,
'customer_timezone' => Auth::user()->timezone,
]);
// Müşterinin zaman diliminde döndür
return $appointment->scheduled_at
->setTimezone($customer->timezone)
->format('Y-m-d H:i');
3. Kuyruk Güvenilirliği
3. Kuyruk Güvenilirliği
Kolay yoldan öğrendik: mesaj kuyrukları ölü mektup yönetimi gerektirir.
// Başarısız işleri eksponansiyel geri dönüş ile tekrar dene
Queue::job(SendConfirmationEmail::class)
->tries(5)
->backoff([1, 5, 10, 30, 60]) // saniye
->retryUntil(now()->addHours(24))
->dispatch($appointment);
Başarısız e-postalar derhal inceleme için ölü mektup kuyruğuna gitti ve sessizce başarısız olmadı.
Performans Metrikleri
Performans Metrikleri
Optimizasyondan sonra:
| Metrik | Önce | Sonra | Değişim |
|---|---|---|---|
| API Cevap Süresi | 2.5s | 180ms | %93 daha hızlı |
| Rezervasyon Başarı Oranı | %94 | %99.7 | Çift rezervasyon engellendi |
| Müşteri Memnuniyeti | 3.2/5 | 4.7/5 | Daha hızlı onaylar |
| Eşzamanlı Rezervasyonlar | 5/saniye | 150/saniye | 30 kat kapasite |
Farklı Olacaklarımız
Farklı Olacaklarımız
- 1. İlk günden asenkron olarak başlamak – Büyüme aşamasında kuyruk sistemini yeniden inşa ettik. Acı vericiydi.
- 2. İzlemeyi daha erken uygulamak – Bottleneck’leri müşteri şikayetleri aracılığıyla keşfettik, paneller vasıtasıyla değil.
- 3. Aşırı sınamaları daha fazla yapmak – 11 PM rezervasyonları, gece yarısı geçişleri, yaz saati uygulaması gibi durumlar üretimde debelenmemize sebep oldu.
Ders
Ders
Bir rezervasyon sistemi görünüşte bir programlama problemidir ama aslında bir eşzamanlılık problemidir. İş mantığı basit. Mühendislik ise değil.
Aynı anda:
- Birden fazla kullanıcı aynı kaynağa (randevu slotları) erişmeye çalışıyorsa
- Zaman hassasiyeti olan işlemler (onayların anında olması gerekir)
- Dağıtılmış işler (birden fazla entegrasyon)
…eşzamanlılık için tasarlanmış bir sisteme ihtiyacınız var, kolaylığa değil.
Benzer zorluklarla dağıtılmış sistemler geliştirdiniz mi? Yorumlarda yaklaşımınızı paylaşın — özellikle zaman dilimi problemini daha iyi nasıl çözdüğünüzü!
Kaynak: Orijinal Makale


