Redis ทำอะไรเมื่อหน่วยความจำไม่เพียงพอ


111

นี่อาจเป็นคำถามที่ง่าย แต่ฉันมีปัญหาในการหาคำตอบ Redis 2.0 จัดการกับหน่วยความจำที่จัดสรรสูงสุดหมดอย่างไร จะตัดสินใจได้อย่างไรว่าจะลบข้อมูลใดหรือเก็บข้อมูลใดไว้ในหน่วยความจำ


คำตอบ:


94

หากคุณเปิดฟังก์ชันหน่วยความจำเสมือนไว้ (ใหม่ในเวอร์ชัน 2.0 หรือ 2.2 ฉันคิดว่า) Redis จะเริ่มจัดเก็บข้อมูลที่ "ไม่ได้ใช้บ่อย" ลงในดิสก์เมื่อหน่วยความจำหมด

หากหน่วยความจำเสมือนใน Redis ถูกปิดใช้งานจะดูเหมือนว่าหน่วยความจำเสมือนของระบบปฏิบัติการเริ่มถูกใช้งาน (เช่นการสลับ) และประสิทธิภาพจะลดลงอย่างมาก

ตอนนี้คุณสามารถกำหนดค่า Redis ด้วยพารามิเตอร์ maxmemory ซึ่งจะป้องกันไม่ให้ Redis ใช้หน่วยความจำเพิ่มเติม (ค่าเริ่มต้น)

Redis เวอร์ชันใหม่กว่ามีนโยบายที่หลากหลายเมื่อถึง maxmemory:

  • volatile-lru ลบคีย์ออกจากคีย์ที่มีชุดหมดอายุพยายามลบคีย์ที่ไม่ได้ใช้เมื่อเร็ว ๆ นี้
  • volatile-ttl ลบคีย์ออกระหว่างคีย์ที่มีชุดหมดอายุพยายามลบคีย์โดยมีเวลาเหลืออยู่สั้น ๆ
  • ระเหย - สุ่มลบคีย์สุ่มออกจากกลุ่มที่มีชุดหมดอายุ
  • allkeys-lru เหมือน volatile-lru แต่จะลบคีย์ทุกประเภททั้งคีย์ปกติหรือคีย์ที่มีชุดหมดอายุ
  • allkeys-random เหมือน volatile-random แต่จะลบคีย์ทุกประเภททั้งคีย์ปกติและคีย์ที่มีชุดหมดอายุ

หากคุณเลือกนโยบายที่ลบคีย์ที่มีชุด EXPIRE เท่านั้นเมื่อ Redis หน่วยความจำหมดดูเหมือนว่าโปรแกรมจะยกเลิกการทำงาน malloc () นั่นคือถ้าคุณพยายามจัดเก็บข้อมูลมากขึ้นการดำเนินการก็จะล้มเหลวอย่างน่าสังเวช

ลิงก์สำหรับข้อมูลเพิ่มเติม (เนื่องจากคุณไม่ควรใช้คำของฉัน):


8
Redis Virtual Memory เลิกใช้งานแล้ว ดูredis.io/topics/virtual-memory
cgaldiolo

19

จากredis.confเวอร์ชัน2.8.2

# Don't use more memory than the specified amount of bytes.
# When the memory limit is reached Redis will try to remove keys
# according to the eviction policy selected (see maxmemory-policy).
#
# If Redis can't remove keys according to the policy, or if the policy is
# set to 'noeviction', Redis will start to reply with errors to commands
# that would use more memory, like SET, LPUSH, and so on, and will continue
# to reply to read-only commands like GET.
#
# This option is usually useful when using Redis as an LRU cache, or to set
# a hard memory limit for an instance (using the 'noeviction' policy).
#
# WARNING: If you have slaves attached to an instance with maxmemory on,
# the size of the output buffers needed to feed the slaves are subtracted
# from the used memory count, so that network problems / resyncs will
# not trigger a loop where keys are evicted, and in turn the output
# buffer of slaves is full with DELs of keys evicted triggering the deletion
# of more keys, and so forth until the database is completely emptied.
#
# In short... if you have slaves attached it is suggested that you set a lower
# limit for maxmemory so that there is some free RAM on the system for slave
# output buffers (but this is not needed if the policy is 'noeviction').
#
# maxmemory <bytes>

# MAXMEMORY POLICY: how Redis will select what to remove when maxmemory
# is reached. You can select among five behaviors:
#
# volatile-lru -> remove the key with an expire set using an LRU algorithm
# allkeys-lru -> remove any key according to the LRU algorithm
# volatile-random -> remove a random key with an expire set
# allkeys-random -> remove a random key, any key
# volatile-ttl -> remove the key with the nearest expire time (minor TTL)
# noeviction -> don't expire at all, just return an error on write operations
#
# Note: with any of the above policies, Redis will return an error on write
#       operations, when there are no suitable keys for eviction.
#
#       At the date of writing these commands are: set setnx setex append
#       incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd
#       sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby
#       zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby
#       getset mset msetnx exec sort
#
# The default is:
#
# maxmemory-policy volatile-lru

3
เริ่มต้นmaxmemory-policyใน Redis 3.2 อยู่ในขณะนี้noeviction: raw.githubusercontent.com/antirez/redis/3.2/redis.conf
LoicAG

5

อัปเดต redis 4.0

127.0.0.1:6379> MEMORY HELP
1) "MEMORY DOCTOR                        - Outputs memory problems report"
2) "MEMORY USAGE <key> [SAMPLES <count>] - Estimate memory usage of key"
3) "MEMORY STATS                         - Show memory usage details"
4) "MEMORY PURGE                         - Ask the allocator to release memory"
5) "MEMORY MALLOC-STATS                  - Show allocator internal stats"

/usr/local/etc/redis.conf

############################## MEMORY MANAGEMENT ################################

# Set a memory usage limit to the specified amount of bytes.
# When the memory limit is reached Redis will try to remove keys
# according to the eviction policy selected (see maxmemory-policy).
#
# If Redis can't remove keys according to the policy, or if the policy is
# set to 'noeviction', Redis will start to reply with errors to commands
# that would use more memory, like SET, LPUSH, and so on, and will continue
# to reply to read-only commands like GET.
#
# This option is usually useful when using Redis as an LRU or LFU cache, or to
# set a hard memory limit for an instance (using the 'noeviction' policy).
#
# WARNING: If you have slaves attached to an instance with maxmemory on,
# the size of the output buffers needed to feed the slaves are subtracted
# from the used memory count, so that network problems / resyncs will
# not trigger a loop where keys are evicted, and in turn the output
# buffer of slaves is full with DELs of keys evicted triggering the deletion
# of more keys, and so forth until the database is completely emptied.
#
# In short... if you have slaves attached it is suggested that you set a lower
# limit for maxmemory so that there is some free RAM on the system for slave
# output buffers (but this is not needed if the policy is 'noeviction').
#
# maxmemory <bytes>

# MAXMEMORY POLICY: how Redis will select what to remove when maxmemory
# is reached. You can select among five behaviors:
#
# volatile-lru -> Evict using approximated LRU among the keys with an expire set.
# allkeys-lru -> Evict any key using approximated LRU.
# volatile-lfu -> Evict using approximated LFU among the keys with an expire set.
# allkeys-lfu -> Evict any key using approximated LFU.
# volatile-random -> Remove a random key among the ones with an expire set.
# allkeys-random -> Remove a random key, any key.
# volatile-ttl -> Remove the key with the nearest expire time (minor TTL)
# noeviction -> Don't evict anything, just return an error on write operations.
#
# LRU means Least Recently Used
# LFU means Least Frequently Used
#
# Both LRU, LFU and volatile-ttl are implemented using approximated
# randomized algorithms.
#
# Note: with any of the above policies, Redis will return an error on write
#       operations, when there are no suitable keys for eviction.
#
#       At the date of writing these commands are: set setnx setex append
#       incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd
#       sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby
#       zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby
#       getset mset msetnx exec sort
#
# The default is:
#
# maxmemory-policy noeviction

# LRU, LFU and minimal TTL algorithms are not precise algorithms but approximated
# algorithms (in order to save memory), so you can tune it for speed or
# accuracy. For default Redis will check five keys and pick the one that was
# used less recently, you can change the sample size using the following
# configuration directive.
#
# The default of 5 produces good enough results. 10 Approximates very closely
# true LRU but costs more CPU. 3 is faster but not very accurate.
#
# maxmemory-samples 5

4

ฉันเพิ่งเริ่มอ่านเกี่ยวกับ Redis เมื่อไม่นานมานี้ดังนั้นฉันจึงไม่คิดบวก แต่ฉันเจอเกร็ดเล็ก ๆ น้อย ๆ ที่อาจเป็นประโยชน์

นี่คือตัวอย่างจากhttp://antirez.com/post/redis-as-LRU-cache.html :

อีกวิธีหนึ่งในการใช้ Redis เป็นแคชคือคำสั่ง maxmemory ซึ่งเป็นคุณลักษณะที่อนุญาตให้ระบุจำนวนหน่วยความจำสูงสุดที่จะใช้ เมื่อข้อมูลใหม่ถูกเพิ่มไปยังเซิร์ฟเวอร์และถึงขีด จำกัด หน่วยความจำแล้วเซิร์ฟเวอร์จะลบข้อมูลเก่าบางส่วนออกโดยลบคีย์ที่ระเหยได้นั่นคือคีย์ที่มีการตั้งค่า EXPIRE (การหมดเวลา) แม้ว่าคีย์จะยังอยู่ไกลก็ตาม จากการหมดอายุโดยอัตโนมัติ

นอกจากนี้ Redis 2.0 ยังมีโหมด VM ที่คีย์ทั้งหมดต้องพอดีกับหน่วยความจำ แต่ค่าสำหรับคีย์ที่ไม่ค่อยได้ใช้สามารถอยู่ในดิสก์ได้:


2

หากคุณสงสัยว่า Redis (2.8) ตอบสนองอย่างไรเมื่อถึงค่าสูงสุดที่กำหนดโดยการกำหนดค่าจะมีลักษณะดังนี้:

$ redis-cli
127.0.0.1:6379> GET 5
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
127.0.0.1:6379> SET 5 a
(error) OOM command not allowed when used memory > 'maxmemory'.

1

ฉันเพิ่งประสบกับสถานการณ์ที่ไม่มีหน่วยความจำว่างและแอปพลิเคชันของฉันหยุดชะงัก (เขียนไม่ได้อ่านเป็นไปได้) การเรียกใช้สคริปต์ PHP หยุดตายในแทร็กกลางทางและต้องkill -9'd ด้วยตนเอง (แม้ว่าหน่วยความจำจะเป็น ทำใช้ได้).

ฉันคิดว่าข้อมูลสูญหาย (หรือข้อมูลไม่สอดคล้องกัน) เกิดขึ้นดังนั้นฉันจึงทำการflushdbกู้คืนจากการสำรองข้อมูล บทเรียน? การสำรองข้อมูลเป็นเพื่อนของคุณ


-3

Redis ไม่ใช่แคชเหมือน memcached โดยค่าเริ่มต้น (ซึ่งตั้งmaxmemory-policyค่าพารามิเตอร์เป็นnoeviction) ข้อมูลทั้งหมดที่คุณใส่ใน redis จะไม่ถูกลบออกมีข้อยกเว้นเพียงอย่างเดียวในการใช้ EXPIRE


2
แล้วมันจะทำอย่างไรเมื่อหน่วยความจำไม่เพียงพอ? มันจะเก็บข้อมูลใหม่ในดิสก์ไม่ใช่หน่วยความจำ?
Cory

1
สิ่งนี้ไม่ถูกต้อง (ตอนนี้) Redis มีกลไกการขับไล่ที่สำคัญโดยมีนโยบายที่มีอยู่หลายประการ: redis.io/topics/lru-cache
LoicAG

@LoicAG: ฟังดูเหมือนถูกต้องสำหรับฉัน ... เว้นแต่จะมีนโยบายการหมดอายุ Redis จะไม่ขับไล่คีย์ใด ๆ และนั่นเป็นสิ่งที่ดี: ตัวอย่างเช่นฉันไม่สามารถให้ Redis กำจัดคีย์ได้ด้วยตัวเอง
Michael

@Cory: หากมีการตั้งค่านโยบายการขับไล่จะลบคีย์ที่มีอยู่ออกไป อย่างไรก็ตามหากคุณไม่ได้กำหนดนโยบายการขับไล่คุณควรได้รับข้อผิดพลาดหน่วยความจำไม่เพียงพอ
Michael

@ ไมเคิลฉันคิดว่ามันเป็นเรื่องของคำศัพท์: มีนโยบายสูงสุดอยู่เสมอและค่าเริ่มต้นคือ "noeviction"; แต่นโยบาย "allkeys-lru" และ "allkeys-random" จะขับไล่คีย์ออกจากทั้งชุดและอีกอัน ("volatile- *") จะขับไล่คีย์ออกจากชุดคีย์ย่อยที่มีการกำหนด TTL
LoicAG
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.