设maxmemory=3MB配合noeviction策略,验证写满之后的OOM报错和读操作依然可用,再对照allkeys-lru策略下同样超量写入全部成功。
noeviction策略下,maxmemory是一道硬墙。
操作CONFIG SET maxmemory-policy noeviction CONFIG SET maxmemory 3mb 循环SET,每个value 2000字节
第几个key开始被拒绝。
结果写入失败: command not allowed when used memory > 'maxmemory'. 成功写入了 714 个key才触发OOM used_memory: 3144560 maxmemory: 3145728
验证了noeviction策略下maxmemory是一条硬性红线:内存用量一旦超过这条线,所有会增加内存占用的写命令都会被直接拒绝,报出一个明确的OOM风格错误,不会尝试腾挪任何数据。
被拒绝的只是"会让内存继续增长"的写操作。
结果GET k_0 → 成功返回了完整的2000字节值
确认了:maxmemory的限制只针对写操作,已经存进去的数据在内存超限之后依然可以正常读取——noeviction的语义是"不许再往里塞新数据,但已有数据完全不受影响",跟"内存耗尽系统崩溃"完全不是一回事。
同样的maxmemory,同样超量的写入,唯一变量是策略。
结果全部500次写入都成功,没有报错(触发了淘汰而不是拒绝)
maxmemory 本身只是划定了一条"内存该在什么时候开始有动作"的线,真正决定"超过这条线之后怎么办"的,是 maxmemory-policy——noeviction 选择"宁可让新写入失败,也不主动删任何数据",其它带淘汰算法的策略则选择"主动腾地方,让写入继续成功,代价是要牺牲掉一些旧数据"。没有配置淘汰策略的Redis实例默认就是noeviction,这也是为什么很多线上事故的表现是"Redis突然写不进去了但读还正常"——排查时第一反应应该是查maxmemory和maxmemory-policy,而不是以为服务挂了。
每一步都是本文上面用redis-cli和redis-py跑出来的原始结果。
noeviction vs allkeys-lru:对照两种策略对超量写入的处理方式