[ OK ]Çekirdek başlatılıyor...
~/im/blog
Benimle Çalışın

Konuşalım

Birlikte çalışmakla ilgileniyor ya da bir sorunuz mu var? Yeni projeleri konuşmaya her zaman açığım.

İletişime geçin

Bağlantı Kurun

Beni sosyal medyada ve profesyonel ağlarda bulabilirsiniz.

Gizlilik Politikası (KVKK)Kullanım Koşulları
© 2026 Irfan MiralGeliştirici:irfanMiral.com
AnasayfaHakkımda/ÖzgeçmişBlogİletişim
2026-08-05• 5 dakika okuma

Bir Queue Tablosu Yetmediğinde: RabbitMQ'ya Geçiş

Veritabanları RabbitMQ Message Queue'lar Mimari

Şaşırtıcı sayıda production sistemi background işi aynı şekilde handle ediyor: bir jobs tablosu, bir status column'ı (pending, processing, done, failed), ve bunu bir loop'ta poll eden, pending row'ları alıp ilerlerken status'larını güncelleyen bir ya da daha fazla worker. Bu başlamak için tamamen mantıklı bir yol. Yeni bir altyapı gerektirmiyor, incelemesi kolay (SELECT * FROM jobs WHERE status = 'failed', herkesin zaten nasıl kullanacağını bildiği bir debugging tool'u), ve düşük volume'lerde uzun süre sorunsuz çalışıyor.

Bunun büyüdüğünün işaretleri genelde abstract olarak "çok fazla volume" değil. Bundan daha spesifikler.

Polling'in kendisi yük haline geliyor

Tabloyu birkaç saniyede bir kontrol eden her worker, yapılacak bir iş olsun olmasın bir query. Düşük volume'de bu ihmal edilebilir. Tablo büyüdükçe ve throughput için daha fazla worker eklendikçe, bu polling, database'de desteklemesi gereken asıl application query'leriyle rekabet eden sürekli bir background yük haline geliyor, ve SELECT ... FOR UPDATE SKIP LOCKED (bunu güvenli şekilde yapmanın doğru yolu) yine de her worker'ın her cycle'da aynı tabloya vurduğu gerçeğini değiştirmiyor.

Retry ve failure handling kötü bir şekilde yeniden icat ediliyor

Bir queue tablosunun retry logic'i genelde bir retry_count column'ı ve onu artırıp job'ı yeniden kuyruğa alan application code, ta ki olmayana kadar: fail etmeden önce kısmen tamamlanmış job'lar etrafındaki edge case'ler, iki worker aynı anda poll ettiği için iki kere alınan job'lar, ya da neden olduğuna bakmanın net bir yolu olmadan biriken failed job'lar, zamanla özel durumlar olarak birikme eğiliminde. Bunlar zor problemler değil, ama bir message queue'nun yıllar önce çözdüğü problemler, ve bunları application code'da yeniden çözmek, edge case'lerini de yeniden çözmek demek.

RabbitMQ gerçekte neyi değiştiriyor

RabbitMQ modeli polling'den push'a çeviriyor: bir producer bir exchange'e bir mesaj publish ediyor, RabbitMQ bunu binding'lere göre bir queue'ya route ediyor, ve consumer'lar tekrar tekrar sormak yerine mesajları geldikçe alıyor:

# Producer
channel.basic_publish(
    exchange='',
    routing_key='email_notifications',
    body=json.dumps({'user_id': 123, 'template': 'welcome'}),
    properties=pika.BasicProperties(delivery_mode=2)  # persistent
)

# Consumer
def callback(ch, method, properties, body):
    process_notification(json.loads(body))
    ch.basic_ack(delivery_tag=method.delivery_tag)

channel.basic_consume(queue='email_notifications', on_message_callback=callback)

basic_ack sadece mesaj başarıyla işlendikten sonra ateşleniyor, consumer işlerken ortasında crash olursa, RabbitMQ mesajı yeniden deliver ediyor, çünkü hiç acknowledge edilmemişti. Failed mesajlar otomatik olarak bir dead-letter exchange'e route edilebiliyor, bu logic'i kendiniz yazmadan size incelenebilir, ayrı bir "fail olan şeyler" queue'su veriyor.

Ne aynı kalıyor, ne direkt transfer olmuyor

"Bir job'ın bir payload'ı ve bir status'u var" mental modeli yok olmuyor, RabbitMQ konsepti değiştirmiyor, delivery mekanizmasını değiştiriyor. Direkt transfer olmayanlar: bir debugging alışkanlığı olarak SELECT * FROM jobs WHERE status = 'failed', bunun yerine bir dead-letter queue'yu kontrol etmeye dönüşüyor, ki bu farklı (muhtemelen daha iyi de, oradaki mesajlar sadece yavaş değil, gerçekten deliver edilemez) bir şekle sahip. Ve queue tablosunun aynı transaction'da diğer application data'sıyla birlikte query edilebilir olmasına dayanan her şey, bir row'u ve ilgili bir queue entry'sini atomik olarak birlikte insert etmek gibi, queue artık ayrı bir sistem olduğu için yeniden düşünülmeli.

Tablonun hâlâ doğru seçim olduğu durum

Volume düşükse, job'lar basitse, ve birkaç saniyede bir poll eden bir avuç worker database'de yük olarak görünmüyorsa, bir queue tablosu bir hata değil, problem için uygun boyutlandırılmış. RabbitMQ'ya geçiş, polling yükü database metric'lerinde görünür hale geldiğinde, application code'daki retry ve failure handling kendi edge case setini büyüttüğünde, ya da birden fazla farklı service'in aynı event'leri üretmesi ya da consume etmesi gerektiğinde değer kazanıyor, bu noktada tam olarak bunun için tasarlanmış bir message broker "ekstra altyapı" olmaktan çıkıp daha basit seçenek olmaya başlıyor.

ÖncekiCache Olarak Redis vs Database Olarak RedisSonraki Yavaş Bir WordPress Sitesini Hızlandırmak: Gerçek Çalışma Sırası