Prowid Photos-un yük balanslaşdırıcısının arxasında üç API nüsxəsi var, amma verilənlər bazası birdir — PostgreSQL. Pikdə saniyədə 350 sorğu gəlir və hər biri foto kartı və ya müəllifin profili üçün bazaya gedir, halbuki fotolar həftələrlə dəyişmir. Keş məlumatın elə yerdə saxlanan müvəqqəti nüsxəsidir ki, ondan oxumaq daha sürətlidir. Sorğunun yolunda keşlərin harada yaşadığını, faydasını necə hesablamağı, hansı strategiyaların olduğunu, məlumatı necə təzə saxlamağı, populyar açar «köhnələndə» bazanı necə çökdürməməyi, həmçinin CDN-in və Cache-Control-un necə işlədiyini öyrənəcəyik.

Keş niyə lazımdır: əvvəlcə rəqəmlər

Bənzətmə — iş masası və arxiv. Hər saat lazım olan sənədlər masanın üstündədir: tez götürmək olur, amma yer azdır. Qalanı zirzəmi arxivindədir: yer çoxdur, amma getmək uzundur. Keş masadır. Lazım olanı keşdə tapdınızsa — bu keşdə tapılma (cache hit), tapmadınızsa — tapılmama (cache miss) və mənbəyə, yəni bazaya getmək lazım gəlir. Tapılma payı hit ratio adlanır.

Bazaya yalnız tapılmayanlar çatır, yəni pik × (1 − hit ratio). Orta gecikmə hit × t(hit) + (1 − hit) × t(miss) düsturu ilə hesablanır. Tutaq ki, Redis-dən oxuma təxminən 2 ms çəkir, tapılmama isə PostgreSQL-ə 40 ms-lik sorğu və dəyərin keşə yazılması deməkdir, cəmi təxminən 44 ms:

js
const peakRps = 350;
const hitMs = 2; // Redis lookup inside the data center
const missMs = 44; // lookup + 40 ms DB query + saving the value

for (const hit of [0, 0.5, 0.9, 0.99]) {
  const avgMs = hit * hitMs + (1 - hit) * missMs;
  const dbRps = peakRps * (1 - hit);
  const pct = Math.round(hit * 100);
  const line = `${pct}% hits: ${avgMs.toFixed(1)} ms`;
  console.log(`${line}, DB ${dbRps.toFixed(1)} RPS`);
}
Hit ratioBazaya (pik 350 RPS)Orta cavab
0%350 RPS44 ms
50%175 RPS23 ms
90%35 RPS6,2 ms
99%3,5 RPS2,4 ms

Hit ratio-dakı hər əlavə «doqquz» bazanın yükünü dəfələrlə azaldır: 90%-dən 99%-ə keçəndə — on dəfə. Amma keş sürəti təzəlik və sadəlik hesabına alır: məlumat köhnələ (stale) bilər, sistemə daha bir komponent əlavə olunur və onu yeniləməyi unutmaq olar. Tez-tez oxunan, nadir dəyişən və kiçik geriləməyə dözən məlumatı keşləyin. Bir dəfə oxunan məlumatı və köhnəlməyə yol verilməyən hər şeyi (məsələn, pul çıxarılanda hesabın qalığını) keşləməyin.

Keş harada yaşayır: beş səviyyə

Sorğu keş səviyyələrindən keçərək PostgreSQL-ə qədər düşür
Sorğu keş səviyyələrindən keçərək PostgreSQL-ə qədər düşür

Sorğu səviyyələrdən aşağı «düşür» və nüsxə tapılan ilk səviyyədə dayanır:

  1. Brauzer. Nüsxə cihazdadır, şəbəkə ümumiyyətlə lazım deyil; Cache-Control başlığı ilə idarə olunur. Bu keş şəxsidir: Leylanın öz keşi var, Muradın isə öz keşi.
  2. CDN. Dünyanın hər yerində insanlara yaxın yerləşən serverlər. Regionda hamı üçün ortaq keş; şəkillər və açıq API cavabları üçün idealdır.
  3. Reverse proxy. Tətbiqin qarşısındakı Nginx cavabları saxlaya (proxy_cache) və API-ni təkrar sorğulardan qoruya bilər.
  4. Tətbiq keşi. Redis: hazır obyektlər və sorğu nəticələri, cavab 1–2 ms-ə.
  5. Verilənlər bazası. PostgreSQL isti səhifələri özü yaddaşda saxlayır (shared_buffers və əməliyyat sisteminin keşi).

Səviyyə istifadəçiyə nə qədər yaxındırsa, istifadəçi o qədər az gözləyir, amma təzəliyi idarə etmək o qədər çətindir: milyon insanın brauzerindəki nüsxəni silmək olmaz. Prowid Photos-da nəyi harada keşləyirik: