Redis छोड़कर SolidQueue पर जाने के कारण
(simplethread.com)- Rails 8 डिफ़ॉल्ट स्टैक से Redis dependency को हटाता है और SolidQueue·SolidCache·SolidCable के ज़रिए सभी कामों को relational database (RDB) पर प्रोसेस करने की ओर शिफ्ट करता है
- Redis तेज़ और भरोसेमंद है, लेकिन इससे configuration·security·cluster management·backup जैसी operational complexity बढ़ती है
- SolidQueue, PostgreSQL की
FOR UPDATE SKIP LOCKEDसुविधा का उपयोग करके lock contention के बिना parallel job processing लागू करता है - recurring jobs, concurrency control, monitoring dashboard (Mission Control) जैसी Redis+Sidekiq की paid features को मुफ़्त में उपलब्ध कराता है
- ज़्यादातर Rails applications के लिए SolidQueue काफ़ी है; केवल ultra-fast·real-time processing वाले कुछ मामलों में ही Redis बनाए रखने की ज़रूरत है
Redis की छिपी हुई लागत
- Redis in सिर्फ़ hosting cost नहीं, बल्कि installation·maintenance·security configuration·HA cluster management जैसी लगातार operational overhead भी होती है
- Rails और Redis के बीच network connection और firewall setup, client authentication, Sidekiq process orchestration की ज़रूरत होती है
- समस्या आने पर Redis और RDBMS दोनों systems को साथ में debug करना पड़ता है, और dual backup strategy भी चाहिए
- इसके उलट, Redis के बिना Rails stack में सिर्फ़ PostgreSQL एक ही manage करना होता है, जिससे चीज़ें सरल हो जाती हैं
SolidQueue कैसे काम करता है
- PostgreSQL की
FOR UPDATE SKIP LOCKEDसुविधा का इस्तेमाल करके कई workers lock contention के बिना एक साथ jobs उठा लेते हैं - मुख्य table structure
solid_queue_jobs: job metadata स्टोर करता हैsolid_queue_scheduled_executions: scheduled jobs की प्रतीक्षाsolid_queue_ready_executions: execution के लिए तैयार job queue
- worker·dispatcher·scheduler·supervisor processes अलग-अलग tables को समय-समय पर poll करते हुए आपस में सहयोग करते हैं
- PostgreSQL के MVCC design और autovacuum की वजह से भारी मात्रा में insert·delete operations भी स्थिर रूप से संभाले जा सकते हैं
recurring job scheduling
- SolidQueue, cron style recurring jobs को डिफ़ॉल्ट रूप से सपोर्ट करता है, और इसे
config/recurring.ymlफ़ाइल में configure किया जाता है - scheduler, execution time आने पर job को queue में डालता है और अगला execution time अपने-आप schedule कर देता है
- Fugit library natural language schedules को parse करती है, और Concurrent::ScheduledTask threads बनाता है
- GoodJob की deterministic scheduling पद्धति अपनाने से process restart के बाद भी schedule बना रहता है
concurrency control फीचर
- SolidQueue, POSIX semaphore pattern का उपयोग करके job unit के हिसाब से concurrent execution limit सपोर्ट करता है
- उदाहरण:
limits_concurrency to: 1, key: ->(user) { user.id }सेट करने पर हर user के लिए एक समय में सिर्फ़ 1 job चलेगी
- उदाहरण:
- semaphore expiry (
duration) सेट करके job conflict और deadlock से बचाव किया जा सकता है - संबंधित tables
solid_queue_semaphores: concurrency limits को track करता हैsolid_queue_blocked_executions: प्रतीक्षा कर रहे jobs को स्टोर करता है
Mission Control से monitoring
- Mission Control Jobs Rails 8 के लिए एक मुफ़्त open source dashboard है, जिसे
/jobspath पर आसानी से mount किया जा सकता है - मुख्य फीचर्स
- real-time queue status, failed jobs tracking, retry/discard control
- scheduled·recurring jobs timeline visualization
- queue-wise throughput और metrics graphs
- यह SQL-based queries सपोर्ट करता है, इसलिए अतिरिक्त tools के बिना सीधे database में analysis किया जा सकता है
Sidekiq से SolidQueue में migration
- चरण 1:
config.active_job.queue_adapter = :solid_queueसेट करें - चरण 2:
bundle add solid_queueके बादrails solid_queue:installऔरdb:migrateचलाएँ - चरण 3:
sidekiq.ymlके cron schedule कोrecurring.ymlमें बदलें - चरण 4:
Procfileमेंjobs: bundle exec rake solid_queue:startजोड़ें - चरण 5: Redis·Sidekiq से जुड़े gem हटा दें
- मौजूदा ActiveJob code बिना बदलाव के वैसे ही काम करेगा
जब Redis अब भी ज़रूरी हो
- प्रति सेकंड हज़ारों से अधिक लगातार job processing
- ऐसे real-time systems जहाँ 1ms से कम latency अनिवार्य हो
- complex pub/sub structure या advanced rate limiting·counter operations की ज़रूरत
- उदाहरण के लिए Shopify, प्रति सेकंड 833 requests और 1,172 worker processes चलाते हुए Redis infrastructure का उपयोग करता है
practical implementation guide
- Rails 8 में नया app बनाते समय SolidQueue·SolidCache·SolidCable अपने-आप configure हो जाते हैं
config/database.ymlमें अलग queue database connection सेट करने की सिफ़ारिश की जाती है- Mission Control authentication जोड़ें और
/jobsroute mount करें Procfile.devमेंjobs: bundle exec rake solid_queue:startजोड़करbin/devचलाने से पूरा stack शुरू हो जाता है- test jobs बनाने के बाद Mission Control में उनका status देखा जा सकता है
आम समस्याएँ और समाधान
- single database configuration भी संभव है, लेकिन इससे operational flexibility कम हो जाती है
- production environment में Mission Control के लिए authentication ज़रूर जोड़ें
- polling interval का डिफ़ॉल्ट मान scheduled jobs के लिए 1 सेकंड और immediate jobs के लिए 0.2 सेकंड है, जो ज़्यादातर apps के लिए उपयुक्त है
- ActionCable/Turbo Streams इस्तेमाल करते समय
SolidCableको अलग DB connection पर सेट करना चाहिए
scalability और performance
- SolidQueue ज़्यादातर Rails apps में पर्याप्त रूप से scale कर सकता है
- PostgreSQL आधारित होने के कारण प्रति सेकंड 200~300 jobs प्रोसेस कर सकता है, और 37signals रोज़ 2 करोड़ jobs बिना Redis के संभालता है
- तुलना तालिका
मद Redis + Sidekiq SolidQueue setup complexity अलग service चाहिए built-in DB का उपयोग query language Redis commands SQL monitoring अलग dashboard Mission Control failure scenarios 6 से अधिक 2 throughput हज़ारों jobs/second 200–300 jobs/second suitable for 99.9% apps 95% apps
निष्कर्ष
- Redis और Sidekiq बेहतरीन तकनीकें हैं, लेकिन ज़्यादातर Rails applications के लिए वे ज़रूरत से ज़्यादा complexity और cost लाते हैं
- SolidQueue एक single-database foundation पर operations को सरल, cost को कम और maintenance को अधिक efficient बनाता है
- Rails 8 के दौर में SolidQueue पर शिफ्ट डिफ़ॉल्ट विकल्प के रूप में सुझाया जाता है
2 टिप्पणियां
Redis अच्छा है, लेकिन।
Hacker News की राय
मेरा मानना है कि सभी open source लेखकों को अपने प्रोजेक्ट की सीमा नियंत्रित करने का अधिकार है
लेकिन हमारी टीम को good_job से SolidQueue पर जाना अब पछतावा लग रहा है
Basecamp, MySQL-केंद्रित है, इसलिए RDBMS engine-specific queries स्वीकार नहीं करता। GitHub issues देखें तो साफ दिखता है कि ध्यान सिर्फ MySQL performance पर है
साथ ही अभी तक batch jobs support भी नहीं है (संबंधित PR)
Complex JOINs में MySQL अक्सर query plan गलत बना देता है, इसलिए मैं STRAIGHT_JOIN से क्रम force करता हूँ। यह future-proofing के लिए है
मैं resque से migration के उम्मीदवार के रूप में इन दोनों की तुलना कर रहा हूँ। GoodJob, pg-only features की वजह से pgbouncer transaction mode के साथ compatible नहीं है
Session persistence चाहिए, जो झंझट है, लेकिन performance improvement ज़्यादातर scale पर बहुत मायने नहीं रखता
फिर भी GoodJob का development model और code readability कहीं ज़्यादा भरोसा देते हैं
अगर production environment सरल हो सके तो वह हमेशा अच्छी बात है
Rails में आदर्श स्थिति मुझे ऐसी लगती है जहाँ Redis पर आसानी से switch किया जा सके
अच्छा होगा अगर SolidQueue से शुरुआत करके scalability limit आने पर Redis पर जाया जा सके
ज़्यादातर Rails apps का traffic इतना बड़ा नहीं होता, इसलिए दोनों systems को बनाए रखना उल्टा complexity बढ़ाता है
बेशक कुछ apps किसी खास queue implementation पर निर्भर होते हैं, लेकिन आम तौर पर सिर्फ settings बदलनी होती हैं
क्या log बहुत बड़ा होने से रोकने के लिए snapshots भी साथ चलते हैं, और क्या यह distributed mode में भी काम करता है
खासकर जब job creation दूसरे DB changes के साथ हो, तब उस guarantee को खो देना समस्या है
Redis इस मामले में हल्का और स्वतंत्र state store होने की वजह से फायदेमंद था
SolidQueue इस separation को उतना स्पष्ट नहीं करता दिखता (riverqueue.com)
मैंने अपने side project में SolidQueue को आज़माया
निष्कर्ष यही है कि, अगर Sidekiq में कोई समस्या नहीं है तो बदलने की खास वजह नहीं है
Redis infrastructure हटाना हो तभी इस पर विचार किया जा सकता है
नए project के लिए GoodJob ज़्यादा mature है और उसकी community भी बेहतर है
SolidQueue का UI बहुत साधारण लगा, जिससे दिक्कत हुई। Index optimization नहीं था, इसलिए data बढ़ने पर page अटक जाता था
RDBMS इस्तेमाल करने पर connection pool management cost भी बढ़ती है, यह भी ध्यान में रखना चाहिए
scalability को लेकर चिंतित लोगों के लिए, Elixir के Oban benchmark को देखें
वह single node पर प्रति मिनट दस लाख jobs process करता है। ज़्यादातर apps का workload इससे बहुत कम होता है
उसमें 5000 jobs एक साथ batch में डाली जाती हैं, इसलिए असल TPS लगभग 200 ही है
Batch के बिना individual jobs डालें तो SQL transaction overhead कहीं ज़्यादा बढ़ जाता है
हम SolidQueue से पहले से ही jobs को DB में store करते आए हैं
इसका फायदा यह है कि production state को वैसे का वैसा development environment में snapshot किया जा सकता है
लेकिन rate limiter हम Redis में रखते हैं, ताकि DB load न बढ़े
DB-based queue की सीमा large payloads हैं
अगर बड़े JSON को queue में डालें तो DB write overhead की वजह से यह अक्षम हो जाता है
Redis (Sidekiq) ऐसे मामलों में कहीं तेज़ है
SolidQueue+SQLite सिर्फ primary key पास करने के लिए ठीक है
लेकिन अगर कई workers एक ही DB को poll करें तो जल्दी bottleneck बन जाता है
बड़े data को S3 जैसे external storage में रखना और सिर्फ reference भेजना बेहतर लगता है
क्या किसी ने benchmark results को संक्षेप में जुटाया है, यह जानने की जिज्ञासा है
SolidQueue में SKIP LOCKED का ज़िक्र है, लेकिन 15 मिनट चलने वाले job के लिए transaction खुला रखना जोखिम भरा है
लंबे समय तक खुली transactions DB performance बिगाड़ती हैं, और network disconnect पर भी कमज़ोर होती हैं
ऐसी संरचना anti-pattern की ओर ले जा सकती है। बाद में देखा तो शायद यह lease model है
मैं Postgres for everything वाली सोच से सहमत हूँ
सादगी के लिए सिर्फ PostgreSQL में एकीकरण अच्छा लगता है
इस उपमा का जवाब कैसे दूँ, समझ नहीं आता
complexity बढ़ाकर Redis चलाने की ज़रूरत है भी या नहीं, यही सवाल है
“ऐसा business जहाँ 1ms से कम latency महत्वपूर्ण हो” — क्या मतलब Rails में HFT चला रहे हैं?
Postgres दुनिया पर छा जाएगा