Redis mengambil semua Memori dan Gangguan

12

Redis server v2.8.4 berjalan pada Ubuntu 14.04 VPS dengan 8 GB RAM dan 16 GB ruang swap (pada SSD). Namun htopmenunjukkan bahwa itu redissaja yang menghabiskan 22.4 Gmemori!

redis-serverakhirnya jatuh karena kehabisan memeory. Memdan Swpkeduanya hit 100% kemudian redis-serverterbunuh bersama dengan layanan lain.

Dari 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

Memulai kembali redis-serverdari kecelakaan OOM atau service redis-server force-reloadmenyebabkan penggunaan memori turun menjadi <100MB.

Pertanyaan: Mengapa redis-servermemori lebih banyak dan lebih banyak sampai crash? Bagaimana kita bisa mencegah ini?

Apakah benar pengaturan maxmemorytidak akan berfungsi karena setelah redis mencapai maxmemorybatas, itu akan mulai menghapus data?

masukkan deskripsi gambar di sini masukkan deskripsi gambar di sini

Setelah memulai ulang redis-server

masukkan deskripsi gambar di sini masukkan deskripsi gambar di sini

Versi redis: Redis server v=2.8.4 sha=00000000:0 malloc=jemalloc-3.4.1 bits=64 build=a44a05d76f06a5d9


Memperbarui

Ketika htopmelaporkan penggunaan memori redis-servermenjadi 4.4G RAM dan 22.6G Swap, jumlah ruang yang diambil oleh semua tombol dalam redis hanya 60.59636307 MB, seperti yang dilaporkan oleh rdbtools . Ini juga jumlah RAM yang diambil redis-servertepat setelah restart.

INFO ALLsaat redis-servermengambil banyak memori

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
Nyxynyx
sumber

Jawaban:

8
  1. Gunakan maxmemoryuntuk menetapkan batas seberapa banyak basis data Redis Anda juga bisa tumbuh. Gagal melakukannya, Redis akan tumbuh hingga OS akan membunuhnya setelah memori habis (sesuai pengalaman Anda saat ini).
  2. Penggunaan maxmemoryharus digabungkan dengan maxmemory-policy- Anda dapat memilih dari berbagai kebijakan penggusuran tergantung pada persyaratan use case Anda. Misalnya, jika Anda menggunakan allkeys-lrukebijakan penggusuran, Redis memang akan mulai mengusir (yang paling baru digunakan) data setelah maxmemorytercapai. Atau, Anda dapat menginstruksikan Redis untuk mengusir hanya data yang berakhir-mampu dengan volatile-lruatau volatile-randomkebijakan. Terakhir, Anda dapat mengatur kebijakan untuk noevictiontetapi itu berarti bahwa setelah memori telah habis, Redis akan menolak menulis lebih lanjut dengan pesan OOM.

Edit:

Nonaktifkan swap pertama - Redis dan swap tidak mudah bergaul dan ini pasti dapat menyebabkan kelambatan.

Lakukan juga free -malih - alih mendapatkan gambar lengkap dari kondisi RAM Anda ( http://www.linuxatemyram.com/ ).

Itamar Haber
sumber
Terima kasih, saya bingung mengapa penggunaan memori terus meningkat, namun melakukan bgsavedan memulai kembali redis-servermenyebabkan penggunaan memori turun ke nilai yang lebih masuk akal yaitu 70 MB. Mungkinkah ini kebocoran memori?
Nyxynyx
Kemungkinan tetapi tidak mungkin (atau orang lain akan melaporkannya) ... Kemungkinan besar masalah fragmentasi. Lain kali itu terjadi, posting output Redis Anda INFO ALL. Jika tebakan saya benar, mem_fragmentation_ratiokemauan akan setinggi langit.
Itamar Haber
redis-serverbabi semua memori dan crash setiap hari. Ini akan menggunakan semua memori sekarang, jadi saya sudah menangkap output INFO ALLdan ditambahkan ke OP. mem_fragmentation_ratio:0.19
Nyxynyx
Jika dataset redis tidak melebihi 250MB dan maxmemorydiatur ke 1 GB, apakah ini berarti bahwa ketika penggunaan redis mencapai 1GB, penggusuran masih akan menghapus data? Karena redis mem_fragmentation_ratioadalah 0.19, apakah itu berarti ada terlalu banyak fragmentasi, atau terlalu banyak disimpan dalam swap, atau keduanya? Adakah cara untuk mengurangi fragmentasi?
Nyxynyx
Ketika redis-server akan macet karena OOM, rdbtools menunjukkan bahwa kunci dalam redis hanya membutuhkan 60MB. Ini terlihat seperti fragmentasi yang sangat serius? Mengingat itu mengambil 4.4GB RAM dan 22.4G Swap.
Nyxynyx
5

Ini hampir pasti fragmentasi memori, karena redis terkenal dan dicintai dalam produksi dan Anda mungkin belum menemukan kebocoran memori.

Rekomendasi tentang pengaturan ukuran kolam tidak akan membantu fragmentasi. Anda harus secara khusus menurunkan ukuran Redis - lebih rendah dari ukuran memori Anda yang sebenarnya - karena Redis tidak dapat menjelaskan fragmentasi - tetapi, dalam hal jawaban singkat, Anda harus melakukan itu, dan mulai merencanakan memulai kembali Anda server sering.

Aturan praktis saya yang bekerja dengan berbagai sistem operasi dan database dalam memori adalah Anda membutuhkan 2x memori Anda yang sebenarnya, dan ukuran memori akan stabil dalam sekitar 2 minggu.

Namun, itu tergantung pada pola alokasi aktual Anda, dan pengalokasi memori yang Anda gunakan.

Saat ini, pengalokasi memori terbaik yang saya temukan untuk server adalah JEMalloc. Kami menggunakannya di Aerospike sekarang untuk mengurangi (hampir menghilangkan) fragmentasi memori jangka panjang. JEMalloc memiliki fitur yang memungkinkan Anda untuk membuat "arena" memori (kumpulan), dan pada alokasi apa pun, pilih kumpulan mana, sehingga memberi Anda alokasi ukuran-suka dan untuk mengelola alokasi memori seumur hidup yang serupa. Ini merupakan kemenangan besar bagi kami dalam kasus-kasus yang Anda diskusikan.

Mesin Zend PHP canggih dalam hal ini, karena semua alokasi di dalam mesin baik dalam memori per transaksi, atau memori global. Memori per transaksi dibebaskan pada satu tegukan di akhir transaksi, dan dengan demikian bisa sangat efisien.

Jika Anda menggunakan Linux, pengalokasi memori kernel (Clib) telah melakukan beberapa putaran, dan versi yang Anda gunakan akan secara dramatis menentukan jumlah fragmentasi, seperti pola aplikasi yang sebenarnya. Sebagai contoh, beberapa pengalokasi jauh lebih baik ketika Anda objek yang sedikit tumbuh, beberapa jauh lebih buruk. Sayangnya, bahkan berdiskusi dengan pengguna Redis lain berarti membicarakan OS mana, dan versi OS mana yang Anda gunakan.

Fakta bahwa Anda dapat me-restart server (dari kegigihan) dan mendapatkan kembali memori Anda bisa berarti kebocoran, tetapi lebih cenderung mengarah ke fragmentasi.

  1. Disallow swap (lebih baik ke OOM daripada swap, untuk redis)
  2. Kurangi ukuran memori redis
  3. Mulai kembali sesuai jadwal
Brian Bulkowski
sumber
Bagaimana Anda mengurangi ukuran memori, dengan menyesuaikan maxmemory?
Nyxynyx