Serwer Redis v2.8.4 działa na Ubuntu 14.04 VPS z 8 GB pamięci RAM i 16 GB przestrzeni wymiany (na dyskach SSD). htop
Pokazuje jednak , że redis
sam zajmuje 22.4 G
pamięć!
redis-server
ostatecznie rozbił się z powodu braku pamięci. Mem
i Swp
oba trafiają w 100%, następnie redis-server
zostają zabite wraz z innymi usługami.
Od dmesg
:
[165578.047682] Out of memory: Kill process 10155 (redis-server) score 834 or sacrifice child
[165578.047896] Killed process 10155 (redis-server) total-vm:31038376kB, anon-rss:5636092kB, file-rss:0kB
Ponowne uruchomienie redis-server
od czasu awarii OOM lub service redis-server force-reload
powoduje zmniejszenie zużycia pamięci do <100 MB.
Pytanie: Dlaczego redis-server
zajmuje coraz więcej pamięci, dopóki się nie zawiesi? Jak możemy temu zapobiec?
Czy to prawda, że ustawienie maxmemory
nie zadziała, ponieważ gdy redis osiągnie maxmemory
limit, rozpocznie usuwanie danych?
Po zrestartowaniu serwera redis
Wersja Redis: Redis server v=2.8.4 sha=00000000:0 malloc=jemalloc-3.4.1 bits=64 build=a44a05d76f06a5d9
Aktualizacja
Gdy htop
zgłasza, że użycie pamięci redis-server
wynosi 4.4G RAM i 22.6G Swap, ilość miejsca zajmowana przez wszystkie klawisze w redis jest tylko 60.59636307 MB
, jak podają rdbtools . Jest to również ilość pamięci RAM zajętej redis-server
zaraz po ponownym uruchomieniu.
INFO ALL
kiedy redis-server
zajmuje mnóstwo pamięci
mem_fragmentation_ratio:0.19
127.0.0.1:6379> INFO all
# Server
redis_version:2.8.4
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:a44a05d76f06a5d9
redis_mode:standalone
os:Linux 3.13.0-24-generic x86_64
arch_bits:64
multiplexing_api:epoll
gcc_version:4.8.2
process_id:26858
run_id:4d4a507b325e567d5ada203a0c65891bcf4d02de
tcp_port:6379
uptime_in_seconds:100011
uptime_in_days:1
hz:10
lru_clock:165668
config_file:/etc/redis/redis.conf
# Clients
connected_clients:60
client_longest_output_list:768774
client_biggest_input_buf:0
blocked_clients:0
# Memory
used_memory:23973468008
used_memory_human:22.33G
used_memory_rss:4563857408
used_memory_peak:24083474760
used_memory_peak_human:22.43G
used_memory_lua:33792
mem_fragmentation_ratio:0.19
mem_allocator:jemalloc-3.4.1
# Persistence
loading:0
rdb_changes_since_last_save:127835154
rdb_bgsave_in_progress:0
rdb_last_save_time:1406716479
rdb_last_bgsave_status:err
rdb_last_bgsave_time_sec:1
rdb_current_bgsave_time_sec:-1
aof_enabled:0
aof_rewrite_in_progress:0
aof_rewrite_scheduled:0
aof_last_rewrite_time_sec:-1
aof_current_rewrite_time_sec:-1
aof_last_bgrewrite_status:ok
# Stats
total_connections_received:110
total_commands_processed:386765263
instantaneous_ops_per_sec:3002
rejected_connections:0
sync_full:0
sync_partial_ok:0
sync_partial_err:0
expired_keys:0
evicted_keys:0
keyspace_hits:1385878
keyspace_misses:23655
pubsub_channels:0
pubsub_patterns:0
latest_fork_usec:82
# Replication
role:master
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
# CPU
used_cpu_sys:10547.48
used_cpu_user:8240.36
used_cpu_sys_children:201.83
used_cpu_user_children:914.86
# Commandstats
cmdstat_del:calls=136,usec=1407,usec_per_call=10.35
cmdstat_exists:calls=161428,usec=1391252,usec_per_call=8.62
cmdstat_zadd:calls=64149642,usec=936323882,usec_per_call=14.60
cmdstat_zrem:calls=137,usec=2131,usec_per_call=15.55
cmdstat_zremrangebyscore:calls=2293,usec=111905082,usec_per_call=48802.91
cmdstat_zrange:calls=7925,usec=285907448,usec_per_call=36076.65
cmdstat_zrangebyscore:calls=921434,usec=292731002,usec_per_call=317.69
cmdstat_zcount:calls=8,usec=172,usec_per_call=21.50
cmdstat_zrevrange:calls=191184,usec=965447,usec_per_call=5.05
cmdstat_zcard:calls=5180,usec=13502,usec_per_call=2.61
cmdstat_zscore:calls=29856,usec=576044,usec_per_call=19.29
cmdstat_hset:calls=64145124,usec=199407095,usec_per_call=3.11
cmdstat_hget:calls=248487,usec=501220,usec_per_call=2.02
cmdstat_hincrby:calls=128339355,usec=2071112929,usec_per_call=16.14
cmdstat_hgetall:calls=193747,usec=1608260,usec_per_call=8.30
cmdstat_select:calls=1,usec=5,usec_per_call=5.00
cmdstat_rename:calls=134,usec=1090,usec_per_call=8.13
cmdstat_keys:calls=4503,usec=4997628,usec_per_call=1109.84
cmdstat_bgsave:calls=2,usec=20012,usec_per_call=10006.00
cmdstat_type:calls=603,usec=2736,usec_per_call=4.54
cmdstat_multi:calls=64181979,usec=383633610,usec_per_call=5.98
cmdstat_exec:calls=64181979,usec=4403181204,usec_per_call=68.60
cmdstat_info:calls=126,usec=28675,usec_per_call=227.58
# Keyspace
db0:keys=2109,expires=0,avg_ttl=0
bgsave
i ponowne uruchomienieredis-server
powoduje, że zużycie pamięci spada do bardziej rozsądnej wartości 70 MB. Czy to może być wyciek pamięci?INFO ALL
. Jeśli moje przypuszczenie jest słuszne,mem_fragmentation_ratio
wola niebios.redis-server
pochłania całą pamięć i codziennie ulega awarii. Zaraz zużyje całą pamięć, więc przechwyciłem dane wyjścioweINFO ALL
i dodałem do OP.mem_fragmentation_ratio:0.19
maxmemory
są ustawione na 1 GB, czy to oznacza, że gdy użycie pamięci redis osiągnie 1 GB, eksmisja nadal usunie dane? Skoro Redismem_fragmentation_ratio
jest0.19
, to czy oznacza to, że jest tam zbyt duża fragmentacja, czy zbyt dużo jest przechowywanych w swapie, czy w obu przypadkach? Jakiś sposób na zmniejszenie fragmentacji?Jest to prawie na pewno fragmentacja pamięci, ponieważ redis jest dobrze znany i lubiany w produkcji i prawdopodobnie nie znaleziono wycieku pamięci.
Zalecenia dotyczące ustawiania wielkości puli nie pomogą w fragmentacji. Będziesz musiał specjalnie zmniejszyć rozmiar Redis - mniejszy niż faktyczny rozmiar pamięci - ponieważ Redis nie może uwzględnić fragmentacji - ale, biorąc pod uwagę krótką odpowiedź, musisz to zrobić i zacząć planować ponowne uruchomienie serwery często.
Moją ogólną zasadą przy pracy z różnymi systemami operacyjnymi i bazami danych w pamięci jest to, że potrzebujesz 2x rzeczywistej pamięci, a rozmiar pamięci ustabilizuje się za około 2 tygodnie.
Zależy to jednak od faktycznych wzorców alokacji i używanego alokatora pamięci.
W tej chwili najlepszym przydziałem pamięci dla serwerów jest JEMalloc. Używamy go teraz w Aerospike, aby zmniejszyć (prawie usunąć) fragmentację pamięci długoterminowej. JEMalloc ma funkcję, która pozwala na tworzenie „areny” pamięci (puli) i przy dowolnej alokacji, wybierz pulę, zapewniając w ten sposób przydziały o podobnej wielkości i zarządzając podobnymi alokacjami czasu życia pamięci. To była dla nas duża wygrana w omawianych przypadkach.
Silnik Zend PHP jest pod tym względem wyrafinowany, ponieważ wszystkie alokacje wewnątrz silnika są albo w pamięci na transakcję, albo w pamięci globalnej. Pamięć na jedną transakcję jest zwalniana za jednym zamachem pod koniec transakcji, a zatem może być bardzo wydajna.
Jeśli korzystasz z Linuksa, narzędzie do alokacji pamięci jądra (Clib) wykonało wiele zwrotów akcji, a wersja, na której jesteś, będzie drastycznie określać stopień fragmentacji, podobnie jak rzeczywisty wzorzec aplikacji. Na przykład niektóre alokatory są znacznie lepsze, gdy nieznacznie rosną obiekty, inne są znacznie gorsze. Niestety, nawet rozmowa z innymi użytkownikami Redis oznacza rozmowę o tym, jakiego systemu operacyjnego i jakiej wersji systemu operacyjnego używasz.
Fakt, że możesz zrestartować serwer (z trwałości) i odzyskać pamięć, może oznaczać wyciek, ale bardziej prawdopodobne wskazuje na fragmentację.
źródło
maxmemory
?