VPN کے ذریعے Redis سست محسوس ہوتا ہے: فی درخواست راؤنڈ ٹرپ کم کریں
VPN دور دراز کی Redis کال کو مقامی نہیں بناتا۔ فی درخواست راؤنڈ ٹرپ کا بجٹ بنائیں، کنکشن دوبارہ استعمال کریں، اور pipeline کو ٹرانزیکشنز سے دور رکھیں۔
مقامی Redis کے ساتھ 200 ms میں جواب دینے والا صفحہ چار سیکنڈ لیتا ہے جیسے ہی کلائنٹ VPN کے پیچھے ہوتا ہے، جبکہ سرور کے کاؤنٹرز بیکار رہتے ہیں۔ Slow Log ایک ملی سیکنڈ سے اوپر کچھ نہیں دکھاتا، CPU کا گراف ہموار ہے، اور انسٹانس دوسرے کلائنٹس کو بغیر شکایت خدمت دیتا ہے۔ جو بدلا وہ فاصلہ ہے، اور فاصلے کو کئی گنا کرنے والی چیز آپ کے کوڈ کے رکنے اور انتظار کرنے کی تعداد ہے۔ درخواست کا راستہ کلائنٹ سے باہر کی طرف چلیں اور حل تقریباً ہمیشہ کم ترتیبی انتظار ہوتا ہے، تیز تر سرور نہیں۔
سرور میٹرکس سے نہیں، کلائنٹ سے شروع کریں
پہلی کمانڈ اور آخری کمانڈ کے درمیان کلائنٹ کے عمل کو دیکھیں۔ اگر ٹریس جواب، وقفہ اور پھر اگلی کمانڈ دکھاتا ہے تو آپ ہر کمانڈ پر پورا راؤنڈ ٹرپ ادا کر رہے ہیں اور سرور کی کوئی ٹیوننگ اسے نہیں بدلے گی۔ Slow Log یہاں غلط آلہ ہے، کیونکہ یہ عمل درآمد کا وقت ریکارڈ کرتا ہے اور کمیونیکیشن I/O کو جان بوجھ کر خارج کرتا ہے۔ سست endpoint کے ساتھ صاف Slow Log راؤنڈ ٹرپ مسئلے کی پہچان ہے۔
کوڈ کو چھونے سے پہلے خود راستہ ناپیں۔ redis-cli -h redis.example.internal --latency بار بار PING بھیجتا ہے اور درخواست اور جواب کا اوسط وقت چھاپتا ہے، جو آپ کی فی تبادلہ لاگت ہے۔ اسے ایک صارف عمل میں ترتیبی کمانڈز کی تعداد سے ضرب دیں اور آپ کو endpoint کے لیے کم از کم حد مل جائے گی۔
گنیں کہ ایک صارف عمل کو واقعی کتنے راؤنڈ ٹرپ درکار ہیں
ایک endpoint لیں اور ہر Redis کال ترتیب سے لکھیں، ان سمیت جو ORM، session middleware یا feature flag کی تلاش میں چھپی ہوں۔ زیادہ تر سست endpoint وہاں بیس یا تیس کالیں کرتے ہیں جہاں تین کافی ہوتیں، اور چھپی ہوئی کالیں عموماً اکثریت میں ہوتی ہیں۔
انحصار کا سلسلہ سمیٹا نہیں جا سکتا: اگر دوسری کمانڈ کو پہلی کے واپس کردہ کلید کی ضرورت ہو تو انتظار حقیقی ہے اور واحد آپشن مختلف ڈیٹا ماڈل یا سرور کی طرف کا ایسا عمل ہے جو پورا مرحلہ ایک ساتھ بیان کرے۔ آزاد ریڈنگ الگ معاملہ ہیں، کیونکہ کوئی چیز آپ کو دوسری بھیجنے سے پہلے پہلے جواب کا انتظار کرنے پر مجبور نہیں کرتی۔ کچھ بھی تبدیل کرنے سے پہلے ہر کال کو منحصر یا آزاد نشان زد کریں، اور حل کی شکل واضح ہو جائے گی۔
اہم عدد ترتیبی انتظار ہیں، کل کمانڈز نہیں۔ ایک batch میں تیس کمانڈز پھر بھی ایک انتظار کی لاگت رکھتی ہیں۔
صرف وہی کمانڈز batch کریں جو ایک دوسرے پر منحصر نہیں
Pipeline آزاد کمانڈز کو قطار میں لگاتا ہے اور جوابات ترتیب سے جمع کرتا ہے، N انتظاروں کو ایک میں بدل دیتا ہے۔ زیادہ تر کلائنٹس اسے الگ کنکشن موڈ کے بجائے بلاک، callback یا context manager کے طور پر پیش کرتے ہیں، اس لیے وہ API دیکھیں جو آپ کا نصب شدہ ورژن دیتا ہے۔ فائدہ راؤنڈ ٹرپ کے وقت کے ساتھ بڑھتا ہے، اور یہی وجہ ہے کہ VPN پر یہ اہم ہے اور localhost پر بمشکل محسوس ہوتا ہے۔
import redis
r = redis.Redis(host="redis.example.internal", port=6379, socket_timeout=2)
pipe = r.pipeline(transaction=False)
for key in ("user:1001", "user:1002", "user:1003"):
pipe.get(key)
print(pipe.execute())
جب صرف batching چاہیے تو transaction=False پاس کریں۔ طے شدہ رویے میں کلائنٹ batch کو MULTI اور EXEC میں لپیٹ دیتا ہے، جو اسے ایٹامک بناتا ہے اور بدلتا ہے کہ دوسرے کلائنٹس دوران عمل کیا دیکھ سکتے ہیں۔ ایٹامک ہونا درستگی کا فیصلہ ہے، کارکردگی کا بٹن نہیں، اور pipeline محض اس لیے ٹرانزیکشن نہیں کہ دونوں راؤنڈ ٹرپ کم کرتے ہیں۔
ہر جواب پڑھیں، صرف batch جمع کرانے تک محدود نہ رہیں۔ قطار میں لگی کمانڈ غلطی واپس کر سکتی ہے جبکہ batch مجموعی طور پر مکمل ہو جاتا ہے، اور جو کلائنٹ جوابات کی فہرست پھینک دیتا ہے وہ ناکام تحریر کو خاموش تحریر میں بدل دیتا ہے۔ جوابات کی فہرست کی لمبائی کا موازنہ قطار میں رکھی گئی کمانڈز کی تعداد سے کریں۔
اقدامات کے درمیان کنکشن زندہ رکھیں
ہر نیا کنکشن نام کی تحلیل، TCP handshake، TLS handshake اور AUTH کی قیمت ادا کرتا ہے، اور VPN پر ان میں سے ہر ایک ایسا راؤنڈ ٹرپ ہے جسے batch نہیں کیا جا سکتا۔ کلائنٹ کو فی عمل ایک بار بنائیں اور دوبارہ استعمال کریں، یا اپنی لائبریری کا فراہم کردہ pool محدود حجم کے ساتھ استعمال کریں۔ فی درخواست دوبارہ جڑنا اس علامت کی دوسری سب سے عام وجہ ہے، ہر کمانڈ کے انتظار کے بعد۔
نجی hostname ترتیب میں رکھیں، لفظی پتے کے طور پر نہیں۔ سرٹیفکیٹ کی توثیق اور سروس کی شناخت نجی نیٹ ورک پر بھی لاگو ہوتی ہیں، اور IP کو پن کرنا اسی لمحے ٹوٹ جاتا ہے جب فراہم کنندہ subnet کو دوبارہ نمبر دیتا ہے۔ اگر سست حصہ نام کی تحلیل ہے تو کنکشن سٹرنگ کے بجائے resolver کا راستہ ٹھیک کریں۔
واضح socket timeout مقرر کریں تاکہ پھنسا ہوا ٹنل worker کو لٹکانے کے بجائے تیزی سے ناکام ہو۔ پھر کلائنٹ میں کنکشن بننے کا لاگ رکھ کر تصدیق کریں کہ pool واقعی دوبارہ استعمال ہوتا ہے۔
batch کا حجم میموری مسئلہ بننے سے پہلے طے کریں
Redis batch کی پوری مدت میں قطار میں رکھے جوابات تھامے رکھتا ہے، اور کلائنٹ بعد میں تجزیہ شدہ نتیجہ تھامے رکھتا ہے۔ دس ہزار بڑی قدروں کا pipeline نیٹ ورک کے انتظار کو میموری کی چھلانگوں اور دونوں سروں پر طویل وقفوں سے بدل دیتا ہے۔
batch کا حجم کمانڈز کی تعداد کے بجائے جوابات کے حجم کے مطابق چنیں۔ ایک batch میں چند سو چھوٹی کمانڈز عموماً آرام دہ ہوتی ہیں، جبکہ سو کئی کلو بائٹ payload نہیں۔ بائٹس اور تعداد دونوں کے مطابق تقسیم کریں، اور ہر batch کو اسی تاخیر کے بجٹ میں رکھیں جو endpoint کے پاس واقعی ہے۔
تبدیلی کے بعد شروع سے آخر تک ناپیں: redis-cli -h redis.example.internal --latency-history بتاتا ہے کہ راستہ خود مستحکم ہے یا نہیں، اور آپ کا اپنا درخواست ٹائمر بتاتا ہے کہ endpoint بہتر ہوا یا نہیں۔ اگر endpoint اب بھی سست ہے جبکہ تاخیر کی تاریخ ہموار ہے تو باقی لاگت سرور کی طرف کا کام یا آپ کی اپنی serialization ہے، اور اگلا قدم batch کی ایک اور تبدیلی نہیں بلکہ handler کا پروفائل ہے۔