redis超过内存大小是否会挂?

redis超过内存大小是否会挂

前提条件:appendonly yes

好奇这个问题,所以做了个实验。答案是会挂掉的,并且数据完全持久化。

容量达到限制之后,内存溢出,Redis服务会挂掉。但是重启redis可以发现,实际落库持久化的并执行了db13:keys=420,expires=0,avg_ttl=0db13:keys=420,expires=0,avg_ttl=0程序日志可以看出执行到这里开始挂掉,完全持久化成功。那redis的持久化策略是啥呢?

模拟插入大数据量

package icu.kevin.cache.avalanche;


import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.Random;

@Slf4j
@RequestMapping("large")
@RestController
public class LargeKeyController {


    @Autowired
    private RedisTemplate redisTemplate;

    @GetMapping("init")
    @Async
    public void initData(@RequestParam (name = "size", defaultValue = "5000") Integer size){
        log.info("starting init size........." + size);
        for (int i = 0; i < size; i++) {
            log.info("starting init data........." + i);
            redisTemplate.opsForSet().add("large_key_" + i, generateTestData(10 * 1024));
        }
    }


    public static String generateTestData(int sizeInKb) {
        int length = sizeInKb * 1024;
        int chunkSize = 10;
        int chunks = length / chunkSize;
        StringBuilder sb = new StringBuilder(length);
        for (int i = 0; i < chunks; i++) {
            String chunk = generateRandomString(chunkSize);
            sb.append(chunk);
        }
        return sb.toString();
    }

    public static String generateRandomString(int length) {
        String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
        StringBuilder sb = new StringBuilder(length);
        Random random = new Random();
        for (int i = 0; i < length; i++) {
            int index = random.nextInt(characters.length());
            sb.append(characters.charAt(index));
        }
        return sb.toString();
    }

}

容量达到限制之后,内存溢出,Redis服务会挂掉

=== REDIS BUG REPORT START: Cut & paste starting from here ===
[28204] 07 Aug 10:57:51.458 # Redis version: 3.0.504
[28204] 07 Aug 10:57:51.459 # --- EXCEPTION_ACCESS_VIOLATION
[28204] 07 Aug 10:57:51.460 # --- STACK TRACE
redis-server.exe!LogStackTrace(c:\release\redis\src\win32_interop\win32_stacktrace.cpp:95)(0x00FBE580, 0x00FBFF60, 0x40028E60, 0x40124730)
。。。。。。。。。。。。。。。。。。。。
[28204] 07 Aug 10:57:51.488 # --- INFO OUTPUT
# Server
redis_version:3.0.504
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:a4f7a6e86f2d60b3
redis_mode:standalone
os:Windows
arch_bits:64
multiplexing_api:WinSock_IOCP
process_id:28204
run_id:56302233dfa6c8a9a5ce3804c5638c3415c8d668
tcp_port:6379
uptime_in_seconds:139
uptime_in_days:0
hz:10
lru_clock:11723439
config_file:D:\Program Files\Redis\redis.windows-service.conf

# Clients
connected_clients:2
client_longest_output_list:0
client_biggest_input_buf:0
blocked_clients:0

# Memory
used_memory:5386539784
used_memory_human:5.02G
used_memory_rss:5386481064
used_memory_peak:5386539784
used_memory_peak_human:5.02G
used_memory_lua:36864
mem_fragmentation_ratio:1.00
mem_allocator:jemalloc-3.6.0

# Persistence
loading:0
rdb_changes_since_last_save:417
rdb_bgsave_in_progress:0
rdb_last_save_time:1722999332
rdb_last_bgsave_status:ok
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
aof_last_write_status:ok

# Stats
total_connections_received:420
total_commands_processed:841
instantaneous_ops_per_sec:6
total_net_input_bytes:4372605821
total_net_output_bytes:8298
instantaneous_input_kbps:34863.84
instantaneous_output_kbps:0.05
rejected_connections:0
sync_full:0
sync_partial_ok:0
sync_partial_err:0
expired_keys:0
evicted_keys:0
keyspace_hits:0
keyspace_misses:0
pubsub_channels:0
pubsub_patterns:0
latest_fork_usec:0
migrate_cached_sockets:0

# 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:7.17
used_cpu_user:4.48
used_cpu_sys_children:0.00
used_cpu_user_children:0.00

# Commandstats
cmdstat_sadd:calls=417,usec=1579622,usec_per_call=3788.06
cmdstat_select:calls=419,usec=2190,usec_per_call=5.23
cmdstat_scan:calls=1,usec=34,usec_per_call=34.00
cmdstat_ping:calls=3,usec=16,usec_per_call=5.33
cmdstat_info:calls=1,usec=107,usec_per_call=107.00

# Cluster
cluster_enabled:0

# Keyspace
db0:keys=21,expires=0,avg_ttl=0
db10:keys=4,expires=0,avg_ttl=0
db13:keys=420,expires=0,avg_ttl=0
[28204] 07 Aug 10:57:51.489 #
=== REDIS BUG REPORT END. Make sure to include from START to END. ===

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Redis是一个开源的键值对存储数据库。它使用内存作为主要的数据存储介质,因此在处理大量数据时,需要考虑内存的使用和管理问题。Redis通过实现一些内存淘汰机制来解决这个问题。本文将对Redis的内存淘汰机制进行详细解析。 一、Redis的内存淘汰机制概述 Redis的内存淘汰机制用于在内存使用超过预设阈值时,删除一些不常用的键值对,以释放内存空间。Redis提供了多种内存淘汰机制,包括: 1. noeviction(默认):当内存不足以容纳新写入数据时,新写入操作报错。 2. allkeys-lru:在所有的键中,最近最少使用的键被优先移除。 3. volatile-lru:在设置了过期时间的键中,最近最少使用的键被优先移除。 4. allkeys-random:从所有的键中随机移除键。 5. volatile-random:从设置了过期时间的键中随机移除键。 6. volatile-ttl:从设置了过期时间的键中,根据键值对的ttl(time-to-live)值,移除最近将要过期的键。 其中,noeviction是Redis的默认策略,表示当内存不足以容纳新写入数据时,新写入操作报错。而其他五种策略则是在内存不足时,用于删除一些键值对以释放内存空间的策略。 二、allkeys-lru淘汰策略 allkeys-lru策略是基于最近最少使用(LRU)算法的内存淘汰机制。它在所有的键中,选择最近最少使用的键进行淘汰。 这个算法的实现依赖于Redis记录键的访问时间。当一个键被访问时,Redis记录下当前时间,并将该时间戳与键的访问时间进行比较。当内存不足以容纳新写入数据时,Redis选择访问时间最早的键进行淘汰。 allkeys-lru策略的优点是可以保证数据的热度。它优先保留经常访问的数据,而淘汰不常用的数据。这样可以避免一些冷数据占用过多的内存空间,从而提高Redis的性能。 三、volatile-lru淘汰策略 volatile-lru策略是基于LRU算法的内存淘汰机制,但它只在设置了过期时间的键中选择最近最少使用的键进行淘汰。 volatile-lru策略的实现方式与allkeys-lru相同,只是在选择淘汰键的时候,只考虑设置了过期时间的键。 volatile-lru策略的优点是可以在保证数据热度的同时,避免长期不使用的过期键占用过多的内存空间。 四、allkeys-random淘汰策略 allkeys-random策略是一种随机淘汰算法,它从所有的键中随机选择一个键进行淘汰。 这种算法的实现方式比较简单,只需要在选择淘汰键时,从所有的键中随机选择一个即可。它的优点是可以避免一些冷数据占用过多的内存空间,但缺点是无法保证数据的热度。 五、volatile-random淘汰策略 volatile-random策略是一种随机淘汰算法,它从设置了过期时间的键中随机选择一个键进行淘汰。 这种算法的实现方式与allkeys-random相似,只是在选择淘汰键时,只考虑设置了过期时间的键。它的优点是可以避免长期不使用的过期键占用过多的内存空间,但缺点是无法保证数据的热度。 六、volatile-ttl淘汰策略 volatile-ttl策略是根据键值对的ttl值,选择将要过期的键进行淘汰。 这种算法的实现方式比较简单,只需要在选择淘汰键时,从设置了过期时间的键中选择将要过期的键即可。它的优点是可以在保证数据热度的同时,避免长期不使用的过期键占用过多的内存空间。 七、Redis的内存淘汰机制配置 Redis的内存淘汰机制可以通过配置文件进行设置。在Redis的配置文件redis.conf中,可以设置maxmemory和maxmemory-policy两个参数。 maxmemory参数用于设置Redis使用的最大内存大小。当Redis使用的内存超过这个值时,就触发内存淘汰机制。 maxmemory-policy参数用于设置Redis的内存淘汰机制策略。它可以设置为noeviction、allkeys-lru、volatile-lru、allkeys-random、volatile-random和volatile-ttl中的任何一个值。 例如,以下是Redis配置文件中的maxmemory和maxmemory-policy参数设置: ``` maxmemory 1gb maxmemory-policy allkeys-lru ``` 这表示Redis最大使用1GB的内存,当内存使用超过1GB时,使用allkeys-lru策略进行内存淘汰。 八、总结 Redis的内存淘汰机制通过实现一些内存淘汰算法,可以在内存使用超过预设阈值时,删除一些不常用的键值对,以释放内存空间。其中,Redis提供了多种内存淘汰机制,包括noeviction、allkeys-lru、volatile-lru、allkeys-random、volatile-random和volatile-ttl。不同的策略有不同的优点和缺点,应该根据实际需求进行选择。在配置Redis的内存淘汰机制时,需要设置maxmemory和maxmemory-policy两个参数,以控制Redis的最大内存使用量和内存淘汰策略。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jc0803kevin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值