记一次redis异常停止排查及参数优化

简介:

背景
跑一个程序,程序采取redis存储任务状态及任务值,程序通过redis获取任务后进行任务下发

image

现象
正在运行的任务进度突然停止,查看执行应用日志,发现报错
日志报错信息
redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool

处理过程
根据报错猜测的可能原因有:

  • 1 Jedis 对象用完以后,没有释放掉,被一直占用,所以会出现无法获取新的资源
  • 2 redis服务找不到了
    考虑到只有一个程序在连接redis,应该不会出现连接不够用的情况

所以先从redis的状态开始排查

1 查看redis状态

 ps  -ef | grep  redis

发现redis进程没了,查看历史登陆和历史命令,没有人工停止的迹象

因为没发现什么问题,就手动重启了redis

/redis-server ../redis.conf &

重启后观察应用日志,发现开始又报新的错误:
redis.clients.jedis.exceptions.JedisDataException: MISCONF Redis is configured to save RDB snapshots, but it is currently not able to persist on disk. Commands that may modify the data set are disabled, because this instance is configured to report errors during writes if RDB snapshotting fails (stop-writes-on-bgsave-error option). Please check the Redis logs for details about the RDB error.
redis.clients.jedis.exceptions.JedisDataException: MISCONF Redis is configured to save RDB snapshots, but it is currently not able to persist on disk.

通过日志可以看到,报空间不足,所以进行查看服务器状态
查看磁盘空间显示是充足的
查看内存状态

 free -m

发现内存剩余不足

image

登陆redis客户端查看内存使用情况

 redis-cli -h ip -p port
 info memory

image

参数详解:

used_memory : 由 Redis 分配器分配的内存总量,以字节(byte)为单位
used_memory_human : 以人类可读的格式返回 Redis 分配的内存总量
used_memory_rss : 从操作系统的角度,返回 Redis 已分配的内存总量(俗称常驻集大小)。这个值和 top 、 ps 等命令的输出一致
used_memory_peak : Redis 的内存消耗峰值(以字节为单位)
used_memory_peak_human : 以人类可读的格式返回 Redis 的内存消耗峰值
used_memory_lua : Lua 引擎所使用的内存大小(以字节为单位)
mem_fragmentation_ratio : used_memory_rss 和 used_memory 之间的比率
mem_allocator : 在编译时指定的, Redis 所使用的内存分配器。可以是 libc 、 jemalloc 或者 tcmalloc

对比几个值
1)当 rss > used ,且两者的值相差较大时,表示存在(内部或外部的)内存碎片。
内存碎片的比率可以通过 mem_fragmentation_ratio 的值看出。
2)当 used > rss 时,表示 Redis 的部分内存被操作系统换出到交换空间了,在这种情况下,操作可能会产生明显的延迟
参数参考:
https://jingyan.baidu.com/article/2c8c281dbd079f0008252a0f.html

发现redis使用内存已经4G了,比最开始启动时的内存多出来很多,查看相关资料了解:
Redis的内存如果不在启动前限制,默认是无限制的,32位的redis会限制在3G,目前使用的是64位,所以在使用过程中因为key的增加内存不断的增加

调节配置参数

总结实际修改过的的步骤:

  • 1 将stop-writes-on-bgsave-error设置为no
stop-writes-on-bgsave-error no
  • 2 配置maxmemory(部分起到作用)
maxmemory 内存大小(字节)
  • 3 系统层面添加overcommit_memory
vim /etc/sysctl.conf
vm.overcommit_memory=1 
使文件生效
sysctl -p /etc/sysctl.conf
  • 4 修改redis
    清理不使用的key(实际解决问题的办法)

实际试错的排查过程
1 查询资料说可能是bgsave失败,临时的解决办法是
stop-writes-on-bgsave-error yes修改为 stop-writes-on-bgsave-error no
bgsave方法的介绍:
image
image

结果:
修改了,重启,没效果
2 又看到需要修改系统层面参数
vim /etc/sysctl.conf

vm.overcommit_memory=1

使文件生效

sysctl -p /etc/sysctl.conf

结果:

内存仍然没有下去,不可用

3 修改redis key过期算法
maxmemory-policy volatile-lru

LRU是Least Recently Used 近期最少使用算法。

  1. volatile-lru -> 根据LRU算法生成的过期时间来删除。
  2. allkeys-lru -> 根据LRU算法删除任何key。
  3. volatile-random -> 根据过期设置来随机删除key。
  4. allkeys->random -> 无差别随机删。
  5. volatile-ttl -> 根据最近过期时间来删除(辅以TTL)
  6. noeviction -> 谁也不删,直接在写操作时返回错误。
    image

结果:
内存占用还是4G,没有消减

image

4 修改maxmemory
查看redis相关资料,发现:
如果不设置maxmemory或者设置为0,64位系统不限制内存,32位系统最多使用3GB内存。

所以通过修改redis.conf配置,指定可使用的最大内存

修改maxmemory 3221225472(3G)

image

重启
结果:
启动后直接报错
redis.clients.jedis.exceptions.JedisDataException: OOM command not allowed when used memory > 'maxmemory'.

使用config get * 命令得到redis 的maxmemory

>config get *

image

查看修改的配置是生效的

查看实际使用的内存:

>info memory

image

实际使用还是4G

看来还是key太大了,自动清理机制还是不能解决问题

解决
为了任务能继续跑下去,把key消费完,手动的调低同服务器其他机器的jvm启动参数,程序继续跑了下去

5 手动清理key
在任务跑的差不多时候,手动清理不需要的key值

总结
这次问题最原始的原因是没有做内存限制,导致随着key的不断增加,内存逐渐变多
以后在安装配置64位的redis时,最开始就要设置最大使用内存和清理key的算法,这样不会影响其他服务

相关文章
|
11月前
|
缓存 运维 监控
Redis 7.0 高性能缓存架构设计与优化
🌟蒋星熠Jaxonic,技术宇宙中的星际旅人。深耕Redis 7.0高性能缓存架构,探索函数化编程、多层缓存、集群优化与分片消息系统,用代码在二进制星河中谱写极客诗篇。
1932 3
|
缓存 NoSQL 算法
高并发秒杀系统实战(Redis+Lua分布式锁防超卖与库存扣减优化)
秒杀系统面临瞬时高并发、资源竞争和数据一致性挑战。传统方案如数据库锁或应用层锁存在性能瓶颈或分布式问题,而基于Redis的分布式锁与Lua脚本原子操作成为高效解决方案。通过Redis的`SETNX`实现分布式锁,结合Lua脚本完成库存扣减,确保操作原子性并大幅提升性能(QPS从120提升至8,200)。此外,分段库存策略、多级限流及服务降级机制进一步优化系统稳定性。最佳实践包括分层防控、黄金扣减法则与容灾设计,强调根据业务特性灵活组合技术手段以应对高并发场景。
3845 7
|
缓存 NoSQL Redis
Redis如何优化频繁命令往返造成的性能瓶颈?
频繁的命令往返是Redis性能优化中需要重点关注的问题。通过使用Pipeline、Lua脚本、事务、合并命令、连接池以及合理设置网络超时,可以有效减少网络往返次数,优化Redis的性能。这些优化措施不仅提升了Redis的处理能力,还能确保系统在高并发情况下的稳定性和可靠性。
416 14
|
存储 监控 NoSQL
NoSQL与Redis配置与优化
通过合理配置和优化Redis,可以显著提高其性能和可靠性。选择合适的数据结构、优化内存使用、合理设置持久化策略、使用Pipeline批量执行命令、以及采用分布式集群方案,都是提升Redis性能的重要手段。同时,定期监控和维护Redis实例,及时调整配置,能够确保系统的稳定运行。希望本文对您在Redis的配置与优化方面有所帮助。
312 23
|
缓存 NoSQL JavaScript
Vue.js应用结合Redis数据库:实践与优化
将Vue.js应用与Redis结合,可以实现高效的数据管理和快速响应的用户体验。通过合理的实践步骤和优化策略,可以充分发挥两者的优势,提高应用的性能和可靠性。希望本文能为您在实际开发中提供有价值的参考。
537 11
|
存储 监控 NoSQL
NoSQL与Redis配置与优化
通过合理配置和优化Redis,可以显著提高其性能和可靠性。选择合适的数据结构、优化内存使用、合理设置持久化策略、使用Pipeline批量执行命令、以及采用分布式集群方案,都是提升Redis性能的重要手段。
335 7
|
NoSQL 关系型数据库 MySQL
MySQL与Redis协同作战:百万级数据统计优化实践
【10月更文挑战第21天】 在处理大规模数据集时,传统的单体数据库解决方案往往力不从心。MySQL和Redis的组合提供了一种高效的解决方案,通过将数据库操作与高速缓存相结合,可以显著提升数据处理的性能。本文将分享一次实际的优化案例,探讨如何利用MySQL和Redis共同实现百万级数据统计的优化。
1013 9
|
存储 监控 NoSQL
Redis大Key问题如何排查?如何解决?
Redis大Key问题如何排查?如何解决?
963 0
Redis大Key问题如何排查?如何解决?
|
NoSQL 关系型数据库 MySQL
MySQL与Redis协同作战:优化百万数据查询的实战经验
【10月更文挑战第13天】 在处理大规模数据集时,传统的关系型数据库如MySQL可能会遇到性能瓶颈。为了提升数据处理的效率,我们可以结合使用MySQL和Redis,利用两者的优势来优化数据查询。本文将分享一次实战经验,探讨如何通过MySQL与Redis的协同工作来优化百万级数据统计。
883 5
|
NoSQL 关系型数据库 MySQL
MySQL与Redis协同作战:百万数据量的优化实录
【10月更文挑战第6天】 在现代互联网应用中,随着用户量的增加和业务逻辑的复杂化,数据量级迅速增长,这对后端数据库系统提出了严峻的挑战。尤其是当数据量达到百万级别时,传统的数据库解决方案往往会遇到性能瓶颈。本文将分享一次使用MySQL与Redis协同优化大规模数据统计的实战经验。
773 3