Redis yük testi: komut gecikmesi, connection pool ve sıcak anahtarlar
Redis tek bir komutu genellikle bir milisaniyenin altında cevaplar; bu yüzden Redis'in yük altındaki sorunları ortalamada değil kuyrukta görünür. Komutları tek bir thread'de sırayla işlediği için yavaş bir komut (büyük bir anahtar, geniş bir tarama) arkasındaki bütün komutları bekletir. Redis yük testi gerçekçi bir komut karışımını hedef hızda çalıştırır ve sorar: p99 gecikme bu hızda nerede, uygulamanın connection pool'u yetiyor mu, ve bellek ile eviction yük altında nasıl davranıyor.
Neyi ölçüyoruz?
- Komut gecikmesi: p95, p99 ve en yüksek değer. Ortalama burada neredeyse hiçbir şey söylemez (p95 ve p99 rehberi).
- Throughput: saniyede işlenen komut sayısı. Tek thread'li bir Redis'te sınır genellikle bir CPU çekirdeğidir; cluster'da yük shard'lara dağılır.
- Bağlantılar ve pool: client tarafında pool'dan bağlantı beklemek, Redis'in kendisi hızlıyken bile gecikmeyi büyütür. Pool boyutu ölçümün bir parçasıdır.
- Bellek ve eviction: anahtar sayısı ve değer boyutu büyüdükçe bellek dolar;
maxmemory'ye ulaşınca Redis eviction politikasına göre anahtar siler ya da yazmaları reddeder. Uzun bir testte (soak testi) bu davranışı görün. - Hit oranı: önbellek olarak kullanılan Redis'te okumaların ne kadarının bir değer bulduğu. Hit oranı düştükçe yük arkadaki veritabanına kayar.
Yük modelini kurmak
Redis için hedef neredeyse her zaman bir hızdır ("saniyede 4.000 komut"), bu yüzden sabit bir varış hızı (arrival rate) kullanın. Komut karışımını canlıdan alın: okuma/yazma oranı, kullanılan veri yapıları (string, hash, sorted set, list) ve değer boyutları. Anahtarları gerçekçi bir aralıktan seçin: hep aynı birkaç anahtarı okumak her şeyi önbellekte tutar, gerçek dağılım ise genellikle birkaç sıcak anahtar ve uzun bir kuyruktan oluşur. Redis'in hangi hızda kırıldığını bulmak için hızı basamaklarla artırın (kırılma noktası testi).
Sık yapılan hatalar
- Küçük ve aynı değerler. 10 baytlık değerlerle yapılan bir test, 50 KB'lık JSON'lar saklayan bir uygulamanın ağ ve bellek yükünü göstermez. Değer boyutlarını canlıya benzetin.
- Yavaş komutlar.
KEYS, büyük kümelerdeSMEMBERSya daHGETALL, uzun aralıklıZRANGEtek thread'i meşgul eder. Uygulamanız bunları kullanıyorsa teste koyun ve kuyruktaki etkisini görün; kullanmıyorsa koymayın. - Uzak yük üreticisi. Redis'in cevabı milisaniyenin altındayken ağ gidiş-dönüşü ölçümün çoğunu oluşturur. Yükü uygulamanızın Redis'e uzaklığına benzer bir yerden üretin.
- Paylaşılan anahtar alanı. Test yazmalarını canlı anahtarlarla çakışmayacak bir önek altında yapın (
loadtest:gibi) ve bir TTL verin; böylece test bittiğinde kendiliğinden temizlenir.
Spitfire ile
Önce Bağlantılar'da bir Redis bağlantısı ekleyin: adresler (host:6379), mod (tek sunucu, cluster ya da sentinel; sentinel'de master adı), ACL kullanıcı adı, parola, veritabanı numarası, pool boyutu (varsayılan 50) ve gerekiyorsa TLS. Parola şifreli saklanır, testte yalnız bağlantının adı geçer. Her runner'daki VU'lar bağlantı başına tek bir connection pool'u paylaşır, tıpkı bir uygulama instance'ı gibi; N runner N pool demektir. Başarısız bir komut tekrar denenmez: tekrar denemek hatayı gizler ve gecikmeleri toplar.
Redis adımı tek bir komut çalıştırır: komutun adı ve argümanları, editörde tek satır (SET "user:{{__VU}}" "{{$uuid}}" EX 60), JSON'da bir dizi olarak. Komutun adı sabit bir kelimedir, argümanların her biri {{$randInt 1 100000}}, {{$randString 512}} ya da CSV veri dosyasından değişkenler içerebilir. Adımın süresi komutun gidiş-dönüşüdür ve pool'dan bağlantı beklemeyi de içerir. Cevap JSON olarak kontrollere ve değişken çıkarmaya gider: string'ler, sayılar, diziler ve (RESP3'te) map'ler olduğu gibi. Var olmayan bir anahtar hata değildir: adımın durumu nil olur ve cevap null'dır; dizi cevaplarında eleman sayısı satır sayısı olarak raporlanır ve rowCount kontrolüyle sınanabilir. Hatalar türüne göre ayrılır: kimlik doğrulama ve yetki, salt okunur replica, sözdizimi, bağlantı reddi ve zaman aşımı.
Tehlikeli komutlar onay ister. SET, DEL ya da INCR gibi sıradan yazmalar normal yük testi trafiğidir. Paylaşılan bir sunucuyu bozabilecek komutlar (FLUSHALL, FLUSHDB, KEYS, CONFIG, SHUTDOWN, SCRIPT, MONITOR ve benzerleri; bir EVAL betiğinin içinde çağrılanlar dahil) adımda açıkça onaylanmadan test kaydedilmez, onaylanmışsa da test her başlatıldığında ayrıca onay ister (güvenlik beyanı). Bir adım tek komuttur: pipeline ve MULTI/EXEC işlemleri adımlar arasında kurulamaz.
Bir oturum önbelleği: saniyede 2.000 iterasyon, her biri rastgele bir oturumu okur ve rastgele bir oturuma 512 karakterlik bir değeri 10 dakikalık TTL ile yazar (saniyede 4.000 komut). Okuma kontrolü hem bulunan hem bulunamayan anahtarı başarılı sayar; okumanın p99'u 5 ms'nin, hata oranı %0,1'in altında kalmalı. Test spitfire validate ile doğrulandı.
{
"name": "Redis: oturum önbelleği",
"scenarios": [
{ "name": "oturum",
"executor": { "type": "constant-arrival-rate", "rate": 2000, "timeUnit": "1s",
"duration": "10m", "preAllocatedVUs": 50, "maxVUs": 200 },
"steps": [
{ "id": "get", "name": "Oturum oku", "protocol": "redis", "connection": "cache",
"redis": { "command": ["GET", "loadtest:session:{{$randInt 1 100000}}"] },
"checks": [ { "type": "status", "op": "in", "value": ["ok", "nil"] } ] },
{ "id": "set", "name": "Oturum yaz", "protocol": "redis", "connection": "cache",
"redis": { "command": ["SET", "loadtest:session:{{$randInt 1 100000}}",
"{{$randString 512}}", "EX", "600"] } }
] }
],
"thresholds": [
{ "metric": "req_duration", "filter": { "step": "get" }, "expr": "p(99)<5" },
{ "metric": "req_failed", "expr": "rate<0.001" }
]
}Koşu sırasında adım bazında komut hızı, p95, p99, gönderilen ve alınan veri ve hata türleri canlı izlenir. Redis'in kendi metriklerini (bellek, eviction, bağlı client'lar, hit oranı) bir Prometheus exporter'ıyla topluyorsanız Observability'te bir Prometheus bağlantısına ekleyin; koşu sayfasının Backend sekmesi onları yük basamaklarıyla hizalı gösterir. Redis çoğu zaman bir veritabanının önündedir; aynı testte veritabanını da yüklemek için SQL yük testi rehberine bakın.
Spitfire tek komutla Docker'a ya da Kubernetes'e kurulur; ücretsiz sürümde bütün test özellikleri ve protokoller açıktır.