Makale

Bellek İçi Veritabanları ve Önbelleğe Alma: Geniş Ölçekte Hız

Bellek İçi Veritabanları ve Önbelleğe Alma: Geniş Ölçekte Hız

Bellek içi veritabanları, verileri disk yerine öncelikle RAM'de depolar. Bu, disk G/Ç gecikmesini ortadan kaldırarak, geleneksel disk tabanlı veritabanlarından çok daha hızlı olan mikro saniyelik yanıt süreleri sağlar.

3 dk okumaDil: TR TürkçeÜcretsiz0 alkış0 yorum
TeknolojiMühendislik MakaleleriCachingDatabasesTechnologyEngineering ArticlesMemory
Okuma seçenekleri

Giriş

Bellek içi veritabanları, verileri disk yerine öncelikle RAM'de depolar. Bu, disk G/Ç gecikmesini ortadan kaldırarak, geleneksel disk tabanlı veritabanlarından çok daha hızlı olan mikro saniyelik yanıt süreleri sağlar.

Bellek içi veritabanları geleneksel veritabanlarının yerine geçmez; tamamlayıcıdırlar. Ultra düşük gecikme süresi, yüksek verim ve gerçek zamanlı veri işleme gerektiren kullanım durumlarında uzmandırlar: önbelleğe alma, oturum yönetimi, gerçek zamanlı analizler, skor tabloları, hız sınırlama ve mesaj aracılık.


Bellek İçi ve Disk Tabanlı Veritabanları

Görünüş Bellek İçi Veritabanı Disk Tabanlı Veritabanı
Birincil depolama RAM SSD/HDD
Okuma gecikmesi < 1 ms (tipik 0,1 ms) 1-10 ms (SSD), 5-20 ms (HDD)
Yazma verimi 100K-1M+ işlem/sn 1K-100K işlem/sn
Veri kalıcılığı İsteğe bağlı (anlık görüntüler, AOF) Her zaman ısrarcı
Kapasite RAM sınırlı (GB-TB) Disk sınırlı (TB'ler-PB'ler)
GB başına maliyet ~$10-50/GB ~0,10-1$/GB
Sorgu karmaşıklığı Anahtar/değer çifti, basit yapılar Karmaşık birleştirmeler, toplamalar
Dayanıklılık Yapılandırılabilir (fsync takası) Tam ASİT garantileri

Redis: En Popüler Bellek İçi Mağaza

Veri Yapıları

# Strings — most basic
SET user:100:name "Alice"
GET user:100:name          # "Alice"
INCR page_counter          # 1
INCRBY page_counter 5      # 6

# Lists — ordered, push/pop from ends
LPUSH notifications:101 "New message"
RPOP notifications:101     # "New message"
LLEN notifications:101     # Length

# Sets — unordered, unique members
SADD user:100:tags "redis" "python" "database"
SMEMBERS user:100:tags     # All members
SISMEMBER user:100:tags "python"  # 1 (true)
SINTER user:100:tags user:200:tags  # Intersection

# Sorted Sets — scored, ordered
ZADD leaderboard 1000 "player1"
ZADD leaderboard 2500 "player2" 900 "player3"
ZREVRANGE leaderboard 0 2 WITHSCORES  # Top 3
# 1) "player2" (2500)
# 2) "player3" (900)
# 3) "player1" (1000)

# Hashes — structured objects
HSET user:100 name "Alice" age 30 email "alice@example.com"
HGETALL user:100
HINCRBY user:100 login_count 1

# Streams — append-only log (like Kafka)
XADD events * type "login" user_id "100"
XRANGE events - + COUNT 10

# Geospatial — location-based
GEOADD locations 13.361389 38.115556 "Palermo"
GEORADIUS locations 15 37 100 km  # Cities within 100km

Kalıcılık Seçenekleri

Mod Nasıl Çalışır? Dayanıklılık Performans Etkisi
RDB (anlık görüntü) Diske periyodik tam döküm Son çöplük kaybedildi Düşük (çatal + yazma)
AOF (yalnızca ekleme) Günlüğe kaydedilen her yazma Yapılandırılabilir: her zaman/sn/hayır Orta
RDB + AOF Her ikisi de birleştirildi Yüksek Orta
İsrar yok Yalnızca RAM, disk G/Ç yok Yeniden başlatmada yok En iyi performans
# redis.conf — persistence configuration
save 900 1       # RDB: save if 1 key changed in 900 seconds
save 300 10      # save if 10 keys changed in 300 seconds
save 60 10000    # save if 10000 keys changed in 60 seconds

appendonly yes            # Enable AOF
appendfsync everysec      # fsync every second (best trade-off)

Prodüksiyon Redis Mimarlık

Ana Kopya:

Client ──► Master (read/write)
              │
         ┌────┴────┐
         │         │
      Replica1  Replica2  (read-only, failover targets)

Redis Sentinel — Yüksek Kullanılabilirlik:

┌──────────┐
│ Sentinel │  (monitors master, performs automatic failover)
└──────────┘
     │
Client ──► Master ──► Replica1 ──► Replica2
               │
          (if master fails, Sentinel promotes a replica)

Redis Kümesi — Parçalama:

Client ──► Any node (auto-redirect to correct shard)

Shard 1 (Master A + Replica A')
Shard 2 (Master B + Replica B')
Shard 3 (Master C + Replica C')

Hash slots: 0-16383 distributed across shards
No central proxy — clients connect directly

Önbelleğe Alma Desenleri

Önbellek Kenarı (tembel yükleme):

def get_user(user_id: str) -> dict:
    # Try cache first
    cached = redis.get(f"user:{user_id}")
    if cached:
        return json.loads(cached)

    # Cache miss — load from database
    user = db.query("SELECT * FROM users WHERE id = %s", user_id)

    # Store in cache with TTL
    redis.setex(f"user:{user_id}", 3600, json.dumps(user))

    return user

İçten Yazma:

def update_user(user_id: str, data: dict):
    # Update database
    db.execute("UPDATE users SET ... WHERE id = %s", data, user_id)

    # Update cache immediately
    redis.setex(f"user:{user_id}", 3600, json.dumps(data))

Arkasına Yazma (zaman uyumsuz):

def write_behind(user_id: str, data: dict):
    # First to cache (instant)
    redis.setex(f"user:{user_id}", 3600, json.dumps(data))

    # Queue for async database write
    redis.lpush("write_queue", json.dumps({
        'user_id': user_id,
        'data': data,
        'timestamp': time.time()
    }))

# Background worker processes the queue
def write_worker():
    while True:
        task = json.loads(redis.brpop("write_queue")[1])
        db.execute("UPDATE users SET ... WHERE id = %s",
                   task['data'], task['user_id'])

Önbelleğe Alma Stratejileri

Önbellek Geçersiz Kılma Stratejileri

Strateji Mekanizma En İyisi
TTL tabanlı Yaşam süresini ve otomatik sona erme süresini ayarlayın Eski veriler kabul edilebilir
İçine yazma Her yazmada önbelleği güncelle Okuma-ağır, yazma-hafif
Arkasına yazma DB'ye zaman uyumsuz yazma Yazma ağırlıklı, nihai tutarlılık tamam
Önbelleğin geçersiz kılınması Açık silme/güncelleme Güçlü tutarlılık gerekli
Sürüm bazlı Önbellek anahtarı sürümü içerir Şema değişiklikleri

Tahliye Politikaları

Politika Açıklama Kullanım Örneği
LRU (En Son Kullanılan) Erişilen en eski anahtarı çıkar Genel amaçlı
LFU (En Az Sık Kullanılan) En az erişilen anahtarı çıkar Kararlı erişim modelleri
TTL Otomatik süresi dolan anahtarlar Oturum verileri, geçici önbellek
Rastgele Rastgele tahliye Basit, öngörülebilir
Tahliye yok Tam bellekte dönüş hatası Kritik veriler kalmalı
# Redis eviction policy
maxmemory 4gb
maxmemory-policy allkeys-lru  # or: volatile-lru, allkeys-lfu, volatile-ttl

Diğer Bellek İçi Veritabanları

Memcached — Basit, Hızlı, Çok İş Parçacıklı

# Simple key-value (no persistence, no replication)
memcached -m 4096 -p 11211 -t 4

# Usage (similar to Redis but simpler)
set user:100 0 3600 15  # key, flags, ttl, byte_count
"Hello, World!"
get user:100

Redis ve Memcached:

Özellik Redis Memcached
Veri yapıları Dizeler, listeler, kümeler, karmalar, akışlar vb. Yalnızca dizeler
İstikrar RDB + AOF Yok
Çoğaltma Ana kopya + Küme Yok
İşlemler MULTI/EXEC, Lua Yok
Bellek verimliliği İyi (sıkıştırma seçenekleri var) Daha iyi (daha düşük yük)
İş parçacığı geçirme Tek iş parçacıklı (olay döngüsü) Çok iş parçacıklı
Kullanım örneği Genel amaçlı önbellek + veri yapıları Yalnızca basit önbellek

Dragonfly — Modern Redis Alternatifi

# Dragonfly is multi-threaded (faster on multi-core CPUs)
dragonfly --bind 0.0.0.0 --port 6379

# Same Redis protocol, same clients
redis-cli SET key value
redis-cli GET key

Hazelcast, Apache Ignite — Dağıtılmış Bellek İçi Veri Izgaraları

// Hazelcast — distributed cache with processing
import com.hazelcast.core.HazelcastInstance;
import com.hazelcast.map.IMap;

HazelcastInstance hz = Hazelcast.newHazelcastInstance();
IMap<String, User> cache = hz.getMap("users");

cache.put("user:100", user);
User cached = cache.get("user:100");

// Distributed computing
cache.executeOnKey("user:100", entry -> {
    User user = entry.getValue();
    user.incrementLoginCount();
    entry.setValue(user);
    return null;
});

Yaygın Kullanım Durumları

1. Oturum Depoları

def create_session(user_id: str) -> str:
    session_id = str(uuid.uuid4())
    redis.setex(
        f"session:{session_id}",
        86400 * 7,  # 7 days
        json.dumps({
            'user_id': user_id,
            'created_at': time.time(),
            'ip': request.remote_addr,
            'user_agent': request.user_agent,
        })
    )
    return session_id

def validate_session(session_id: str) -> dict | None:
    data = redis.get(f"session:{session_id}")
    if data:
        return json.loads(data)
    return None

2. Hız Sınırlaması

import time

def check_rate_limit(user_id: str, max_requests: int = 100,
                     window_seconds: int = 60) -> bool:
    key = f"ratelimit:{user_id}:{int(time.time()) // window_seconds}"

    count = redis.incr(key)
    if count == 1:
        redis.expire(key, window_seconds)

    return count <= max_requests

# Token bucket algorithm (more precise)
def token_bucket(user_id: str, capacity: int = 100,
                 refill_rate: float = 1.0) -> bool:
    key = f"token_bucket:{user_id}"
    now = time.time()

    lua = """
    local key = KEYS[1]
    local now = tonumber(ARGV[1])
    local capacity = tonumber(ARGV[2])
    local refill_rate = tonumber(ARGV[3])

    local bucket = redis.call('HMGET', key, 'tokens', 'last_refill')
    local tokens = tonumber(bucket[1]) or capacity
    local last_refill = tonumber(bucket[2]) or now

    local elapsed = now - last_refill
    tokens = math.min(capacity, tokens + elapsed * refill_rate)

    if tokens >= 1 then
        tokens = tokens - 1
        redis.call('HMSET', key, 'tokens', tokens, 'last_refill', now)
        return 1
    else
        return 0
    end
    """
    return bool(redis.eval(lua, 1, key, now, capacity, refill_rate))

3. Gerçek Zamanlı Skor Tabloları

def add_score(game_id: str, player: str, score: int):
    redis.zadd(f"leaderboard:{game_id}", {player: score})

def get_top_players(game_id: str, n: int = 10) -> list[dict]:
    results = redis.zrevrange(
        f"leaderboard:{game_id}", 0, n - 1,
        withscores=True
    )
    return [
        {"player": player.decode(), "score": int(score)}
        for player, score in results
    ]

def get_player_rank(game_id: str, player: str) -> int:
    rank = redis.zrevrank(f"leaderboard:{game_id}", player)
    return rank + 1 if rank is not None else None

4. Mesaj Sırası / Pub-Sub

# PUBLISH/SUBSCRIBE
# Publisher
redis.publish("notifications:global",
              json.dumps({"type": "alert", "message": "System update at 2AM"}))

# Subscriber (separate process)
pubsub = redis.pubsub()
pubsub.subscribe("notifications:global")
for message in pubsub.listen():
    if message['type'] == 'message':
        process_notification(json.loads(message['data']))

# List-based queue (reliable)
redis.lpush("task_queue", json.dumps(task))
task = redis.brpop("task_queue")  # Blocking pop

Performans Optimizasyonu

Serileştirme Etkisi

Biçim Serileştirme Seri durumdan çıkarma Boyut (1000 ürün)
Turşu (Python) 1x 1x 100KB
JSON 0,8x 0,7x 180KB
Mesaj Paketi 0,6x 0,5x 130KB
Protobuf 0,9x 0,4x 75KB
Özel ikili 0,3x 0,2x 55KB

Boru Hattı (Gidiş-Dönüşleri Azaltın)

# Without pipeline: N round-trips
for user_id in user_ids:
    redis.get(f"user:{user_id}")  # N network calls

# With pipeline: 1 round-trip
pipe = redis.pipeline()
for user_id in user_ids:
    pipe.get(f"user:{user_id}")
results = pipe.execute()  # Single network call

Bağlantı Havuzu

import redis

class RedisPool:
    _instance = None
    _pool = None

    @classmethod
    def get_connection(cls) -> redis.Redis:
        if cls._pool is None:
            cls._pool = redis.ConnectionPool(
                host='redis-cluster.example.com',
                port=6379,
                max_connections=100,
                socket_timeout=2,
                retry_on_timeout=True,
                health_check_interval=30,
            )
        return redis.Redis(connection_pool=cls._pool)

İzleme

# Redis INFO
redis-cli INFO

# Key metrics to monitor:
connected_clients: 42
used_memory_human: 3.2G
used_memory_peak_human: 4.1G
total_commands_processed: 15238912
keyspace_hits: 984532
keyspace_misses: 5214
expired_keys: 11245
evicted_keys: 0
instantaneous_ops_per_sec: 4532
Metrik Uyarı Kritik Eylem
Bellek kullanımı > Maksimum belleğin %80'i > %95 Ölçeği artırın, TTL'yi optimize edin
İsabet oranı < %85 < %70 Önbelleğe alma stratejisini inceleyin
Çoğaltma gecikmesi > 1 saniye > 10 saniye Ağı kontrol edin, çoğaltın
Çıkarılan anahtarlar > 0 > 100/saat Belleği veya TTL'yi artırın

Sonuç

Bellek içi veritabanları modern, yüksek performanslı uygulamalar için temel altyapıdır:

  1. Önbellekleme için kullanın — Veritabanı yükünü azaltın, yanıt sürelerini iyileştirin.
  2. Gerçek zamanlı veriler için kullanın — Skor tabloları, hız sınırlaması, oturum yönetimi.
  3. Mesaj aracısı olarak kullanın — Pub/sub, görev kuyrukları, etkinlik akışları.
  4. Redis varsayılan seçimdir — Zengin veri yapıları, kalıcılık seçenekleri, kümeleme.
  5. Asla birincil veritabanı olarak kullanmayın — Veri kaybı riski, bellek sınırlamaları, sınırlı sorgulama yeteneği.

Karar Çerçevesi

Need sub-millisecond latency?
├─ Yes
│  Q: Complexity of operations?
│  ├─ Simple key-value: Memcached
│  ├─ Data structures, persistence: Redis
│  └─ Distributed computing: Hazelcast/Ignite
└─ No
   Q: Data fits in memory?
   ├─ Yes: Consider in-memory for performance
   └─ No: Disk-based (PostgreSQL, etc.)

Bellek içi veritabanları, veritabanlarını değiştirmekle ilgili değildir; her şeyi daha hızlı hale getirmekle ilgilidir.

Öne Çıkan Makaleler

2026’da Oluşturmaya Değer 50 Claude Skill
EditoryalTR
8 dkÜcretsiz

2026’da Oluşturmaya Değer 50 Claude Skill

Claude Skills, tekrarlanan promptları yeniden kullanılabilir workflow’lara dönüştürebilir. İşte yazma, kodlama, araştırma, iş, üretkenlik, tasarım, analiz ve destek için 50 pratik Claude Skill.

TeknolojiAIAi GuidesAI Agents
0 alkış
Oku
Senior Engineer’lardan Öğrendiğim 6 Kodlama Pattern’i
EditoryalTR
8 dkÜcretsiz

Senior Engineer’lardan Öğrendiğim 6 Kodlama Pattern’i

TeknolojiCodeProgrammingCoding
0 alkış
Oku
Özel Bir Yapay Zeka Not Asistanı Kurun
Öne çıkanTR
9 dkÜcretsiz

Özel Bir Yapay Zeka Not Asistanı Kurun

Markdown notlarını özel taslakları açığa çıkarmadan aranabilir bir asistana dönüştürün.

TeknolojiPlatform RehberleriYapay Zeka YazımıAIAutomationData
0 alkış
Oku

Yorumlar

0 yorum

Henüz onaylı yorum yok. Yeni yanıtlar moderasyon bekleyebilir.