Redis'e bağlı istemcileri görmek için CLIENT LIST, belirli bir bağlantıyı kapatmak için CLIENT KILL, bağlantılara ad vermek için CLIENT SETNAME kullanılır. Bağlantı sayısının üst sınırı maxclients (varsayılan 10.000), boşta kalan bağlantıların kapanma süresi timeout (varsayılan olarak kapatılmaz), istemci tamponlarının sınırları ise client-output-buffer-limit ve maxmemory-clients ayarlarıyla belirlenir.

Bu yazıda Redis'in bağlantıları nasıl kabul ettiğini, bağlantı sınırını, çıkış tamponu sınırlarını, istemci çıkarma (client eviction) mekanizmasını, zaman aşımını ve CLIENT komut ailesinin günlük yönetimde en çok işe yarayan alt komutlarını anlatıyoruz. Son bölümde bir bağlantı sızıntısını adım adım bulmayı gösteriyoruz. Serinin diğer yazıları için Redis öğrenme rehberi sayfasına bakın.

Redis bağlantıları nasıl kabul eder

Redis istemci bağlantılarını yapılandırılmış TCP portunda ve etkinse Unix soketinde kabul eder. Yeni bir bağlantı geldiğinde soket engellemesiz (non-blocking) moda alınır, çünkü Redis çoklama ve engellemesiz G/Ç kullanır; gecikme olmaması için TCP_NODELAY seçeneği açılır ve yeni veri geldiğinde sorguları hemen okuyabilmek için bir okuma olayı oluşturulur. Bu işlemlerden sonra Redis, eşzamanlı istemci sınırına ulaşılıp ulaşılmadığını kontrol eder.

İstemcilerin hangi sırayla servis edildiği, soket dosya tanımlayıcısı numarası ve çekirdeğin olayları bildirme sırasına bağlıdır; belge bu sıranın belirsiz kabul edilmesi gerektiğini söyler. Redis her istemci soketinde, okunacak yeni veri olduğunda yalnızca tek bir read() çağrısı yapar; böylece çok hızlı sorgu gönderen birkaç istemci diğerlerini cezalandırmaz. Okunan tamponda birden çok komut varsa bunlar sırayla işlenir.

maxclients ve ERR max number of clients reached

Eşzamanlı istemci sınırı redis.conf içindeki maxclients yönergesiyle ayarlanır ve varsayılanı 10.000'dir. Redis ayrıca çekirdekten açabileceği en fazla dosya tanımlayıcısı sayısını (yumuşak sınır) sorar. Bu sınır, istenen istemci sayısı artı Redis'in iç kullanım için ayırdığı 32 tanımlayıcıdan küçükse, maxclients değeri işletim sisteminin gerçekten izin verdiği sayıya indirilir ve başlangıçta bunu bildiren bir günlük satırı yazılır:

bash
$ ./redis-server --maxclients 100000
[41422] 23 Jan 11:28:33.179 # Unable to set the max number of files limit to 100032 (Invalid argument), setting the max clients configuration to 10112.

Belge, belirli bir istemci sayısı hedefliyorsanız işletim sisteminin süreç başına dosya tanımlayıcısı sınırını da buna göre ayarlamanızı önerir ve Linux için ulimit -Sn 100000 (yalnızca katı sınır yeterince büyükse çalışır) ile sysctl -w fs.file-max=100000 komutlarını örnek verir. Linux sunucu yönetiminin genel konuları için Linux sunucu yönetimi yazısına bakabilirsiniz.

Sınır dolduğunda Redis yeni bağlantıya bir hata gönderip bağlantıyı hemen kapatır; yeni soketin çıkış tamponu genellikle hatayı alacak kadar büyük olduğu için mesaj istemciye ulaşır. Hatanın metni şudur; cluster içinde diğer düğümlerden gelen bağlantılar da sınıra sayılır ve mesaj ERR max number of clients + cluster connections reached olur:

text
ERR max number of clients reached

Hata sayfası çözümü üç adıma ayırır. Önce INFO clients ile connected_clients (replikalar hariç bağlantı sayısı) ve maxclients değerlerini karşılaştırın; INFO stats içindeki rejected_connections alanı sınır yüzünden reddedilen bağlantıları sayar. Sonra CLIENT LIST ile bağlantıların nereden geldiğine bakın: aynı uygulamadan gelen ve uzun süredir boşta duran çok sayıda bağlantı, genellikle uygulamanın bağlantıları kapatmadığını gösterir. Son olarak nedeni giderin: her istek için yeni bağlantı açan uygulamayı tek bir istemci ya da havuz kullanacak şekilde düzeltin, çok kopyalı dağıtımlarda havuz boyutunu küçültün, gerekirse timeout ayarlayın ya da maxclients değerini yükseltin. Bağlantı havuzu tasarımı bağlantı URL ve connection pool yazısında.

Çıkış tamponu sınırları

Çıkış tamponu sınırları: Normal istemci, Pub/Sub istemcisi, Replika

Redis her istemci için değişken uzunlukta bir çıkış tamponu tutar, çünkü bir komut büyük miktarda veri üretebilir. İstemci yanıtları Redis'in gönderebildiğinden hızlı biriktirirse (özellikle mesajları yeterince hızlı işleyemeyen Pub/Sub istemcilerinde) tampon büyür ve bellek tüketir. Bu yüzden Redis istemci türüne göre sınırlar koyar; sınır aşıldığında bağlantı kapatılır ve olay günlüğe yazılır.

İki tür sınır vardır. Katı sınır sabittir; aşıldığı anda Redis bağlantıyı mümkün olan en kısa sürede kapatır. Yumuşak sınır zamana bağlıdır: örneğin 10 saniyede 32 megabaytlık bir yumuşak sınır, tamponun kesintisiz 10 saniye boyunca 32 megabaytın üzerinde kalması durumunda bağlantının kapanacağı anlamına gelir.

İstemci türüVarsayılan katı sınırVarsayılan yumuşak sınır
Normal istemci0 (sınır yok)0 (sınır yok)
Pub/Sub istemcisi32 megabayt60 saniyede 8 megabayt
Replika256 megabayt60 saniyede 64 megabayt

Normal istemcilerin sınırsız olmasının nedeni, çoğu istemcinin tek komut gönderip yanıtı tamamen okuduktan sonra bir sonrakini göndermesidir; böyle bir istemcinin bağlantısını kesmek istenmez. Sınırlar CONFIG SET ile çalışırken ya da kalıcı olarak redis.conf ile değiştirilebilir; ayar sözdizimi için Redis dağıtımındaki örnek redis.conf dosyasına bakılması önerilir. Sınır yüzünden kesilen bağlantıların toplamı INFO stats içindeki client_output_buffer_limit_disconnections alanında görünür.

Sorgu tamponu için ise yapılandırılamayan, 1 GB'lık bir katı sınır vardır. Bu sınır, istemci ya da sunucu yazılımındaki hatalar yüzünden sunucunun çökmesini önlemek için konmuş uç bir güvenlik önlemidir; sınıra ulaşılınca bağlantı kapatılır ve client_query_buffer_limit_disconnections sayacı artar.

İstemci çıkarma: maxmemory-clients

Redis 7.0 ile gelen istemci çıkarma (client eviction), tüm istemci bağlantılarının toplam belleği bir eşiği aştığında bağlantıları kesen bir güvenlik mekanizmasıdır. Toplama sorgu tamponu, çıkış tamponu ve diğer ara tamponlar dahildir. Mekanizma önce en çok bellek kullanan istemcileri keser ve eşiğin altına dönmek için gereken en az sayıda bağlantıyı kapatır. Replika ve birincil (master) bağlantıları bu mekanizmadan etkilenmez.

Eşik maxmemory-clients ayarıdır ve redis.conf ya da CONFIG SET ile verilebilir. Değer 0 (sınır yok, varsayılan), mb ya da gb ekli bir bayt miktarı veya % ekiyle maxmemory değerinin bir yüzdesi olabilir. Belge büyük üretim kurulumlarında sıfırdan farklı bir değer verilmesini kuvvetle önerir ve başlangıç için 5% değerini örnek gösterir. Bu yolla kesilen bağlantılar INFO stats içindeki evicted_clients alanında sayılır.

text
CONFIG SET maxmemory-clients 5%
CLIENT NO-EVICT on

Bazı bağlantıların hiçbir zaman kesilmemesini isteyebilirsiniz; örneğin sunucuyu INFO ile izleyip sorun olduğunda alarm veren bir aracın bağlantısı. Bu bağlantıdan CLIENT NO-EVICT on gönderdiğinizde o bağlantı çıkarma işleminin dışında tutulur; CLIENT NO-EVICT off ile yeniden aday havuzuna döner. Komut başarılıysa OK döner. Bu ayar veri anahtarlarının çıkarılmasıyla ilgili değildir; anahtar çıkarma politikaları maxmemory ve eviction yazısında anlatılıyor.

timeout ve TCP keepalive

Güncel Redis sürümleri varsayılan olarak boşta kalan bir istemcinin bağlantısını kapatmaz; bağlantı sonsuza kadar açık kalabilir. İsterseniz redis.conf ya da CONFIG SET timeout <saniye> ile bir zaman aşımı koyabilirsiniz; bu durumda belirtilen süreden uzun boşta kalan bağlantı kapatılır. Zaman aşımı yalnızca normal istemcilere uygulanır, Pub/Sub istemcilerine uygulanmaz; çünkü abonelik bağlantısı itme (push) tarzıdır ve boşta beklemesi olağandır.

Belge zaman aşımının iki durumda mantıklı olduğunu söyler: istemci yazılımındaki bir hatanın sunucuyu boşta bağlantılarla doldurabileceği kritik uygulamalar ve böyle bir hata yaşandığında sunucuya yeniden bağlanabilmek için bir hata ayıklama önlemi. Zaman aşımının kesin olmadığını da bilin: Redis boşta istemcileri bulmak için zamanlayıcı ya da O(N) tarama kullanmaz, kontrolü zaman zaman ve parça parça yapar. Belgedeki örneğe göre 10 saniyelik bir zaman aşımında, çok sayıda istemci bağlıysa bağlantı örneğin 12 saniye sonra kapanabilir.

Redis 3.2 ve sonrasında TCP keepalive (SO_KEEPALIVE) varsayılan olarak açıktır ve yaklaşık 300 saniyeye ayarlıdır. Bu, bağlı görünen ama aslında ulaşılamayan istemcileri tespit etmeye yarar; ayrıca bağlantıyı açık tutmak için trafik görmek isteyen ağ cihazları arasında beklenmedik bağlantı kopmalarını önler.

CLIENT LIST: bağlantıları listelemek

CLIENT LIST: bağlantıları listelemek: Benzersiz 64 bit istemci kimliği, addr, laddr, name

CLIENT LIST bağlı istemcileri ve durumlarını, her satırda bir bağlantı olacak şekilde, büyük ölçüde okunabilir bir metin olarak döndürür. Belgedeki örnekte iki istemci bağlıdır:

text
redis 127.0.0.1:6379> client list
addr=127.0.0.1:52555 fd=5 name= age=855 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=32768 obl=0 oll=0 omem=0 events=r cmd=client
addr=127.0.0.1:52787 fd=6 name= age=6 idle=5 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=ping

Güncel sürümlerde satırlarda çok daha fazla alan bulunur. Günlük işlerde en çok bakacağınız alanlar şunlardır:

AlanAnlamı
idBenzersiz 64 bit istemci kimliği
addrİstemcinin IP adresi ve uzak portu
laddrİstemcinin bağlandığı yerel (bind) adres ve port
nameCLIENT SETNAME ile verilen ad
ageBağlantının toplam süresi, saniye
idleBağlantının boşta kaldığı süre, saniye
flagsİstemci bayrakları; N özel bayrak yok demektir
dbSeçili veritabanı numarası
sub, psub, ssubKanal, desen ve shard kanal abonelik sayıları
omemÇıkış tamponunun kullandığı bellek
tot-memİstemcinin tüm tamponlarda tükettiği toplam bellek
cmdSon çalıştırılan komut
userBağlantının kimlik doğruladığı kullanıcı adı
lib-name, lib-verİstemci kütüphanesinin adı ve sürümü

Bayraklardan bazıları sorun giderirken özellikle işe yarar: b engelleyen bir işlemde bekleyen istemciyi, P Pub/Sub abonesini, O MONITOR modundaki istemciyi, x MULTI/EXEC bağlamındaki istemciyi, e istemci çıkarma dışında tutulan bağlantıyı, S replika bağlantısını, U Unix soketiyle bağlananı gösterir.

Listeyi süzmek için iki seçenek vardır: TYPE ile normal, master, replica ya da pubsub türündeki istemcileri, ID ile verdiğiniz kimliklerdeki istemcileri listeleyebilirsiniz. MONITOR ile engellenmiş istemciler normal sınıfına girer. Belge, hata ayıklama amacıyla düzenli olarak yeni alanlar eklendiğini ve bazılarının ileride kaldırılabileceğini, bu yüzden çıktıyı ayrıştıran kodun eksik alanları ve bilinmeyen alanları sorunsuz atlaması gerektiğini vurgular.

text
CLIENT LIST TYPE pubsub
CLIENT LIST ID 12 15

Yalnızca kendi bağlantınızın bilgisini görmek için CLIENT INFO kullanın; çıktı biçimi CLIENT LIST ile aynıdır. CLIENT ID ise bağlantının kimliğini tamsayı olarak döndürür ve iki garanti verir: kimlik asla tekrar kullanılmaz, ve tekdüze artar; yani daha büyük kimlikli bağlantı sunucuya daha sonra kurulmuştur.

CLIENT SETNAME ve CLIENT SETINFO

CLIENT SETNAME geçerli bağlantıya bir ad verir; bu ad CLIENT LIST çıktısındaki name alanında görünür ve Redis 4.0'dan beri SLOWLOG çıktısında da yer alır. Belgenin örneğinde bir kuyruk uygulamasında üreticiler ve tüketiciler bağlantılarını rollerine göre adlandırır. Ad uzunluğu için Redis string sınırı (512 MB) dışında bir sınır yoktur; ancak CLIENT LIST biçimini bozacağı için ada boşluk koyamazsınız. Adı boş metinle ayarlamak adı kaldırır. Her yeni bağlantı adsız başlar; CLIENT GETNAME ad verilmemişse nil döndürür.

text
CLIENT SETNAME siparis-isci-1
CLIENT GETNAME

CLIENT SETINFO ise kütüphane bilgisini (LIB-NAME ve LIB-VER) bağlantıya iliştirir. Belgeye göre istemci kütüphanelerinin bu komutu kimlik doğrulamadan sonra tüm bağlantılarda pipeline ile göndermesi ve eski sürümlü sunuculardan gelebilecek hataları yok sayması beklenir. Bu yüzden resmî kütüphanelerle bağlandığınızda lib-name ve lib-ver alanlarını genellikle dolu görürsünüz.

CLIENT KILL: bağlantı kapatmak

CLIENT KILL: bağlantı kapatmak: ID client-id, TYPE normal, master, replica, pubsub, USER kullanıcı, ADDR ip:port

CLIENT KILL iki biçimde çalışır. Eski biçim tek argüman olarak ip:port alır; bu değer CLIENT LIST çıktısındaki addr alanıyla eşleşmelidir ve başarıda OK döner. Yeni biçim ise filtre değer çiftleri alır ve kaç bağlantının kapatıldığını tamsayı olarak döndürür; bu sayı sıfır olabilir. Birden çok filtre verdiğinizde mantıksal VE ile birleştirilir.

FiltreKapatılan bağlantılar
ID client-idVerilen benzersiz kimliğe sahip istemci
TYPE normal, master, replica, pubsubVerilen türdeki istemciler
USER kullanıcıVerilen ACL kullanıcısıyla doğrulanmış istemciler
ADDR ip:portVerilen adresten bağlanan istemci
LADDR ip:portSunucunun verilen yerel adresine bağlanan istemciler
SKIPME yes veya noKomutu gönderen bağlantının atlanıp atlanmayacağı; varsayılan yes
MAXAGE saniyeVerilen süreden daha eski bağlantılar
text
CLIENT KILL addr 127.0.0.1:12345 type pubsub
CLIENT KILL USER eski-servis
CLIENT KILL ID 12

İlk satır belgedeki örnektir ve yalnızca belirtilen adresteki Pub/Sub istemcisini kapatır. İkinci satır, off yapılan bir ACL kullanıcısının hâlâ açık oturumlarını kapatmanın yoludur; ACL tarafı ACL yazısında anlatılıyor. Redis tek iş parçacıklı yapısı nedeniyle bir bağlantıyı komut çalıştırırken kapatamaz; istemci açısından bağlantı hiçbir zaman bir komutun ortasında kesilmez. İstemci, bağlantının kapandığını ancak bir sonraki komutu gönderdiğinde ağ hatasıyla fark eder.

CLIENT PAUSE: istemcileri kısa süre durdurmak

CLIENT PAUSE tüm istemcileri milisaniye cinsinden verilen süre boyunca askıya alır; replikalarla etkileşim normal sürer. ALL modu (varsayılan) tüm komutları, WRITE modu yalnızca yazma komutlarını bekletir. Belge, Redis 6.2'den beri önerilen modun WRITE olduğunu ve bu modun CLIENT UNPAUSE ile erken bitirilebildiğini belirtir. Tipik kullanım, bir örnekten diğerine kontrollü geçiştir: istemcileri durdurmak, replikaların son akışı işlemesini beklemek, replikayı birincile çevirmek ve istemcileri yeni birincile yönlendirmek. Duraklama süresince anahtarlar çıkarılmaz ve süreleri dolmaz; veri kümesi sabit kalır.

Uygulamalı örnek: bağlantı sızıntısını bulmak

Bir gün uygulamanız ERR max number of clients reached almaya başladı diyelim. Aşağıdaki sıra, belgelerdeki komut ve alanlarla kurulmuş kendi teşhis akışımızdır.

text
INFO clients
CLIENT LIST TYPE normal
CONFIG GET timeout
CONFIG GET maxclients

İlk komutta connected_clients değerinin maxclients değerine dayandığını görürsünüz. İkinci komutun çıktısında satırları addr alanındaki IP'ye ve name alanına göre gruplayın. Tek bir IP'den yüzlerce bağlantı geliyor ve bunların idle değerleri binlerce saniyeyse, o uygulama bağlantıları kapatmıyor ya da her istek için yeni bağlantı açıyor demektir. Kalıcı çözüm uygulama tarafındadır: tek bir istemci nesnesi ya da havuz kullanmak. Acil durumda o adresin bağlantılarını CLIENT KILL ADDR ile tek tek, ya da sızıntı yapan servisin ayrı bir ACL kullanıcısı varsa CLIENT KILL USER ile toplu kapatabilirsiniz. timeout değeri 0 ise boşta bağlantılar kendiliğinden kapanmaz; makul bir değer koymak tekrar etmesini sınırlar.

Bundan sonra her servise CLIENT SETNAME ile ad verdirmek, bir sonraki sefer teşhisi dakikalardan saniyelere indirir. Bellek tarafında istemci tamponlarının toplamını INFO memory içindeki mem_clients_normal alanıyla izleyebilirsiniz; ayrıntı bellek kullanımı yazısında.

Sık Sorulan Sorular

Redis boşta kalan bağlantıları kendisi kapatır mı?

Varsayılan olarak hayır; güncel sürümlerde boşta bağlantı açık kalır. timeout ayarıyla saniye cinsinden bir süre verirseniz normal istemciler bu süreden sonra kapatılır, Pub/Sub istemcileri bu kuraldan muaftır.

maxclients değerini yükseltmek yeterli mi?

Yükseltebilirsiniz, ancak her bağlantı bir dosya tanımlayıcısı kullanır; işletim sisteminin sınırı düşükse Redis değeri kendisi düşürür ve günlüğe yazar. Ayrıca sorunun nedeni çoğu zaman uygulamanın bağlantıları yeniden kullanmamasıdır.

CLIENT KILL hangi yanıtı döndürür?

Eski ip:port biçiminde bağlantı kapatıldıysa OK; filtreli yeni biçimde kapatılan bağlantı sayısını tamsayı olarak döndürür ve eşleşme yoksa sıfır olur.

İzleme aracımın bağlantısının kesilmesini nasıl önlerim?

maxmemory-clients ile istemci çıkarma etkinse, izleme aracının bağlantısından CLIENT NO-EVICT on gönderin. Bu bağlantı CLIENT LIST çıktısında e bayrağıyla görünür.

CLIENT LIST çıktısını kodla ayrıştırırken neye dikkat etmeliyim?

Alan listesi sürümlere göre değişir; bazı alanlar eklenir, bazıları kaldırılabilir. Belge, bilinmeyen alanları atlayan ve eksik alanlarda hata vermeyen bir ayrıştırıcı yazmanızı önerir.

Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.

İlgili içerikler: Redis öğrenme rehberi · Bağlantı URL ve connection pool · Redis ACL · INFO komutu ve sunucu izleme · CONFIG GET, SET ve REWRITE