کلاینت تازهٔ Platformatic برای memcached روی Node.js
خلاصهٔ کاملتر
تیم Platformatic میگه memcached بعد از بیستوچند سال هنوز پابهپای گزینههای جدیدتر جلو میآد: یه key/value ساده تو حافظه، با تأخیر خیلی کم، بدون ترد پسزمینه و فقط یه باینری برای دیپلوی. مشکل از سمت Node.js بود؛ بیشتر کلاینتهای موجود قدیمیان، قبل از پروتکل فعلی نوشته شدن و دیگه نگهداری نمیشن. خودشون هم موقع اجرا دیدن همین کلاینتها کندترین حلقهٔ زنجیرن، برای همین @platformatic/memcached رو از صفر نوشتن.
نکتهٔ فنی اصلی انتخاب پروتکله. memcached سه پروتکل داره و به گفتهٔ نویسنده بیشتر کلاینتهای Node سراغ اشتباهیش میرن: پروتکل متنی کلاسیک که پرگوئه و باید خط به خط پارس بشه، و جوابهاش (NOT_FOUND، ERROR، CLIENT_ERROR) فقط با تطبیق رشته تشخیص داده میشن، پس یه پیام خطای تازه میتونه کلاینت رو بیسروصدا از هماهنگی خارج کنه. پروتکل باینری هم منسوخ شده.
این کلاینت فقط از پروتکل meta استفاده میکنه که تو memcached 1.6 اضافه شد تا جای هر دوتای قبلی رو بگیره: دستور و پاسخ فشرده و تکخطی، فلگهای روشن، و بلوکهای داده با طول مشخص، پس مقداری که خودش \r\n داره هم امن جابهجا میشه. هر دستور، حتی delete، از CAS پشتیبانی میکنه و سرور یه توکن opaque برمیگردونه که کلاینت با هر پاسخ چکش میکنه. دستورهای mg، ms، md، ma و mn بهعلاوهٔ version و stats پشتیبانی میشن.
import { Client } from '@platformatic/memcached'
const client = new Client('localhost:11211')
await client.set('greeting', 'hello', { ttl: 60 })
const value = await client.get('greeting')
await client.close()سرعتش از همون ترفندهای @platformatic/kafka میآد: pipelining کامل روی یک کانکشن (یعنی چند دستور پشت سر هم میره و پاسخها با یه صف FIFO به درخواستها وصل میشن)، پارس تدریجی روی Buffer که مقدار رو با طول میخونه نه با گشتن دنبال جداکننده، و یکی کردن نوشتنها تو یه فراخوانی writev. گزینهٔ autoPipelining تعیین میکنه کِی flush بشه. وابستگی رانتایم هم صفره و فقط node:net رو لازم داره؛ حداقل نسخهٔ لازم هم Node.js 22.12.0 هست.
برای production هم چیزهای لازم رو داره: شاردینگ سمت کلاینت با هشینگ سازگار به سبک ketama (۱۶۰ نقطه به ازای هر نود) که با اضافه یا کم شدن یه نود فقط حدود ۱/N کلیدها جابهجا میشن، auto discovery برای AWS ElastiCache، پشتیبانی از TLS و حالت authfile، کانکشنپول با poolSize و اتصال دوبارهٔ خودکار با backoff نمایی. متریکها از client.metrics() میآد و رویدادهای هر عملیات روی node:diagnostics_channel منتشر میشن تا پکیج جانبی OpenTelemetry بدون monkey-patch ازشون span بسازه.
نکات کلیدی:
- بنچمارک خودشون: بالای ۳۵۰٬۰۰۰ SET و ۳۶۹٬۰۰۰ GET در ثانیه روی یک کانکشن، حدود ۳ برابر سریعترین رقیب
- فقط پروتکل meta؛ SASL پشتیبانی نمیشه چون به پروتکل باینریِ منسوخ وصله
- مقدارها ورودی و خروجی Buffer هستن؛ کلید باید ASCII چاپی بدون فاصله و حداکثر ۲۵۰ بایت باشه
- کلیدها ممکنه داده حساس داشته باشن، برای همین تو diagnostics نمیآن مگه با diagnosticsIncludeKeys:true
- فعلاً خصوصی و آزمایشیه و API ممکنه قبل از انتشار عمومی عوض بشه




