Redis займає всю пам'ять і збої


12

Сервер Redis v2.8.4 працює на Ubuntu 14.04 VPS з 8 ГБ оперативної пам’яті та 16 ГБ місцями для обміну (на SSD). Однак htopпоказує, що redisпоодинці займає 22.4 Gпам'ять!

redis-serverврешті-решт зазнав аварій через пам'ять. Memі Swpобидва удари на 100% потім redis-serverвбиваються разом з іншими службами.

Від 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

Перезапуск redis-serverз іншого аварії OOM або service redis-server force-reloadспричиняє використання пам'яті до <100 МБ.

Питання: Чому вона redis-serverзаймає все більше пам’яті, поки не вийде з ладу? Як ми можемо запобігти цьому?

Це правда, що налаштування maxmemoryне працюватиме, оскільки, як тільки Redis досягне maxmemoryмежі, воно почне видаляти дані?

введіть тут опис зображення введіть тут опис зображення

Після перезапуску redis-сервера

введіть тут опис зображення введіть тут опис зображення

Версія Redis: Redis server v=2.8.4 sha=00000000:0 malloc=jemalloc-3.4.1 bits=64 build=a44a05d76f06a5d9


Оновлення

Коли htopповідомлення про використання пам'яті redis-serverстановить 4,4G оперативної пам’яті та 22,6G Swap, обсяг місця, зайнятий всіма клавішами в Redis, є лише 60.59636307 MB, як повідомляє rdbtools . Це також об'єм оперативної пам’яті, зайнятий redis-serverправильно після її перезавантаження.

INFO ALLколи redis-serverзаймає тонни пам'яті

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

Відповіді:


8
  1. Використовуйте, maxmemoryщоб встановити обмеження на кількість вашої бази даних Redis. Якщо цього не зробити, Redis буде рости до тих пір, поки ОС не вб'є її, коли пам'ять буде вичерпана (відповідно до вашого поточного досвіду).
  2. Використання maxmemoryмає бути поєднане maxmemory-policy- ви можете обирати різні політики щодо виселення залежно від вимог Вашого випадку використання. Наприклад, якщо ви використовуєте allkeys-lruполітику виселення, Redis дійсно почне виселяти (найменше використовувані останні) дані, коли maxmemoryвже буде досягнуто. Крім того, ви можете доручити Redis вилучати лише дані, які можуть працювати з терміном дії, volatile-lruабо з volatile-randomполісами. Нарешті, ви можете встановити політику на, noevictionале це означатиме, що як тільки пам'ять вичерпана, Redis буде відмовляти в подальших записах із повідомленням OOM.

Редагувати:

Спочатку вимкніть заміну - Redis і swap не змішуються легко, і це, безумовно, може спричинити повільність.

Також free -mзамість верху зробіть повну картину стану вашої оперативної пам’яті ( http://www.linuxatemyram.com/ ).


Дякую, я розгублений, чому використання пам’яті постійно зростає, але, якщо робити bgsaveі перезапускати, redis-serverспоживання пам’яті знижується до більш розумного значення 70 Мб. Це може бути витік пам'яті?
Nyxynyx

Можливо, але малоймовірно (або інші люди повідомили б про це) ... Швидше за все, проблема роздробленості. Наступного разу, коли це станеться, опублікуйте висновок Redis ' INFO ALL. Якщо я здогадуюсь правильний, mem_fragmentation_ratioволя зависла до неба.
Ітамар Хабер

redis-serverпіднімає всю пам'ять і вибивається щодня. Зараз збирається використати всю пам'ять, тому я захопив результат INFO ALLі додав до ОП. mem_fragmentation_ratio:0.19
Nyxynyx

Якщо набори даних Redis не перевищують 250 Мб і maxmemoryвстановлені в 1 Гб, чи означає це, що коли використання пам'яті Redis досягає 1 ГБ, виселення все одно видалить дані? Так як Redis - х mem_fragmentation_ratioє 0.19, це означає , що Theres занадто багато фрагментації, або занадто багато зберігається в обміні, або як? Будь-який спосіб зменшити фрагментацію?
Nyxynyx

Коли сервер redis збирається вийти з ладу через OOM, rdbtools показує, що ключі в redis займають лише 60 Мб. Це виглядає як надзвичайно серйозна фрагментація? Враховуючи, що вона займає 4,4 ГБ оперативної пам’яті та 22,4 Г Swap.
Nyxynyx

5

Це майже напевно фрагментація пам’яті, оскільки Redis добре відомий і любить у виробництві, і ви, мабуть, не знайшли витоку пам’яті.

Рекомендації щодо встановлення розміру пулу не допоможуть фрагментації. Вам доведеться спеціально зменшити розмір Redis - менший, ніж фактичний розмір пам'яті, - оскільки Redis не може пояснити фрагментацію - але, з точки зору короткої відповіді, вам доведеться це зробити і почати планувати перезапуск свого сервери часто.

Моє правило роботи з різними операційними системами та базами даних в пам'яті - вам потрібна 2х фактична пам'ять, і розмір пам’яті стабілізується приблизно через 2 тижні.

Однак це залежить від вашої фактичної структури розподілу та розподільника пам'яті, яку ви використовуєте.

Наразі найкращий розподільник пам'яті, який я знайшов для серверів, - це JEMalloc. Зараз ми використовуємо його в Aerospike для зменшення (майже видалення) довготривалої фрагментації пам'яті. У JEMalloc є функція, яка дозволяє створювати пам'ять «арена» (пул), і при будь-якому розподілі вибирайте, який пул, таким чином, надаючи розміри однакового розміру та керуйте аналогічними ресурсами пам'яті. Для нас це була велика перемога в таких випадках, які ви обговорюєте.

Двигун Zend PHP в цьому плані є складним, оскільки всі розподіли всередині двигуна знаходяться або в операційній пам'яті, або в глобальній пам'яті. Пам'ять на транзакцію звільняється одним махом в кінці транзакції, і, таким чином, може бути дуже ефективною.

Якщо ви перебуваєте в Linux, розподільник пам’яті ядра (Clib) здійснив ряд поворотів, і в якій версії ви будете різко визначати об'єм фрагментації, як і фактичний шаблон програми. Наприклад, деякі розподільники набагато краще, коли ви злегка зростаєте об'єктами, деякі - набагато гірше. На жаль, навіть обговорювати з іншими користувачами Redis означає говорити про те, яку ОС та яку ОС ОС ви використовуєте.

Те, що ви можете перезапустити сервер (з постійності) та повернути свою пам'ять, може означати витік, але, швидше за все, вказує на фрагментацію.

  1. Вимкнути заміну (краще OOM, ніж поміняти, для redis)
  2. Зменшити розмір пам'яті Redis
  3. Перезавантажте за графіком

Як би ви зменшили розмір пам'яті, скоригувавшись maxmemory?
Nyxynyx
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.