İçeriğe Atla
Mustafa Erbay
Yaşam · 12 dk okuma · görüntülenme Read in English

Dağıtık Kilit Alternatiflerinin Gizli Maliyetleri ve Hayatımızdaki…

Dağıtık sistemlerde kilit mekanizmalarını seçerken karşılaştığım teknik ve operasyonel maliyetleri, somut örneklerle inceliyorum.

100%

Dağıtık sistemlerde bazen bir kaynağı aynı anda sadece bir işin kullanmasını sağlamak gerekiyor. Bu, en temel concurrency sorunlarından biri ve çözüm olarak aklımıza ilk gelen şey “kilit”. Ama bu kilitleri dağıtık bir ortamda yönetmek, düşündüğümüzden çok daha fazla maliyet getiriyor. Yıllar içinde, bu kilitlerin hayatımızı, projelerimizi ve cüzdanımızı nasıl etkilediğini defalarca gördüm. Bir üretim ERP’sinde kritik bir stok güncellemesi yaparken de, kendi yan ürünümün arka plan servislerinde bir işin tekil çalışmasını garanti etmeye çalışırken de bu maliyetlerle yüzleştim. Her seçimin bir bedeli var ve bu bedeller bazen gözden kaçabiliyor.

Basit Dosya Kilidi ve Gizli Maliyetleri

En basit haliyle, bir dosya kilidi kullanmak akla gelir. flock veya mkdir tabanlı çözümler, tek sunuculu ortamlarda iş görür gibi görünür. Bir betiğin aynı anda iki kere çalışmasını engellemek için mkdir /var/lock/myapp.lock && trap 'rmdir /var/lock/myapp.lock' EXIT gibi bir yöntemle başladım ben de. Bu, basit bir cron job için fena değil. Hatta daha da basiti, sadece bir PID dosyası yazıp kontrol etmek:

#!/bin/bash
LOCK_FILE="/var/run/myapp.pid"

if [ -f "$LOCK_FILE" ]; then
    PID=$(cat "$LOCK_FILE")
    if ps -p $PID > /dev/null; then
        echo "Uygulama zaten çalışıyor (PID: $PID)."
        exit 1
    else
        echo "Önceki kilit dosyası temizleniyor (PID: $PID bulunamadı)."
        rm -f "$LOCK_FILE"
    fi
fi

echo $$ > "$LOCK_FILE"
trap "rm -f $LOCK_FILE; exit" INT TERM EXIT

echo "Uygulama başlatıldı..."
# Uygulama mantığı buraya gelir
sleep 60
echo "Uygulama tamamlandı."

Ancak sistem dağıtık hale geldiğinde, bu yaklaşımların maliyetleri hızla artar. Birden fazla sunucuda aynı LOCK_FILE’a erişmek için NFS gibi bir paylaşımlı dosya sistemi kullanmanız gerekir. NFS’nin kendisi başlı başına bir karmaşa kaynağıdır: ağ gecikmeleri, sunucu çöküşleri, dosya sistemi tutarlılığı sorunları. Diyelim ki kilit dosyasını tutan NFS sunucusu çöktü. Ne olacak? Tüm uygulamalarınız kilitlenip kalabilir veya tam tersi, kilit dosyası algılanmadığı için hepsi aynı anda çalışmaya başlayıp veri bozulmasına yol açabilir.

Benim başıma gelen bir senaryoda, gece çalışan bir raporlama servisi, NFS bağlantısı koptuğu için kilit dosyasını oluşturamadı. Sonuç olarak, iki sunucudaki raporlama betikleri aynı anda çalıştı ve aynı verileri işlemeye çalıştı. Raporlar mükerrer çıktı, hatta bazı kritik iş süreçleri (ki faturalama ile ilgiliydi) yanlış verilerle devam etti. Bu hatayı bulmak ciddi zaman aldı. Basit bir dosya kilidi, dağıtık sistemlerde “gizli maliyet” olarak ciddi operasyonel yük, hatalı veri ve zaman kaybı olarak geri döner. Üstelik, bu tür kilitlerin atomikliği ve çökme durumlarındaki dayanıklılığı genellikle zayıftır, bu da onu production ortamları için riskli hale getirir.

Veritabanı Tabanlı Kilitler: Kolaylık ve Ölçeklenebilirlik Engelleri

Bir adım ötesi, veritabanı tabanlı kilitlerdir. PostgreSQL gibi bir veritabanında SELECT FOR UPDATE veya özel bir kilit tablosu kullanarak dağıtık kilit mekanizması oluşturmak mümkündür. Bu yöntem, veritabanının transaction özelliklerinden faydalandığı için atomiklik konusunda dosya kilitlerinden çok daha güvenilirdir. Bir ERP projesinde, belirli bir siparişin durumunu güncellerken birden fazla operatörün aynı anda müdahale etmesini engellemek için bu yöntemi kullanmıştım. pg_advisory_lock gibi daha sofistike fonksiyonlar da mevcuttur.

-- Özel bir kilit tablosu ile basit kilit
CREATE TABLE distributed_locks (
    lock_name VARCHAR(255) PRIMARY KEY,
    locked_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    locked_by VARCHAR(255)
);

-- Kilit almaya çalışma
BEGIN;
SELECT * FROM distributed_locks WHERE lock_name = 'my_critical_resource' FOR UPDATE;
-- Eğer satır yoksa, ekle
INSERT INTO distributed_locks (lock_name, locked_by) VALUES ('my_critical_resource', 'app_instance_1') ON CONFLICT (lock_name) DO NOTHING;
-- Eğer ekleme başarılıysa, kilit alındı. Değilse, başka biri aldı.
COMMIT;

Bu yöntem, transaction garantileri sayesinde daha sağlam görünse de, kendi maliyetleriyle gelir. İlk olarak, veritabanınız tek bir kilit sunucusu haline gelir. Yüksek contention durumlarında, tüm uygulamalarınız bu tek noktaya yüklenir ve veritabanı performansı düşer. Connection pool’lar tükenir, sorgular kuyruklanır, gecikmeler artar. Görece az sayıda eşzamanlı işlemde bile, kilit için yapılan sürekli denemeler ve transaction overhead’i veritabanı CPU’sunu beklenenden çok daha fazla yorabilir; darboğaz işlem hacminden değil, kilit etrafındaki rekabetten doğar.

İkinci olarak, veritabanı çöküşleri veya ağ sorunları durumunda, kilit durumu belirsiz hale gelebilir. Bir transaction açık kalırsa, kilit sonsuza kadar tutulabilir ve diğer tüm işlemler kilitlenir. Bu tür durumları izlemek ve otomatik olarak temizlemek için karmaşık uygulama mantığı veya ek monitoring sistemleri geliştirmek zorundasınız. Bu da ek geliştirme ve operasyonel maliyet demektir. Ayrıca, veritabanı replikasyonları olsa bile, kilit genellikle primary instance üzerinde tutulur, bu da failover durumlarında kilit mekanizmasının yeniden başlatılmasını veya tutarlılık sorunlarını beraberinde getirir. Tüm bu ek yükler, başlangıçtaki “kolay” çözümün aslında uzun vadede ne kadar pahalı olabileceğini gösterir.

Redis Kilitleri ve “Fencing Token” İhtiyacı

Redis, dağıtık kilitler için popüler bir seçenek haline geldi. SET resource_name my_random_value NX PX 10000 komutuyla, belirli bir key’i sadece bir kez (NX) ve belirli bir süre (PX) için ayarlayarak kilit mekanizması oluşturabiliriz. my_random_value ise kilit sahibi kimliğini temsil eden bir “fencing token” olarak kullanılır, böylece sadece kilidi alan client onu serbest bırakabilir.

import redis
import uuid
import time

r = redis.Redis(host='localhost', port=6379, db=0)

def acquire_lock(lock_name, acquire_timeout=10, lock_timeout=5):
    identifier = str(uuid.uuid4())
    end_time = time.time() + acquire_timeout
    while time.time() < end_time:
        if r.set(lock_name, identifier, nx=True, px=int(lock_timeout * 1000)):
            return identifier
        time.sleep(0.01)
    return None

def release_lock(lock_name, identifier):
    pipe = r.pipeline(transaction=True)
    pipe.watch(lock_name)
    if pipe.get(lock_name).decode() == identifier:
        pipe.multi()
        pipe.delete(lock_name)
        pipe.execute()
        return True
    pipe.unwatch()
    return False

# Örnek kullanım
lock_name = "my_resource_lock"
identifier = acquire_lock(lock_name)

if identifier:
    print(f"Kilit alındı: {identifier}")
    try:
        # Kritik işlem burada yapılır
        time.sleep(2)
    finally:
        release_lock(lock_name, identifier)
        print(f"Kilit serbest bırakıldı: {identifier}")
else:
    print("Kilit alınamadı.")

Redis kilitleri daha performanslı ve ölçeklenebilir olsa da, kendi karmaşıklıkları ve maliyetleriyle gelirler. En büyük sorunlardan biri, Redis’in tek instance çalıştığı durumlarda SPOF (Single Point of Failure) olmasıdır. Redis cluster veya Sentinel kullanarak yüksek erişilebilirlik sağlasanız bile, ağ bölümlenmeleri (network partitions) ve clock drift gibi sorunlar ortaya çıkabilir. Diyelim ki bir client kilidi aldı, işini yaparken bir ağ kesintisi yaşandı ve Redis’e “işim bitti, kilidi bırak” mesajını gönderemedi. Kilidin süresi dolduğunda, başka bir client kilidi alabilir. Önceki client’ın işi bitince Redis’e “kilidi bırak” mesajını gönderirse, aslında yeni client’ın kilidini bırakmış olabilir. Bu, “fencing token” ile çözülmeye çalışılan, ancak yine de dikkatli olunması gereken bir durumdur.

Redlock algoritması bu sorunları çözmek için tasarlanmıştır, ancak kendisi de ek karmaşıklık ve performans maliyeti getirir. Redlock, birden fazla Redis instance’ında kilit almayı gerektirir, bu da gecikmeyi artırır ve yönetim yükünü yükseltir. Kendi yan ürünümde, bir arama motoru indeksleme işinin tekil çalışmasını garanti etmek için Redis kilitlerini kullanmıştım. Başlangıçta basit SET NX PX yeterli oldu, ancak bir network probleminde indeksleme işinin iki kere çalıştığını ve indeksin bozulduğunu gördüm. Sonuç, indeksin sıfırdan yeniden oluşturulması ve uzunca süren bir downtime oldu. Bu tür olaylar, Redis kilitlerinin basit görünen yüzünün altında yatan “operasyonel maliyeti” çok iyi özetliyor.

Zookeeper/etcd Gibi Konsensus Tabanlı Sistemler

Dağıtık kilitlerin “altın standardı” olarak kabul edilen çözümlerden biri, Apache ZooKeeper veya etcd gibi konsensus tabanlı sistemlerdir. Bu sistemler, dağıtık bir ortamda tutarlılık ve dayanıklılık sağlamak için tasarlanmıştır. Paxos veya Raft gibi algoritmalar kullanarak, bir değerin (bu durumda kilit durumu) tüm düğümler arasında oy birliğiyle kabul edilmesini sağlarlar. Bu, Redis veya veritabanı tabanlı kilitlerden çok daha güvenilir ve doğru bir kilit mekanizması sunar. Kritik bir raporun aynı anda birden fazla iş tarafından üretilmesini gerçekten engellemek gerektiğinde, tutarlılık garantisi en katı olan seçenek tipik olarak budur.

# etcdctl ile basit bir kilit alma
# etcdctl get /mylock --for-write
# etcdctl put /mylock "locked" --lease=10  # 10 saniyelik bir lease ile
# İşlem bitince:
# etcdctl del /mylock

Bu sistemlerin en büyük maliyeti, operasyonel karmaşıklıklarıdır. ZooKeeper veya etcd cluster’ı kurmak, yönetmek ve izlemek, ayrı bir uzmanlık alanı gerektirir. Üç veya beş düğümlü bir cluster çalıştırmanız gerekir ki bu da daha fazla sunucu kaynağı, ağ bant genişliği ve yönetim yükü demektir. Ayrıca, kilit alma ve bırakma işlemleri, bir konsensus algoritması üzerinden geçtiği için Redis gibi in-memory bir veritabanına göre daha yüksek gecikmeye sahiptir. Her kilit işlemi, cluster’daki düğümler arasında bir oy birliği gerektirdiğinden, bu da ağ trafiğini artırır.

Benim için en büyük maliyetlerden biri, bu sistemlerin öğrenme eğrisi oldu. Bir etcd cluster’ını doğru şekilde yapılandırmak, yedeklemek, izlemek ve hatalarını ayıklamak, sıradan bir uygulama geliştiricinin veya sistem yöneticisinin günlük işi değildir. Yanlış yapılandırılmış bir cluster, ağ bölümlenmelerinde veya düğüm arızalarında tutarsız durumlara düşebilir, bu da tüm dağıtık kilit mekanizmanızın çökmesine yol açar. etcd gibi sistemler diske duyarlıdır; cluster’ın disk I/O’su yetersiz kaldığında kilit alma süreleri tahammül sınırlarını aşacak kadar uzayabilir ve uygulamadaki tüm kritik işlemler kilitlenip kalabilir. Bu tür “gizli” performans darboğazlarını bulmak ve gidermek, ciddi mühendislik eforu gerektirir.

Kendi Kilit Uygulamam ve Öğrendiklerim

Yıllar içinde, basit bir cron işinden karmaşık bir üretim ERP’sine kadar birçok farklı sistemde dağıtık kilitlerle cebelleştim. Bir noktada, “neden kendi basit kilit servisimi yazmayayım ki?” diye düşündüm. Amacım, yukarıdaki çözümlerin bazı dezavantajlarını aşmak ve daha hafif, amaca yönelik bir çözüm geliştirmekti. Bir REST API üzerinden kilit alıp bırakan, arkada basit bir PostgreSQL tablosu kullanan ve TTL (Time To Live) mekanizması olan bir servis yazdım. Bu servis, belirli bir süre içinde kilit serbest bırakılmazsa otomatik olarak kilidi serbest bırakıyordu, böylece ölü kilitlerin önüne geçiyordum.

# FastAPI ile basit bir kilit servisi örneği
# (Gerçek bir implementation çok daha karmaşık olacaktır, hata yönetimi vb.)
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
import time
import uuid

app = FastAPI()

# In-memory kilitler (production için uygun değil, örnek amaçlı)
# Production'da PostgreSQL veya Redis kullanılmalı
locks = {}

class LockRequest(BaseModel):
    resource_id: str
    ttl_seconds: int = 300 # Default 5 dakika

@app.post("/lock")
async def acquire_lock_endpoint(request: LockRequest):
    lock_id = str(uuid.uuid4())
    current_time = time.time()
    
    # Check if resource is already locked and if existing lock is expired
    if request.resource_id in locks:
        existing_lock = locks[request.resource_id]
        if current_time < existing_lock['expires_at']:
            raise HTTPException(status_code=409, detail="Resource already locked")
        else:
            # Expired lock, clean up and acquire new one
            del locks[request.resource_id]

    locks[request.resource_id] = {
        "lock_id": lock_id,
        "expires_at": current_time + request.ttl_seconds
    }
    return {"lock_id": lock_id, "message": "Lock acquired"}

@app.post("/unlock")
async def release_lock_endpoint(request: LockRequest, lock_id: str):
    if request.resource_id not in locks:
        raise HTTPException(status_code=404, detail="Resource not locked")
    
    existing_lock = locks[request.resource_id]
    if existing_lock['lock_id'] != lock_id:
        raise HTTPException(status_code=403, detail="Invalid lock_id for resource")
    
    del locks[request.resource_id]
    return {"message": "Lock released"}

Bu yaklaşımın da kendi maliyetleri oldu. Kendi kilit servisimi yazmak, başlangıçta bana kontrol hissi verse de, aslında sıfırdan bir dağıtık sistemin karmaşıklıklarını üstlenmek demekti. Zaman senkronizasyonu (clock drift), ağ gecikmeleri, servis çöküşleri ve otomatik kilit yenileme gibi konuları kendim ele almak zorunda kaldım. Örneğin, bir client kilidi aldıktan sonra işini bitirmeden çökerse, kilit TTL süresi bitene kadar kalıyor ve diğer işleri engelliyordu. Bunu aşmak için client’ların düzenli olarak “kalp atışı” göndererek kilidi yenilemeleri gerekiyordu, bu da client tarafında ek bir karmaşıklık demekti.

Üstelik tek başına çalışan böyle bir servis kendisi de bir SPOF’tur: süreç çökerse veya yeniden başlarsa tutulan tüm kilitler bir anda kaybolabilir. Standart bir kütüphane ya da yerleşik bir servisin getirdiği “güvenilirlik”, ancak bunları kendin baştan inşa etmeye kalkınca ne kadar değerli olduğunu gösteriyor. Kendi çözümüm, belirli bir senaryo için uygun olabilirken, genel bir çözüm olarak çok daha fazla bakım ve hata ayıklama maliyeti taşıyordu. Bu, mühendislik hayatımda “wheel re-invent etmenin” nadiren iyi bir fikir olduğunu öğrendiğim anlardan biriydi.

Maliyetleri Düşürmek: Ne Zaman Kilit Gereklidir?

Tüm bu kilit mekanizmalarının getirdiği maliyetleri gördükten sonra, en önemli soru şu hale geliyor: Gerçekten bir dağıtık kilide ihtiyacım var mı? Çoğu zaman cevabım “hayır” oluyor. Birçok durumda, kilit kullanmaktan kaçınarak veya farklı mimariler kullanarak bu maliyetlerden kurtulmak mümkün.

İlk olarak, idempotency kavramı. Eğer bir işlem birden fazla kez çalışsa bile aynı sonucu veriyorsa, neden kilitleyelim ki? Bir mesaj kuyruğundan gelen işleri işlerken, mesajları aynı anda birden fazla worker’ın işlemesi sorun değilse, kilit yerine idempotency anahtarları kullanmak daha basit ve ölçeklenebilir bir yaklaşımdır. Örneğin, bir ödeme işlemini sadece transaction_id’sine göre bir kez işlemek, birden fazla kez gelirse ignore etmek.

İkinci olarak, eventual consistency (nihai tutarlılık). Her şeyin anında tutarlı olması şart mı? Genellikle değildir. Bir kullanıcının sepete ürün eklemesi anında tüm dünyada görünmek zorunda değildir. Kısa bir gecikme kabul edilebilir. Bu durumda, CQRS (Command Query Responsibility Segregation) veya event-sourcing gibi mimarilerle, verinin tutarlı hale gelmesi için biraz zaman tanıyarak kilit ihtiyacını ortadan kaldırabiliriz. Bir üretim ERP’sinde stok seviyelerini anlık değil, birkaç saniye gecikmeyle güncelleyerek (ancak son tutarlı durumu garanti ederek) sistem üzerindeki kilit yükünü ciddi oranda azaltmıştık. Bu, gerçek zamanlı dashboard tasarımlarında da çok sık kullandığım bir yaklaşım.

Üçüncü olarak, optimistic locking. Özellikle veritabanı işlemlerinde, bir kaydı update ederken version kolonu gibi bir alan kullanarak, başka birinin aynı kaydı değiştirip değiştirmediğini kontrol edebiliriz. Eğer değiştirilmişse, kendi işlemimizi yeniden deneriz. Bu, contention’ın düşük olduğu durumlarda dağıtık kilitlerden çok daha hafif ve performanstır.

-- Optimistic Locking Örneği
UPDATE products
SET stock = stock - 1, version = version + 1
WHERE id = 123 AND version = <current_version_read_earlier>;

-- Eğer etkilenen satır sayısı 0 ise, başka bir işlem kaydı değiştirmiş demektir, yeniden denenebilir.

Bu yaklaşımlar, kilit mekanizmalarının getirdiği performans düşüşü, karmaşıklık ve operasyonel yük gibi maliyetleri önemli ölçüde azaltır. Dağıtık bir kilit kullanmadan önce, gerçekten hard-guaranteed tekil erişime ihtiyacınız olup olmadığını sorgulamak, mühendislik hayatınızda çok daha az baş ağrısı demektir. Çoğu zaman, daha basit ve daha esnek çözümler mevcuttur.

Sonuç: Kilitler Bir Zorunluluk mu, Bir Seçim mi?

Dağıtık kilitler, dağıtık sistem mimarilerinde kaçınılmaz bir zorunluluk gibi görünse de, aslında çoğu zaman birer seçimdir. Ve bu seçimin, yukarıda detaylandırdığım gibi, ciddi teknik, operasyonel ve hatta finansal maliyetleri vardır. Basit dosya kilitlerinden, veritabanı tabanlı çözümlere, Redis’in hızlı ama karmaşık dünyasından, ZooKeeper/etcd gibi konsensus devlerine kadar her bir alternatif, kendi içinde bir dizi ödünleşimi barındırır.

Benim deneyimim, dağıtık bir kilit uygulamadan önce durup düşünmek gerektiği yönünde. Gerçekten de bu kadar katı bir tekil erişime ihtiyacımız var mı? İdempotency, eventual consistency veya optimistic locking gibi alternatif yaklaşımlarla aynı işi daha esnek ve daha az maliyetli bir şekilde çözebilir miyiz? Geçen ay, kendi yan ürünümün bir komponentinde, başlangıçta bir Redis kilidi düşünmüştüm. Ancak sonra fark ettim ki, işin doğası gereği birden fazla kere çalışması sorun yaratmayacak, sadece bir last_run timestamp’ı ile kontrol edebileceğim bir senaryoydu. Bu basit farkındalık, hem geliştirme süresinden hem de olası operasyonel kabuslardan beni kurtardı.

Unutmayın, mühendislikte her zaman en güçlü veya en popüler aracı kullanmak en iyi çözüm değildir. Önemli olan, sorunu doğru anlamak ve o soruna en uygun, en az maliyetli ve en sürdürülebilir çözümü bulmaktır. Dağıtık kilitler, güçlü araçlardır ancak çok dikkatli ve bilinçli kullanılmalıdırlar. Bir sonraki kritik işleminizi tasarlarken, bu maliyetleri göz önünde bulundurarak daha bilinçli seçimler yapmanızı dilerim.

Paylaş:

Bu yazı faydalı oldu mu?

Yükleniyor...

Bu yazı nasıldı?

Sıkça Sorulanlar

Bu makale ile ilgili okurların sorduğu yaygın sorular.

Dağıtık sistemlerde kilit mekanizmalarını seçerken nelere dikkat etmelidir?
Ben dağıtık sistemlerde kilit mekanizmalarını seçerken, teknik ve operasyonel maliyetleri dikkate alıyorum. Örneğin, basit dosya kilidi kullanmak kolay gibi görünür, ancak dağıtık sistemlerde bu yaklaşımın maliyetleri hızla artabilir. Bu nedenle, farklı seçenekler arasında ticaret melakukan gerekiyor ve her seçimin bir bedeli olduğunu unutmamalıyım.
Birden fazla sunucuda aynı kilit dosyasını nasıl kullanabilirim?
Birden fazla sunucuda aynı kilit dosyasını kullanmak için, ben genellikle merkezi bir kilit yönetimi sistemi kullanıyorum. Örneğin, ZooKeeper veya etcd gibi araçlar, dağıtık sistemlerde kilitlerin merkezi olarak yönetilmesini sağlar. Bu sayede, birden fazla sunucuda aynı kilit dosyasını kullanmak mümkün hale gelir ve sistemlerin tutarlılığı sağlanabilir.
Kilit mekanizmalarının performans etkilerini nasıl ölçebilirim?
Kilit mekanizmalarının performans etkilerini ölçmek için, ben genellikle sistemin response thời ve işlem hızını ölçüyorum. Örneğin, kilit mekanizmalarını kullanarak bir işlemi gerçekleştirdiğimde, sistem response thời ve işlem hızını ölçerek, kilit mekanizmasının performans etkilerini değerlendirebilirim. Ayrıca, farklı kilit mekanizmaları arasında performans karşılaştırması da yapabilirim.
Dağıtık sistemlerde kilit mekanizmalarının güvenlik etkileri nelerdir?
Dağıtık sistemlerde kilit mekanizmalarının güvenlik etkileri önemli olabilir. Örneğin, eğer kilit mekanizması doğru şekilde yapılandırılmazsa, sistemlerin güvenliği tehlikeye girebilir. Ben genellikle, kilit mekanizmalarının güvenlik etkilerini değerlendirirken, kimlik doğrulama ve yetkilendirme gibi güvenlik önlemlerini dikkate alıyorum. Ayrıca, kilit mekanizmalarının güncellenmesi ve bakımı da önemli güvenlik önlemlerindendir.
ME

Mustafa Erbay

Sistem Mimarisi · Network Uzmanı · Altyapı, Güvenlik ve Yazılım

2006'dan bu yana sistem mimarisi, network, sunucu altyapıları, büyük yapıların kurulumu, yazılım ve sistem güvenliği ekseninde çalışıyorum. Bu blogda sahada karşılığı olan teknik deneyimlerimi paylaşıyorum.

Kişisel Notlar

Bu notlar sadece sizde saklanır. Tarayıcınızda yerel olarak tutulur.

Hazır 0 karakter

Yorumlar

Sunucu Taraflı AI Moderasyon

Yorumlar sunucuda yapay zeka ile denetlenir ve kalıcı olarak saklanır.

?
0/2000

Sunucu taraflı AI denetim

✉️ Ücretsiz · Spam yok · İstediğin an çık

Yeni yazılardan haberdar olun

Yeni içerikler ve teknik notlar e-postanıza gelsin.

  • 📌
    Haftanın en iyisi Sadece okumaya değer tek yazı
  • 🔧
    Alet çantası Bu hafta kullandığım araçlar
  • 🧠
    Perde arkası Blog'a girmeyen notlar

Spam yapmıyoruz. İstediğiniz zaman ayrılabilirsiniz. · Sadece Umami (self-hosted, Google yok) ile takip.

Okuma İstatistikleriniz

0

Yazı Okundu

0dk

Okuma Süresi

0

Gün Serisi

-

Favori Kategori

İlgili Yazılar