Um servidor redis v2.8.4 está sendo executado em um Ubuntu 14.04 VPS com 8 GB de RAM e 16 GB de espaço de troca (em SSDs). No entanto, htop
mostra que redis
sozinho está ocupando 22.4 G
memória!
redis-server
eventualmente travou devido a falta de memória. Mem
e os Swp
dois hits 100% redis-server
são mortos juntamente com outros serviços.
De 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
Reiniciar a redis-server
partir de uma falha no OOM ou service redis-server force-reload
faz com que o uso da memória caia para <100MB.
Pergunta: Por que redis-server
ocupa mais e mais memória até travar? Como podemos evitar isso?
É verdade que a configuração maxmemory
não funcionará porque, quando o redis atingir o maxmemory
limite, ele começará a remover os dados?
Depois de reiniciar o redis-server
Versão Redis: Redis server v=2.8.4 sha=00000000:0 malloc=jemalloc-3.4.1 bits=64 build=a44a05d76f06a5d9
Atualizar
Quando htop
relata que o uso da memória redis-server
é de 4.4G RAM e 22.6G Swap, a quantidade de espaço ocupada por todas as chaves em redis é apenas 60.59636307 MB
, conforme relatado pelo rdbtools . Essa também é a quantidade de RAM consumida redis-server
logo após a reinicialização.
INFO ALL
quando redis-server
está ocupando toneladas de memória
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
e reiniciarredis-server
faz com que o uso da memória caia para um valor mais razoável de 70 MB. Isso poderia ser um vazamento de memória?INFO ALL
. Se meu palpite estiver correto, amem_fragmentation_ratio
vontade estará no céu.redis-server
monopoliza toda a memória e trava todos os dias. Está prestes a usar toda a memória agora, então eu capturei a saídaINFO ALL
e a adicionei ao OP.mem_fragmentation_ratio:0.19
maxmemory
estiver definido como 1 GB, isso significa que quando o uso de mem do redis atingir 1 GB, a remoção ainda removerá os dados? Como o redismem_fragmentation_ratio
é0.19
, isso significa que há muita fragmentação ou muito armazenamento em swap, ou ambos? Alguma maneira de reduzir a fragmentação?É quase certamente uma fragmentação da memória, pois o redis é bem conhecido e amado na produção e você provavelmente não encontrou um vazamento de memória.
As recomendações sobre como definir o tamanho do pool não ajudarão na fragmentação. Você precisará diminuir especificamente o tamanho do Redis - menor que o tamanho real da memória - porque os Redis não podem explicar a fragmentação - mas, em termos de uma resposta curta, você precisará fazer isso e iniciar o plano de reiniciar o seu servidores com freqüência.
Minha regra prática ao trabalhar com uma variedade de sistemas operacionais e bancos de dados na memória é que você precisa de 2x a sua memória real e o tamanho da memória estabilizará em cerca de duas semanas.
No entanto, isso depende dos seus padrões de alocação reais e do alocador de memória que você está usando.
No momento, o melhor alocador de memória que encontrei para servidores é o JEMalloc. Agora o usamos no Aerospike para reduzir (quase remover) a fragmentação de memória de longo prazo. O JEMalloc possui um recurso que permite criar uma "arena" de memória (pool) e, em qualquer alocação, escolher qual pool, fornecendo alocações de tamanho semelhante e gerenciar alocações de duração da memória semelhantes. Tem sido uma grande vitória para nós no tipo de casos que você está discutindo.
O mecanismo Zend PHP é sofisticado nesse aspecto, porque todas as alocações dentro do mecanismo estão na memória por transação ou na memória global. A memória por transação é liberada de uma só vez no final da transação e, portanto, pode ser muito eficiente.
Se você estiver no Linux, o alocador de memória do kernel (Clib) sofreu várias reviravoltas, e em qual versão você está determinará dramaticamente a quantidade de fragmentação, assim como o padrão real do aplicativo. Por exemplo, alguns alocadores são muito melhores quando você cresce objetos levemente, outros são muito piores. Lamentavelmente, até discutir com outros usuários Redis significa falar sobre qual SO e qual versão do SO você está usando.
O fato de você poder reiniciar o servidor (por persistência) e recuperar a memória pode significar um vazamento, mas é mais provável que aponte para fragmentação.
fonte
maxmemory
?