კეშტის არქიტექტურა: Redis, Memcached
კეშტის არქიტექტურა: Redis, Memcached
1) როდის და რატომ
მიზნები: ლატენტობის შემცირება, BD/PSP/გარე API გადმოტვირთვა და მწვერვალების შემსუბუქება.
კეშის ფენები ხშირად მრავალმხრივია: in-process (L1) - მომსახურების დონე (Redis/Memcached L2) - edge/CDN. შიდა ქეში აჩქარებს „ცხელ“ კითხვებს, L2 - მომსახურებისთვის საერთო, edge - საზოგადოებრივი შინაარსისთვის.
2) Redis vs Memcached - მოკლედ
წესი: თუ თქვენ გჭირდებათ მონაცემთა რთული სტრუქტურები, persistence, pub/sub/strimes/scripts - მიიღეთ Redis. თუ სუპერ მარტივი, სწრაფი, იაფი KV ქეშის ფენა durability - Memcached.
3) კეშტის შაბლონები
3. 1 Cache-aside (lazy)
პროგრამა კითხულობს კეშისგან გამოტოვებულ შეცდომებს, კითხულობს BD- დან და TTL- ს ყუთში აყენებს.
მარტივი კონტროლი TTL, დამოუკიდებლობა კეშისგან. - შესაძლებელია „ქარიშხალი“ გამოტოვების დროს.
3. 2 Read-through
კლიენტი/მარიონეტული თავად აყენებს origin- ს გამოტოვებისას და ყაბაყში აყენებს.
ცენტრალიზებული ლოგიკა. - უფრო რთულია ინფრასტრუქტურა.
3. 3 Write-through / Write-behind
Write-through: ჩაწერა ჯერ ქეშში, შემდეგ BD- ში.
Write-behind: ჩაწერა რიგში, ასინქრონული ფაფა BD- ში (შურისძიების პოტენციური ზარალი - საჭიროა ჟურნალი).
3. 4 Two-tier (L1+L2)
L1 (in-process) მოკლე TTL და რბილი TTL, L2 (Redis/Memcached) - „კეშის ჭეშმარიტება“. ინვალიდობა pub/sub- ით.
4) TTL, ქარიშხალი და თანმიმდევრულობა
TTL: დააყენეთ მონაცემთა ცვლილების სიხშირე. ცხელი გასაღებებისთვის გამოიყენეთ TTL (jitter) რანდომიზაცია: 'tl = base ± rand (0.. base0. 1) '- ამოიღეთ სინქრონული გასასვლელი.
Dogpile (thundering herd): დაიცავით შეცდომები:- Singleflight: მხოლოდ ერთი პროცესი ასახავს მნიშვნელობას (იხ. ლუას მაგალითი).
- Soft-TTL + background refresh: 'soft _ ttl' შემდეგ მიეცით მოძველებული (stale) და განაახლეთ ფონი.
- Semaphore/lock: `SET key:lock value NX PX=2000`.
- Near-stale: 'stale-while-revalidate' პასუხები API- სთვის (იხ. ნაწილი 8).
5) გასაღებები, ნეიმსპასი, სერიალიზაცია
5. 1 გასაღებები
შაბლონი: '{domain}: {entity: {id}: {field'
მაგალითები:- `user:profile:42` `catalog:product:1001:v2` `psp:rates:2025-11-03`
დაამატეთ სქემის ვერსია (': v2') - ეს ხელს უწყობს მასობრივ ინვალიდობას.
5. 2 ნეიმსპასი „სივრცის ვერსიით“
შეინარჩუნეთ გასაღები: catalog = 17 '. რეალური გასაღებები: 'კატალოგი: 17: პროდუქტი: 1001'. კატალოგის გლობალური ინვალიდობისთვის, უბრალოდ ჩადეთ 'ns: catalog'.
5. 3 სერიალიზაცია/შეკუმშვა
JSON - მოსახერხებელი, მაგრამ მძიმე. გამოიყენეთ Pack Pack/CBOR.
ჩართეთ შეკუმშვა (LZ4/ZSTD) დიდი payload (> 1-2 KB). Redis- ში - კლიენტის მხარეს.
6) ცხელი გასაღებები და შარდვა
Hot-keys: დააკვირდით ტოპ-N hit/miss/byte. უკიდურესად ცხელი გასაღებებისთვის:- Replicated read pattern: დუბლირებული მნიშვნელობა რამდენიმე shard გასაღების 'hot: k: 1.. N', შეარჩიეთ შემთხვევითი კითხვის დროს.
- ადგილობრივი L1: მეხსიერებაში შეინახეთ შეზღუდული შესაძლებლობის მქონე პირი.
- Redis Cluster - nationaly (16384 hash-slots).
- Memcached არის კლიენტის კომპოზიციური ჰაში.
- Hash-tag Redis '{...}' აფიქსირებს სლოტს კლავიშების ნაკრებისთვის: 'user: {42}: profile' და 'user: {42}: limits' იქნება ერთ საშინელებაზე.
7) გადაადგილების პოლიტიკა და ზომა
Redis `maxmemory-policy`: `allkeys-lru`, `volatile-lru`, `allkeys-lfu`, `noeviction` и т. д. კეშისთვის, ჩვეულებრივ, 'allkeys-lru '/' allkeys-lfu'.
Memcached — LRU на item-slab.
გასაღების ზომა და სარგებელი: დააკვირდით max item size (Memcached ნაგულისხმევი 1 MB, tuning slab).
მეხსიერების ჭარბი რაოდენობა პროგნოზირებადი უნდა იყოს: არა 'noeviction' აქტიურ გზაზე.
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 Node. js cache aside (გამარტივებული)
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) ინვალიდობა და თანმიმდევრულობა
ღონისძიების თანახმად: BD- ში შეცვლისას, გამოაქვეყნეთ 'pub/sub' მოვლენა 'invalidate: {ns: {id' ", აბონენტები ამოიღებენ გასაღებებს.
ტაიმერის მიხედვით: მოკლე TTL ხშირად ცვალებადი მონაცემებისთვის.
ვერსია: იხ. 'ns:' გასაღებები.
Outbox: შეზღუდული შესაძლებლობის მქონე პირთა მიწოდების გარანტია (მოვლენა საწოლში/ტოპში, retray).
კეშთან ოპერაციების idempotence: გამოიყენეთ 'SETXX/SETNX', ვერსიები ('etag') და ჰეშის ველი.
10) რეპლიკაცია, მტევანი, failover
10. 1 Redis
Sentinel: ავტომატური failover master-replica (stateFUL IP/სახელი).
Cluster: შარდვა + ავტომატური failover; მომხმარებლებმა უნდა შეინარჩუნონ რედაქციის 'MOVED/ASK'.
AOF/RDB: კეშისთვის, როგორც წესი, 'appendfsync everysec', შეგიძლიათ კონფიდენციალურობის გარეშე (როგორც სუფთა კეში).
10. 2 Memcached
ყუთიდან არ არის რეპლიკაცია. საიმედოობა - მრავალსაფეხურიანი ხიბლის მეშვეობით + გამეორება 'n' (კლასობრივი მხარე).
ნოდის დაცემისას - გამოტოვების ზრდა და კეშის „გადამზადება“.
10. 3 K8s და ქსელის ასპექტები
Redis/Memcached- ს არ მოსწონს pod's ხშირი გადანერგვა; გამოიყენეთ statefulSet + AZ ანტიპოდები, ფიქსირებული PVC/POD IP.
დააყენეთ PodDisrupite Budget და TopologySpreadConstraints.
11) გარიგებები, სკრიპტები და ატომურობა (Redis)
INCR/DECR, HINCRBY - მრიცხველები, კვოტები, საბადოები-ლიმიტები (მხოლოდ გაითვალისწინეთ პერსონალი).
MULTI/EXEC - ატომური ბრძანებების პაკეტი.
Lua (EVAL) - racing გარეშე read modify-write.
Pipeline - ამცირებს 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) რიგები, pub/sub და Streams (Redis)
Pub/Sub: ინვალიდობა, სიგნალები. შენახვის გარეშე, მხოლოდ ონლაინ მსმენელები.
Streams: დადასტურების ღონისძიებების სტრიქონები (ACK), მომხმარებელთა ჯგუფები, retrais - მოსახერხებელია write-behind/გულშემატკივრებისთვის.
Lists ('BRPOP'): მარტივი ხაზები.
ნუ გამოიყენებთ Redis- ს, როგორც „ყველაფრის ერთ ავტობუსს“ ზურგჩანთების გარეშე - ეს არის ქეში/სწრაფი საბურავი, არა კაფკა.
13) უსაფრთხოება და წვდომა
ქსელის იზოლაცია/VPC, mTLS ingress დონეზე, ACL/პაროლები ('requirepass '/ACL Redis 6 +).
Disable dangerous გუნდები Redis- ში ('CONFIG', 'FLUSHALL', 'KEYS') ACL- ის საშუალებით.
Memcached- ისთვის - არ მოუსმინოთ საჯარო ინტერფეისებს, '-U 0' (UDP- ის გარეშე), მხოლოდ პირადი ქსელები.
PII არ ინახება; საჭიროების შემთხვევაში - მოკლე TTL + დაშიფვრა განაცხადის დონეზე.
14) დაკვირვება და მოვლა
ძირითადი მეტრიკა:- Hit ratio/Miss ratio (namespace/მარშრუტზე).
- Latency p95/p99 ბრძანებები 'GET/SET/MGET', timeouts.
- Evictions и OOM errors.
- Replication lag (Redis), cluster state, migrate/rehash events.
- Top-N keys ტრაფიკი/ბაიტი (ნიმუში).
- Logs: ნელი ბრძანებები ('slowlog'), ქსელის შეცდომები.
- დაშბორდები: საერთო (CPU/RAM/Connections), გუნდები, კლასტერის სლოტები, sentinels, გადის Prometheus ექსპორტიორებს.
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 (helm values, გამარტივებული)
yaml cluster:
enabled: true nodes: 6 # 3 masters + 3 replicas persistence:
size: 100Gi resources:
requests: { cpu: "500m", memory: "2Gi" }
15. 3 Memcached (deployment)
yaml containers:
- image: memcached:1. 6 args: ["-m", "32768", "-I", "2m", "-v", "-t", "8", "-o", "modern"]
ports: [{ containerPort: 11211 }]
15. 4 NGINX, როგორც read-through მარიონეტული (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) ტესტირება და კარიბჭე
დატვირთული პროფილები „ცივი/თბილი/ცხელი ქეში“.
გამოტოვების ინექცია (purge მასიურად) - origin უნდა გაუძლოს „გადამზადებას“.
ალერტები: hit-ratio- ს მკვეთრი ვარდნა, miss latency ზრდა, evictions ზვავი, timeouts- ის ზრდა.
17) ანტი შაბლონები
შეინახეთ „ჭეშმარიტება“ Redis- ში AOF/RDB- ის გარეშე და სარეზერვო გარეშე.
TTL = 0 (განუსაზღვრელი) ცვალებადი მონაცემებისთვის - მარადიული არაკონსტიტუციურობა.
მასობრივი 'KEYS' გაყიდვაში.
Jitter/soft-TTL- ის არარსებობა არის სინქრონული გასასვლელი და ქარიშხალი.
ერთი ინსტანცია ყველა გუნდისთვის შარდვის/რეპლიკების გარეშე.
გამოიყენეთ Memcached ატომური/სკრიპტების საჭიროებისთვის.
18) განხორციელების სიის სია (0-45 დღე)
0-10 დღე
შეარჩიეთ შაბლონი (cache-aside + L1/L2), აღწერეთ გასაღებები, TTL, ნეიმსპასი.
ჩართეთ jitter/soft-TTL, singleflight; ძირითადი ალერტები/დაშბორდები.
Redis- ისთვის - კონფიგურაცია ACL, დაცული რეჟიმი, slowlog, maxmemory-policy.
11-25 დღე
გადასვლა შარდზე (Redis Cluster ან კლიენტის ჰაში), შენიშვნები.
ინვალიდობა pub/sub- ით ან ნეიმსპასის ვერსიით; Outbox BD- ში.
კეშის „გადამზადების“ დატვირთული ტესტები; limiting origin.
26-45 დღე
Autopromo/კანარის TTL, გაათბეთ გამოშვებამდე.
Streams write-behind/fon presocress.
ყოველკვირეული მოხსენებები hit-ratio- ს, ტოპ გასაღებების, მეხსიერების ღირებულების შესახებ.
19) სიმწიფის მეტრიკა
Hit-ratio L2-80% (სტატისტიკა მარშრუტებზე/ნეიმსპასებზე).
P95 GET <2-3 ms (in-DC), გამოტოვება <SLO origin.
მასობრივი შეზღუდული შესაძლებლობის მქონე 0 ქარიშხალი (დადასტურებულია ტესტებით).
ავტომატური ინვალიდობა და ნეიმსპასის ვერსიები.
შარდვა/რეპლიკაცია მოიცავს 1 კვანძის უკმარისობას შესამჩნევი დეგრადაციის გარეშე.
20) დასკვნა
კეშის ძლიერი არქიტექტურა არის გასაღების დისციპლინა და TTL, ქარიშხლისგან დაცვა, სწორი შარდვა და პროგნოზირებადი გადაადგილება. Redis იძლევა მდიდარ სემანტიკას, პერსონალურობას და ატომურობას; Memcached არის მაქსიმალური სიმარტივე და სიჩქარე. დაამატეთ დაკვირვება, მოვლენების ინვალიდობა, L1 + L2 და ქეში გახდება პლატფორმის ამაჩქარებელი და არა შემთხვევითი ვარდნის წყარო და „მისტიკური“ შეცდომები.