Redis kļūda "ERR max number of clients reached" nozīmē, ka serverim ir tik daudz atvērtu savienojumu, cik atļauj maxclients, tāpēc tas noraida jaunus. Komandas esošajos savienojumos turpina darboties, un atmiņa un CPU var izskatīties pilnīgi normāli. Tas ir jaudas limits, taču vairumā incidentu labot vajag nevis limitu. Kaut kas tur daudz vairāk savienojumu, nekā vajadzētu, vai operētājsistēma Redis ierobežoja zemāk, nekā domājat.
Kas tieši notiek pie limita
Pārbaude atrodas failā networking.c, un tā notiek, pieņemot savienojumu, pirms vēl tiek izveidots klienta objekts. Ja klientu skaits kopā ar klastera kopnes savienojumiem sasniedz vai pārsniedz maxclients, Redis uzraksta kļūdu, palielina skaitītāju un aizver soketu. Klients redz:
ERR max number of clients reached
Dažas šī koda detaļas praksē ir svarīgas:
- Klastera režīmā teksts ir cits: "ERR max number of clients + cluster connections reached". Klastera kopne tiek ieskaitīta tajā pašā limitā. redis.conf komentāri norāda, ka katrs mezgls izmanto divus kopnes savienojumus, vienu ienākošo un vienu izejošo, un ka ļoti lieliem klasteriem limits jāpielāgo atbilstoši.
- TLS klienti ziņojumu var arī neredzēt. Noraidīšana notiek pirms TLS rokasspiediena, un koda komentārs saka, ka šajā gadījumā nekas netiek uzrakstīts, tāpēc savienojums vienkārši pārtrūkst. Lietotne tad žurnālā raksta par savienojuma pārrāvumu vai rokasspiediena kļūdu, nevis Redis kļūdu.
- Arī replikas tiek skaitītas. Limita pārbaude izmanto pilnu klientu sarakstu, kurā ietilpst arī replikācijas savienojumi.
connected_clientskomandāINFOreplikas atskaita, tāpēc primārajā serverī ar replikām skaitļi precīzi nesakritīs. - Jūsu administratora sesijai nav rezervētas vietas. Ja visas vietas ir aizņemtas,
redis-clitiek noraidīts tāpat kā visi pārējie. Tāpēc pirmais labojums bieži jāveic klienta pusē.
Valkey ir tāda pati pārbaude un tāds pats ziņojums. Valkey 9.2, kas šī raksta tapšanas brīdī ir laidiena kandidāta stadijā, savā konfigurācijā pievieno maxclients-reserved un priority-subnets. Tie patur daļu limita savienojumiem no norādītajiem administrēšanas vai monitoringa tīkliem, lai operatori netiktu izslēgti. Pašā Redis līdzvērtīga iestatījuma nav.
Pirmā pārbaude: kāds ir reālais maxclients?
Noklusējums ir 10000. Redis klientu apstrādes dokumentācija paskaidro āķi: Redis vajag maxclients plus 32 failu deskriptorus (32 tiek rezervēti iekšējai lietošanai). Startējot tas pārbauda savu atvērto failu limitu un, ja tas ir par zemu, mēģina to paaugstināt pats. Kods failā server.c samazina vērtību soli pa solim, līdz OS to pieņem. Ja pietiekami daudz iegūt neizdodas, Redis samazina maxclients, lai tas ietilptu. Tas neatsakās startēt. Tas ieraksta brīdinājumu žurnālā un turpina ar mazāko limitu.
Tātad, ja procesa cietais (hard) limits ir 1024 atvērti faili, 10000 klusi kļūst par 992, lai gan konfigurāciju neviens nav mainījis. Pārbaudiet, kas ir darbojošamies procesam:
# darbojošā procesa reālais limits
grep 'open files' /proc/$(pidof redis-server)/limits
# ko Redis izlēma startējot
grep -i 'maxclients\|open files' /var/log/redis/redis-server.log
Meklējamie brīdinājumi ir "maxclients has been reduced to N to compensate for low ulimit" vai "Unable to obtain the current NOFILE limit", ja Redis limitu nevarēja nolasīt un pieņēma 1024. Ja Redis darbojas zem systemd, ulimit jūsu čaulā uz servisu neattiecas. Limits nāk no vienības iestatījuma LimitNOFILE=.
maxclients var mainīt darbības laikā ar CONFIG SET. Konfigurācijas kods vispirms vēlreiz pielāgo failu limitu, un, ja OS jauno vērtību nevar atbalstīt, komanda beidzas ar kļūdu "The operating system is not able to handle the specified number of clients, try with N". Tātad CONFIG SET klusi nepārsniegs OS limitu.
Otrā pārbaude: kas tur savienojumus
Sāciet ar skaitļiem. Ja nevarat pieslēgties, jo visas vietas ir aizņemtas, palaidiet šīs komandas no hosta, kura savienojums jau ir atvērts, izmantojiet monitoringa aģenta sesiju vai vispirms atbrīvojiet dažas vietas (skatīt tālāk).
redis-cli INFO clients
# connected_clients:9968
# cluster_connections:0
# maxclients:10000
# blocked_clients:12
redis-cli INFO stats | grep -E 'rejected_connections|total_connections_received'
Skaitītājs rejected_connections, kas turpina augt, apstiprina, ka limits tiek sasniegts tieši tagad. Tad sagrupējiet savienojumus. CLIENT LIST izdrukā vienu rindu katram savienojumam ar tādiem laukiem kā addr, name, age, idle, flags, cmd un, sākot ar Redis 7.2, lib-name un lib-ver:
# savienojumi pa klientu IP adresēm
redis-cli CLIENT LIST | grep -o 'addr=[^:]*' | sort | uniq -c | sort -rn | head
# savienojumi pa klienta nosaukumiem / bibliotēkām (ja klienti tos iestata)
redis-cli CLIENT LIST | grep -o 'name=[^ ]*' | sort | uniq -c | sort -rn | head
redis-cli CLIENT LIST | grep -o 'lib-name=[^ ]*' | sort | uniq -c | sort -rn | head
Modeļi, ko parasti atrodam:
- Viens hosts vai serviss ar tūkstošiem savienojumu. Savienojumu noplūde: klients, kas tiek izveidots katram pieprasījumam un nekad netiek aizvērts, pūls bez augšējās robežas vai ietvars, kas katrā darba procesā atver jaunu pūlu.
- Milzīgas
idlevērtības daudziem savienojumiem. Savienojumi, ko pameta klienti, kas avarēja vai tika nogalināti, tos neaizverot. Paša Redistimeoutnoklusējums ir 0, tāpēc šādi savienojumi paliek atvērti, līdz TCP keepalive pamana, ka otras puses vairs nav. Keepalive pēc noklusējuma ir ieslēgts ar 300 sekundēm, un konfigurācijas komentārs saka, ka Linux sistēmā miruša savienojuma aizvēršanai vajag apmēram divreiz vairāk laika. - Viss mērogojās vienlaikus. Automātiskā mērogošana dubultoja podu skaitu, un katrs pods atver fiksēta izmēra pūlu. Pūla izmērs × instanču skaits ir tas skaitlis, kas jāsalīdzina ar
maxclients. - Daudz
blpop/xreadvai abonentu. Bloķējošās komandas un Pub/Sub aizņem savienojumu visu gaidīšanas laiku. Katram šādam patērētājam vajag savu savienojumu, tāpēc tie ātri sakrājas.
Risinājumi, no tūlītējiem līdz pastāvīgiem
# atbrīvot vietas tagad: aizvērt konkrēta hosta savienojumu
redis-cli CLIENT KILL ADDR 10.20.0.15:53122
redis-cli CLIENT KILL TYPE normal MAXAGE 86400 # Redis 7.4+, pēc savienojuma vecuma
# automātiski aizvērt dīkstāvē esošus savienojumus (sekundes, 0 = nekad)
redis-cli CONFIG SET timeout 300
# paaugstināt griestus, ja OS limits to atļauj
redis-cli CONFIG SET maxclients 20000
Atbrīvojiet vietas tagad. CLIENT KILL var aizvērt savienojumus pēc ID, ADDR, LADDR, USER vai TYPE, un kopš Redis 7.4 arī pēc MAXAGE. Ņemiet vērā, ka MAXAGE aizver klientus, kas vecāki par norādīto sekunžu skaitu: tas ir savienojuma vecums, nevis dīkstāves laiks. Dīkstāves filtra nav, tāpēc, lai aizvērtu tikai dīkstāvē esošus savienojumus, paņemiet ID no CLIENT LIST un aizveriet tos. Noplūdinošā servisa restarts bieži atbrīvo vairāk vietu un ātrāk nekā jebkas, ko darāt serverī.
Iestatiet dīkstāves taimautu. timeout aizver parastus savienojumus, kas dīkstāvē ilgāk par norādīto sekunžu skaitu. Saskaņā ar timeout.c tas neattiecas uz replikām, saiti ar master, bloķētiem klientiem un Pub/Sub abonentiem, tāpēc to ieslēgt ir samērā droši. Dokumentācija brīdina, ka pārbaude notiek pakāpeniski, tāpēc savienojumi tiek aizvērti nedaudz vēlāk par precīzo vērtību. Iestatiet to garāku par jūsu pūlu pašu dīkstāves taimautu, lai savienojumu vispirms aizvērtu pūls un tas neuzdurtos mirušam soketam.
Paaugstiniet limitu, ja slodze ir reāla. Ja savienojumu skaits ir pamatots, vispirms paaugstiniet OS failu limitu (LimitNOFILE= vai ulimit -n), tad maxclients konfigurācijas failā un ar CONFIG SET. Katrs savienojums izmanto arī atmiņu saviem buferiem. Pirms klientu skaita reizināšanas pārbaudiet tot-mem komandā CLIENT LIST un ieskatieties mūsu Redis OOM un maxmemory ceļvedī.
maxclients tikai nopērk laiku, un nākamais incidents nāk ar lielāku atmiņas patēriņu un vairāk atvērtu failu deskriptoru. Labojiet klientu: viens kopīgs pūls katram procesam, stingra pūla izmēra augšējā robeža un savienojumu atgriešana pēc lietošanas.Novērsiet nākamo reizi
- Iestatiet brīdinājumu par attiecību
connected_clients / maxclients, piemēram, pie 80%. Brīdiniet arī par jebkururejected_connectionspieaugumu. Abas vērtības irINFO, un tās labi papildina pārējās mūsu datubāzu metrikām, kas paredz incidentus. - Lieciet klientiem sevi identificēt.
CLIENT SETNAMEar servisa nosaukumu pārvērš IP adrešu sienu par atbildi dažās sekundēs. Daudzas bibliotēkas sūta arīlib-name. - Plānojiet savienojumu budžetu uz papīra: pūla izmērs × procesi × instances pie maksimālā mēroga, plus replikas, klastera kopne un monitorings, jāpaliek krietni zem
maxclients. - Pārbaudiet efektīvo limitu pēc katras izvietošanas vai OS izmaiņām.
CONFIG GET maxclientsdarbojošamies serverim, nevis skaitli konfigurācijas failā.
Galvenās atziņas
- "ERR max number of clients reached" nozīmē, ka atvērtie savienojumi sasniedza
maxclients. Esošie savienojumi turpina darboties. - Noklusējums ir 10000, bet Redis startējot to samazina, lai ietilptu failu deskriptoru limitā mīnus 32. Pārbaudiet žurnālu un
CONFIG GET maxclients. - Klastera kopnes savienojumi un replikas tiek ieskaitīti limitā. TLS klienti var redzēt tikai pārtrauktu savienojumu.
- Vainīgo atrodiet ar
CLIENT LIST, grupējot pēcaddr,nameunlib-name, un skatieties uzidle. - Tūlītējam atvieglojumam izmantojiet
timeoutunCLIENT KILL, pastāvīgi labojiet klienta pūlu, un limitus paaugstiniet tikai reālai slodzei.