Se está ejecutando un servidor redis v2.8.4 en un Ubuntu 14.04 VPS con 8 GB de RAM y 16 GB de espacio de intercambio (en SSD). Sin embargo, htop
muestra que redis
solo está ocupando 22.4 G
memoria!
redis-server
finalmente se estrelló por falta de memoria. Mem
y Swp
ambos alcanzan el 100% y luego redis-server
se mata junto con otros servicios.
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 redis-server
desde etiher un bloqueo de OOM o service redis-server force-reload
causa que el uso de memoria caiga a <100 MB.
Pregunta: ¿Por qué redis-server
ocupa más y más memoria hasta que se bloquea? como podemos prevenir esto?
¿Es cierto que la configuración maxmemory
no funcionará porque una vez que redis alcance el maxmemory
límite, comenzará a eliminar datos?
Después de reiniciar redis-server
Versión Redis: Redis server v=2.8.4 sha=00000000:0 malloc=jemalloc-3.4.1 bits=64 build=a44a05d76f06a5d9
Actualizar
Cuando se htop
informa que el uso de memoria redis-server
debe ser 4.4G RAM y 22.6G Swap, la cantidad de espacio ocupado por todas las teclas en redis es solo 60.59636307 MB
, según lo informado por rdbtools . Esta es también la cantidad de RAM que ocupa redis-server
inmediatamente después de reiniciarse.
INFO ALL
cuando redis-server
está tomando toneladas de memoria
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
y reiniciarredis-server
hace que el uso de la memoria caiga a un valor más razonable de 70 MB. ¿Podría ser esto una pérdida de memoria?INFO ALL
. Si mi suposición es correcta, lamem_fragmentation_ratio
voluntad se disparará.redis-server
acumula toda la memoria y se cuelga todos los días. Está a punto de usar toda la memoria ahora, así que capturé la salidaINFO ALL
y la agregué al OP.mem_fragmentation_ratio:0.19
maxmemory
se configuran en 1 GB, ¿significa esto que cuando el uso de memoria de redis llegue a 1 GB, el desalojo aún eliminará los datos? Dado que redismem_fragmentation_ratio
es0.19
, ¿significa que hay demasiada fragmentación, o demasiado almacenado en el intercambio, o ambos? ¿Alguna forma de reducir la fragmentación?Es casi seguro que es fragmentación de la memoria, ya que redis es bien conocido y amado en la producción y probablemente no haya encontrado una pérdida de memoria.
Las recomendaciones sobre cómo establecer el tamaño del grupo no ayudarán a la fragmentación. Tendrá que reducir específicamente el tamaño de Redis, más bajo que el tamaño real de su memoria, porque Redis no puede explicar la fragmentación, pero, en términos de una respuesta breve, tendrá que hacerlo y comenzar a planear reiniciar su servidores con frecuencia.
Mi regla general para trabajar con una variedad de sistemas operativos y bases de datos en memoria es que necesita 2 veces su memoria real, y el tamaño de la memoria se estabilizará en aproximadamente 2 semanas.
Sin embargo, eso depende de sus patrones de asignación reales y del asignador de memoria que esté utilizando.
En este momento, el mejor asignador de memoria que he encontrado para servidores es JEMalloc. Lo usamos en Aerospike ahora para reducir (casi eliminar) la fragmentación de la memoria a largo plazo. JEMalloc tiene una función que le permite crear una "arena" (grupo) de memoria y, en cualquier asignación, elegir qué grupo, lo que le brinda asignaciones de tamaño similar y administrar asignaciones de vida útil de memoria similares. Ha sido una gran victoria para nosotros en el tipo de casos que está discutiendo.
El motor PHP de Zend es sofisticado a este respecto, porque todas las asignaciones dentro del motor están en la memoria por transacción o en la memoria global. La memoria por transacción se libera de una sola vez al final de la transacción y, por lo tanto, puede ser muy eficiente.
Si está en Linux, el asignador de memoria del núcleo (Clib) ha dado varios giros y vueltas, y la versión en la que se encuentre determinará drásticamente la cantidad de fragmentación, al igual que el patrón de aplicación real. Por ejemplo, algunos asignadores son mucho mejores cuando crecen objetos ligeramente, algunos son mucho peores. Lamentablemente, incluso discutir con otros usuarios de Redis significa hablar sobre qué sistema operativo y qué versión de sistema operativo está utilizando.
El hecho de que pueda reiniciar el servidor (desde la persistencia) y recuperar su memoria podría significar una fuga, pero lo más probable es que se trate de fragmentación.
fuente
maxmemory
?