العمارة المخبأة: Redis، Memcached
العمارة المخبأة: Redis، Memcached
1) متى ولماذا ذاكرة التخزين المؤقت
الأهداف: تقليل زمن الانتقال، وإفراغ واجهات برمجة التطبيقات الخارجية من DB/PSP والتخفيف من الذروة.
غالبًا ما تكون طبقات ذاكرة التخزين المؤقت متعددة المستويات: قيد العملية (L1) → مستوى الخدمة (Redis/Memcached L2) → الحافة/CDN. يسرع المخبأ الداخلي القراءات الساخنة، L2 شائع للخدمات، والحافة للمحتوى العام.
2) Redis vs Memcached - موجز
القاعدة: إذا كنت بحاجة إلى هياكل بيانات معقدة، مثابرة، حانة/فرعية/تدفقات/نصوص - خذ Redis. إذا كانت طبقة مخبأ KV فائقة البساطة والسرعة والرخيصة بدون متانة هي Memcached.
3) أنماط التخزين المؤقت
3. 1 مخبأ جانبا (كسول)
يقرأ التطبيق من المخبأ → يقرأ → من قاعدة البيانات → يضعه في المخبأ مع TTL.
سيطرة بسيطة على TTL، واستقلال مخبأ. − «عاصفة» محتملة في حالة الفشل.
3. 2 قراءة
العميل/الوكيل نفسه يسحب من الأصل عند فشل ويضعه في المخبأ.
منطق مركزي − بنية تحتية أكثر تعقيداً
3. 3 الكتابة/الكتابة من الخلف
الكتابة: الكتابة أولاً إلى المخبأ، ثم إلى قاعدة البيانات.
اكتب خلف: الكتابة إلى قائمة الانتظار، وميض غير متزامن في قاعدة البيانات (خسارة محتملة عند الانهيار - تحتاج إلى سجل).
3. 4 من مستويين (L1 + L2)
L1 (قيد العملية) مع TTL قصير و TTL الناعم، L2 (Redis/Memcached) - "الحقيقة المخبأة. "الإعاقة عبر الحانة/الفرعية.
4) TTL والعواصف والاتساق
TTL-Set قريبة من تواتر تغيير البيانات. بالنسبة للمفاتيح الساخنة، استخدم TTL (jitter) randization: 'tl = base ± rand (0.. base0. 1) - يزيل التدفقات الخارجية المتزامنة.
Dogpile (قطيع مدوي): حماية الأخطاء:- Singleflight: عملية واحدة فقط تزيد من القيمة (انظر مثال Lua).
- تحديث خلفية Soft-TTL +: بعد «noft _ tl»، أعطه قديمًا واستكماله بالخلفية.
- Semaphore/lock: 'SET key: lock value NX PX = 2000'.
- شبه قديم: «إعادة التحقق من صحة» للاستجابة لواجهات برمجة التطبيقات (انظر القسم 8).
5) المفاتيح ومساحات الأسماء والتسلسل
5. 1 تسمية المفتاح
قالب: '{نطاق}: {كيان}: {معرف}: {حقل}'
أمثلة:- "المستخدم: الملف الشخصي: 42 'كتالوج: المنتج: 1001: v2'" psp: المعدلات: 2025-11-03 "
أضف نسخة مخطط (': v2') - وهذا يسهل الإعاقة الجماعية.
5. 2 Neimspaces عبر «إصدار الفضاء»
عقد المفتاح 's: كتالوج = 17'. المفاتيح الحقيقية: «الكتالوج: 17: المنتج: 1001». بالنسبة للإعاقة في الدليل العالمي، ببساطة «ns: callog».
5. 3 التسلسل/الضغط
JSON مريح، لكنه ثقيل. استخدم MessagePack/CBOR.
تمكين الضغط (LZ4/ZSTD) للحمولة الكبيرة (> 1-2 كيلوبايت). في Redis - من جانب العميل.
6) المفاتيح الساخنة والشحن
المفاتيح الساخنة: راقب Top-N بواسطة hit/miss/byte. للمفاتيح الساخنة للغاية:- نسق القراءة المتكرر: تكرار القيمة في عدة مفاتيح شظايا ساخنة: k: 1.. N '، اختر عشوائيا عند القراءة.
- Local L1: ضع عملية الاشتراك في الإعاقة في الاعتبار.
- Redis Cluster - أصلي (16384 فتحة تجزئة).
- Memcached هو تجزئة متسقة من جانب العميل.
- Hash-tag in Redis' {...} "يصلح فتحة لمجموعة من المفاتيح:" المستخدم: {42}: الملف الشخصي "و" المستخدم: {42}: الحدود "ستكون على نفس البطاقة.
7) سياسات وحجم الاستباق
Redis' maxmemory-policy ":" allkeys-lru "،" fulle-lru "،" allkeys-lfu "،" noeviction "и т. д. بالنسبة للذاكرة المخبأة، عادة «allkeys-lru »/« allkeys-lfu».
Memcached - LRU на لوح العنصر.
حجم المفتاح وقيمته: راقب حجم العنصر الأقصى (Memcached افتراضيًا 1 ميجابايت، لوح الضبط).
يجب أن يتحلل تجاوز الذاكرة بشكل متوقع: ليس «إخلاء» على المسار النشط.
maxmemory 32gb maxmemory-policy allkeys-lfu hz 50 tcp-keepalive 60
8) أنماط الحماية من العواصف - كود
8. 1 Redis Lua singleflight (زائف)
lua
-- KEYS[1] = data_key, KEYS[2] = lock_key
-- ARGV[1] = now_ms, ARGV[2] = soft_ttl_ms, ARGV[3] = hard_ttl_ms, ARGV[4] = lock_ttl_ms local payload = redis. call("GET", KEYS[1])
if payload then local meta = redis. call("HGETALL", KEYS[1].. ":meta")
local last = tonumber(meta[2] or "0")
if tonumber(ARGV[1]) - last < tonumber(ARGV[2]) then return { "HIT", payload }
end if redis. call ("SET," KEYS [2], "1," "NX," "PX," ARGV [4]) then return {"REFRESH," payload} - one worker updates, the rest give stale end return {"STALE," payload}
end if redis. call("SET", KEYS[2], "1", "NX", "PX", ARGV[4]) then return { "MISS", nil }
end return { "BUSY", nil }
8. 2 عقدة. js-cache-جانبا (مبسط)
js const v = await redis. get(key);
if (v) return decode(v);
const lock = await redis. setNX(key+":lock", "1", { PX: 1500 });
if (lock) {
const fresh = await loadFromDB(id);
await redis. set(key, encode(fresh), { EX: ttl, NX: false });
await redis. del(key+":lock");
return fresh;
} else {
await sleep(60); // short backoff const retry = await redis. get (key) ;//give someone's already filled return decode (retry);
}
9) الإعاقة والاتساق
حسب الحدث: عند التغيير في قاعدة البيانات، قم بنشر «الحانة/الحدث الفرعي» يبطل: {ns}: {id} '→ يقوم المشتركون بحذف المفاتيح.
حسب الوقت: TTL قصير للبيانات المتغيرة بشكل متكرر.
Versioning: see's ns: 'keys.
Outbox: ضمان تسليم الإعاقة (حدث تسجيل/موضوع، retrai).
خصوصية عمليات ذاكرة التخزين المؤقت: استخدم 'SETXX/SETNX'، والإصدارات ('etag') وحقول التجزئة للزيادة.
10) النسخ، المجموعة، الفشل
10. 1 Redis
Sentinel: automatic failover master-replica (stateFUL IP/name).
المجموعة: الشحن + الفشل التلقائي ؛ يجب على العملاء دعم إعادة توجيه «نقل/اسأل».
AOF/RDB: بالنسبة لذاكرة التخزين المؤقت عادة "appendfsync everysec'، فمن الممكن بدون ثبات (مثل المخبأ الخالص).
10. 2 ميمكاشيد
لا تكرار خارج الصندوق. الموثوقية - عبر شظية متعددة الخوادم + تكرار «n» (جانب العميل).
عندما تسقط العقد، هناك زيادة في الأخطاء و «إعادة تدريب» المخبأ.
10. 3 K8s والشبكات
Redis/Memcached لا تحب إعادة إنشاء القرون بشكل متكرر ؛ استخدم StatefulSet + AZ antipodes، PVC/POD IP الثابت.
ضبط PodDistructionBudget and TopologySpreadRestrictions.
11) المعاملات والنصوص والذرة (Redis)
INCR/DECR، HINCRBY - عدادات، حصص، حدود الأسعار (فقط انظر الثابت).
MULTI/EXEC - حزمة من الأوامر الذرية.
Lua (EVAL) - قراءة وتعديل الكتابة بدون سباق.
خط الأنابيب - يقلل RTT (خاصة في قفزات الشبكة).
lua
-- KEYS[1]=bucket, ARGV[1]=capacity, ARGV[2]=refill_rate_per_sec, ARGV[3]=now_ms
-- Returns 1 if the token is issued, otherwise 0
12) قوائم الانتظار والحانة/الفرعية والتدفقات (Redis)
حانة/فرعية: الإعاقة والإشارات. لا حفظ، المستمعين عبر الإنترنت فقط.
التدفقات: قوائم انتظار حدث التأكيد (ACK)، مجموعة المستهلك، Retrai - سهلة الاستخدام للكتابة/المعجبين.
القوائم («BRPOP»): قوائم انتظار بسيطة.
لا تستخدم Redis كـ «حافلة واحدة من كل شيء» بدون نسخة احتياطية - فهذه حافلة مخبأ/سريعة، وليست كافكا.
13) الأمن والوصول
عزل الشبكة/VPC، mTLS على مستوى الدخول، ACL/كلمات المرور («مطلوب »/ACL في Redis 6 +).
تعطيل الأوامر الخطرة في Redis («CONFIG» و «FLUSHALL' و» KEYs') عبر ACL.
بالنسبة إلى Memcached - لا تستمع إلى الواجهات العامة، '-U 0' (بدون UDP)، فقط الشبكات الخاصة.
لا تخزن PII ؛ إذا لزم الأمر - تشفير TTL + قصير على مستوى التطبيق.
14) إمكانية الرصد والصيانة
المقاييس الرئيسية:- نسبة الإصابة/نسبة التفويت (حسب مساحة الاسم/المسار).
- Latency p95/p99 'GET/SET/MGET' أوامر، مهلات.
- عمليات الإخلاء и أخطاء OOM.
- تأخر النسخ (Redis)، الحالة العنقودية، أحداث الهجرة/إعادة الصياغة.
- مفاتيح Top-N حسب حركة المرور/البايت (أخذ العينات).
- جذوع الأشجار: أوامر بطيئة («slowlog»)، أخطاء الشبكة.
- لوحات القيادة: عامة (CPU/RAM/connections)، أوامر، فتحات عنقودية، حراس، يمرون عبر مصدري بروميثيوس.
15) التشكيلات وعمليات النشر - أمثلة
15. 1 Redis Sentinel (مقتطف)
port 6379 protected-mode yes appendonly yes appendfsync everysec maxmemory-policy allkeys-lfu
'sentinel. conf ':
sentinel monitor m1 10. 0. 0. 11 6379 2 sentinel auth-pass m1 sentinel down-after-milliseconds m1 5000 sentinel failover-timeout m1 60000
15. 2 Redis Cluster (قيم القيادة، مبسطة)
yaml cluster:
enabled: true nodes: 6 # 3 masters + 3 replicas persistence:
size: 100Gi resources:
requests: { cpu: "500m", memory: "2Gi" }
15. 3 ميمكاشيد (نشر)
yaml containers:
- image: memcached:1. 6 args: ["-m", "32768", "-I", "2m", "-v", "-t", "8", "-o", "modern"]
ports: [{ containerPort: 11211 }]
15. 4 NGINX كبديل للقراءة (حلقة API)
nginx proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=api:100m max_size=10g inactive=10m;
map $request_uri $cache_key { default "api:$request_uri"; }
location /api/ {
proxy_cache api;
proxy_cache_valid 200 1m;
proxy_cache_use_stale updating error timeout http_500 http_502 http_503 http_504;
proxy_cache_lock on; # singleflight на уровне NGINX proxy_cache_key $cache_key;
proxy_pass http://backend;
}
16) الاختبار والبوابات
ملفات تعريف حمل مخبأ بارد/دافئ/ساخن.
حقن الأخطاء (التطهير الجماعي) - يجب أن يتحمل الأصل «إعادة التدريب».
التنبيهات: انخفاض حاد في نسبة الإصابة، ارتفاع في زمن الفشل، سيل من عمليات الإخلاء، ارتفاع في المهلات.
17) الأنماط المضادة
تخزين «الحقيقة» في Redis بدون AOF/RDB ودون تكرار.
TTL = 0 (دائم) للبيانات المتطايرة → عدم الاتساق الدائم.
كتلة «المفاتيح» في الحث.
عدم وجود نفث/TTL لينة → الانقطاعات والعواصف المتزامنة.
مثال واحد لجميع الأوامر بدون شحن/نسخ طبق الأصل.
استخدم Memcached للمهام التي تتطلب ذرية/نصوص.
18) قائمة التنفيذ المرجعية (0-45 يوما)
0-10 أيام
حدد قالب (cache-aside + L1/L2)، وصف المفاتيح، TTL، مساحات الأسماء.
تمكين jitter/loft-TTL، رحلة فردية ؛ التنبيهات/لوحات القياس الأساسية.
بالنسبة إلى Redis - قم بتكوين ACL، الوضع المحمي، slowlog، maxmemory-policy.
11-25 يومًا
التحول إلى الشحن (Redis Cluster أو client hash)، نسخ طبق الأصل.
الإعاقة عن طريق إصدار الحانة/الحانة الفرعية أو الفضاء الجديد ؛ في قاعدة البيانات.
اختبارات تحميل «إعادة تدريب» المخبأ ؛ تحديد المنشأ.
26-45 يومًا
Autopromo/canary TTL، الإحماء قبل الإطلاق.
تدفقات لإعادة تجميع الكتابة/الخلفية.
تقارير أسبوعية عن نسبة الإصابة، المفاتيح العليا، تكلفة الذاكرة.
19) مقاييس النضج
نسبة الإصابة L2 ≥ 80٪ (إحصائيات عن الطرق/مساحات الأسماء).
P95 GET <2-3 ms (in-DC)، يخطئ <أصل SLO.
0 عواصف في الإعاقة الجماعية (أثبتت الاختبارات).
الإعاقة التلقائية ونسخ nymspace.
يغطي التشظي/التكرار فشل العقدة 1 دون تحلل ملحوظ.
20)
بنية ذاكرة التخزين المؤقت القوية هي نظام المفاتيح و TTL، والحماية من العواصف، والتجزئة المناسبة، والاستباق المتوقع. يعطي Redis دلالات غنية ومثابرة وذرية ؛ Memcached - أقصى قدر من البساطة والسرعة. أضف إمكانية الملاحظة، وإعاقة الحدث، L1 + L2، وأصبح المخبأ مسرعًا للمنصة، وليس مصدرًا للقطرات العرضية والأخطاء «الصوفية».