Redis chiếm tất cả Bộ nhớ và Tai nạn


12

Một máy chủ redis v2.8.4 đang chạy trên VPS Ubuntu 14.04 với RAM 8 GB và dung lượng trao đổi 16 GB (trên SSD). Tuy nhiên htopcho thấy rằng redismột mình đang chiếm 22.4 Gbộ nhớ!

redis-servercuối cùng bị sụp đổ do ra khỏi memeory. MemSwpcả hai lượt truy cập 100% sau đó redis-serverbị giết cùng với các dịch vụ khác.

Từ 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

Khởi động lại redis-servertừ khắc phục sự cố OOM hoặc service redis-server force-reloadkhiến việc sử dụng bộ nhớ giảm xuống <100MB.

Câu hỏi: Tại sao redis-serverchiếm càng nhiều bộ nhớ cho đến khi nó gặp sự cố? Làm thế nào chúng ta có thể ngăn chặn điều này?

Có đúng là cài đặt maxmemorysẽ không hoạt động vì một khi redis đạt đến maxmemorygiới hạn, nó sẽ bắt đầu xóa dữ liệu?

nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây

Sau khi khởi động lại máy chủ redis

nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây

Phiên bản Redis: Redis server v=2.8.4 sha=00000000:0 malloc=jemalloc-3.4.1 bits=64 build=a44a05d76f06a5d9


Cập nhật

Khi htopbáo cáo mức sử dụng bộ nhớ redis-serverlà 4,4G RAM và 22,6G Hoán đổi, lượng không gian được chiếm bởi tất cả các phím trong redis chỉ 60.59636307 MB, như báo cáo của rdbtools . Đây cũng là dung lượng RAM được sử dụng redis-serverngay sau khi khởi động lại.

INFO ALLkhi redis-serverchiếm hàng tấn bộ nhớ

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

Câu trả lời:


8
  1. Sử dụng maxmemoryđể đặt giới hạn cho số lượng cơ sở dữ liệu Redis của bạn cũng có thể tăng lên. Không làm như vậy, Redis sẽ phát triển cho đến khi HĐH sẽ giết nó sau khi bộ nhớ cạn kiệt (theo kinh nghiệm hiện tại của bạn).
  2. Việc sử dụng maxmemorynên được kết hợp với maxmemory-policy- bạn có thể chọn từ các chính sách trục xuất khác nhau tùy thuộc vào yêu cầu của trường hợp sử dụng của bạn. Ví dụ: nếu bạn sử dụng allkeys-lruchính sách trục xuất, Redis thực sự sẽ bắt đầu đuổi dữ liệu (ít được sử dụng gần đây nhất) một khi maxmemoryđã đạt được. Ngoài ra, bạn có thể hướng dẫn Redis chỉ đuổi dữ liệu có thể hết hạn bằng các chính sách volatile-lruhoặc volatile-random. Cuối cùng, bạn có thể đặt chính sách thành noevictionnhưng điều đó có nghĩa là một khi bộ nhớ đã hết, Redis sẽ từ chối viết thêm bằng tin nhắn OOM.

Biên tập:

Đầu tiên vô hiệu hóa trao đổi - Redis và trao đổi không trộn dễ dàng và điều này chắc chắn có thể gây chậm.

Ngoài ra, free -mthay vì trên cùng để có hình ảnh đầy đủ về trạng thái RAM của bạn ( http://www.linuxatemyram.com/ ).


Cảm ơn bạn, tôi bối rối vì lý do tại sao việc sử dụng bộ nhớ tiếp tục tăng, nhưng việc thực hiện bgsavevà khởi động lại redis-serverkhiến việc sử dụng bộ nhớ giảm xuống giá trị hợp lý hơn là 70 MB. Đây có thể là một rò rỉ bộ nhớ?
Nyxynyx

Có thể nhưng không chắc (hoặc người khác sẽ báo cáo về nó) ... Nhiều khả năng là một vấn đề phân mảnh. Lần tới, hãy đăng kết quả đầu ra của Redis ' INFO ALL. Nếu dự đoán của tôi là chính xác, ý mem_fragmentation_ratiochí của bầu trời cao.
Itamar Haber

redis-serverhog lên tất cả các bộ nhớ và tai nạn hàng ngày. Bây giờ sắp sử dụng hết bộ nhớ, vì vậy tôi đã nắm bắt được đầu ra INFO ALLvà thêm vào OP. mem_fragmentation_ratio:0.19
Nyxynyx

Nếu bộ dữ liệu redis không vượt quá 250MB và maxmemoryđược đặt thành 1 GB, điều này có nghĩa là khi sử dụng mem của redis đạt 1GB, việc trục xuất vẫn sẽ xóa dữ liệu? Vì redis mem_fragmentation_ratio0.19, điều đó có nghĩa là có quá nhiều phân mảnh, hoặc quá nhiều được lưu trữ trong trao đổi, hoặc cả hai? Cách nào để giảm sự phân mảnh?
Nyxynyx

Khi máy chủ redis sắp sập do OOM, rdbtools cho thấy các khóa trong redis chỉ chiếm 60MB. Điều này có vẻ như phân mảnh cực kỳ nghiêm trọng? Xem xét việc chiếm tới 4,4 GB RAM và 22,4G Hoán đổi.
Nyxynyx

5

Điều này gần như chắc chắn là phân mảnh bộ nhớ, vì redis nổi tiếng và được yêu thích trong sản xuất và có lẽ bạn chưa tìm thấy rò rỉ bộ nhớ.

Các khuyến nghị về việc thiết lập kích thước của hồ bơi sẽ không giúp phân mảnh. Bạn sẽ phải đặc biệt hạ thấp kích thước Redis - thấp hơn kích thước bộ nhớ thực của bạn - bởi vì Redis không thể giải thích được sự phân mảnh - nhưng, về mặt câu trả lời ngắn, bạn sẽ phải làm điều đó và bắt đầu kế hoạch khởi động lại máy chủ thường xuyên.

Nguyên tắc cơ bản của tôi khi làm việc với nhiều hệ điều hành và cơ sở dữ liệu trong bộ nhớ là bạn cần gấp đôi bộ nhớ thực của mình và kích thước bộ nhớ sẽ ổn định trong khoảng 2 tuần.

Tuy nhiên, điều đó phụ thuộc vào các mẫu phân bổ thực tế của bạn và bộ cấp phát bộ nhớ bạn đang sử dụng.

Ngay bây giờ, bộ cấp phát bộ nhớ tốt nhất mà tôi tìm thấy cho các máy chủ là JEMalloc. Chúng tôi sử dụng nó tại Aerospike ngay bây giờ để giảm (gần như loại bỏ) sự phân mảnh bộ nhớ dài hạn. JEMalloc có một tính năng cho phép bạn tạo "đấu trường" bộ nhớ (nhóm) và trên bất kỳ phân bổ nào, chọn nhóm nào, do đó cung cấp cho bạn phân bổ kích thước giống như và để quản lý phân bổ tuổi thọ bộ nhớ tương tự. Đó là một chiến thắng lớn cho chúng tôi trong các trường hợp bạn đang thảo luận.

Công cụ PHP Zend rất tinh vi trong vấn đề này, bởi vì tất cả các phân bổ bên trong công cụ đều nằm trong bộ nhớ trên mỗi giao dịch hoặc bộ nhớ toàn cầu. Mỗi bộ nhớ giao dịch được giải phóng tại một lần giảm giá vào cuối giao dịch, và do đó có thể rất hiệu quả.

Nếu bạn đang ở trong Linux, bộ cấp phát bộ nhớ kernel (Clib) đã thực hiện một số vòng xoắn và phiên bản nào bạn bật sẽ xác định đáng kể mức độ phân mảnh, giống như mẫu ứng dụng thực tế. Ví dụ, một số phân bổ tốt hơn nhiều khi bạn là đối tượng tăng trưởng nhẹ, một số tồi tệ hơn nhiều. Đáng tiếc, thậm chí thảo luận với những người dùng Redis khác có nghĩa là nói về hệ điều hành nào và phiên bản hệ điều hành nào bạn đang sử dụng.

Việc bạn có thể khởi động lại máy chủ (từ sự kiên trì) và lấy lại bộ nhớ có thể có nghĩa là rò rỉ, nhưng nhiều khả năng chỉ ra sự phân mảnh.

  1. Không cho phép trao đổi (tốt hơn là OOM thay vì trao đổi, cho redis)
  2. Giảm kích thước bộ nhớ của redis
  3. Khởi động lại theo lịch trình

Làm thế nào bạn sẽ giảm kích thước bộ nhớ, bằng cách điều chỉnh maxmemory?
Nyxynyx
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.