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

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
日志服务 SLS,月写入数据量 50GB 1个月
简介:

背景
跑一个程序,程序采取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的算法,这样不会影响其他服务

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
21天前
|
NoSQL 关系型数据库 MySQL
MySQL与Redis协同作战:百万级数据统计优化实践
【10月更文挑战第21天】 在处理大规模数据集时,传统的单体数据库解决方案往往力不从心。MySQL和Redis的组合提供了一种高效的解决方案,通过将数据库操作与高速缓存相结合,可以显著提升数据处理的性能。本文将分享一次实际的优化案例,探讨如何利用MySQL和Redis共同实现百万级数据统计的优化。
54 9
|
21天前
|
NoSQL 关系型数据库 MySQL
MySQL与Redis协同作战:优化百万数据查询的实战经验
【10月更文挑战第13天】 在处理大规模数据集时,传统的关系型数据库如MySQL可能会遇到性能瓶颈。为了提升数据处理的效率,我们可以结合使用MySQL和Redis,利用两者的优势来优化数据查询。本文将分享一次实战经验,探讨如何通过MySQL与Redis的协同工作来优化百万级数据统计。
48 5
|
29天前
|
NoSQL 关系型数据库 MySQL
MySQL与Redis协同作战:百万数据量的优化实录
【10月更文挑战第6天】 在现代互联网应用中,随着用户量的增加和业务逻辑的复杂化,数据量级迅速增长,这对后端数据库系统提出了严峻的挑战。尤其是当数据量达到百万级别时,传统的数据库解决方案往往会遇到性能瓶颈。本文将分享一次使用MySQL与Redis协同优化大规模数据统计的实战经验。
109 3
|
29天前
|
NoSQL 关系型数据库 BI
记录一次MySQL+Redis实现优化百万数据统计的方式
【10月更文挑战第13天】 在处理百万级数据的统计时,传统的单体数据库往往力不从心,这时结合使用MySQL和Redis可以显著提升性能。以下是一次实际优化案例的详细记录。
101 1
|
1月前
|
JSON NoSQL Java
springBoot:jwt&redis&文件操作&常见请求错误代码&参数注解 (九)
该文档涵盖JWT(JSON Web Token)的组成、依赖、工具类创建及拦截器配置,并介绍了Redis的依赖配置与文件操作相关功能,包括文件上传、下载、删除及批量删除的方法。同时,文档还列举了常见的HTTP请求错误代码及其含义,并详细解释了@RequestParam与@PathVariable等参数注解的区别与用法。
|
1月前
|
存储 缓存 NoSQL
大数据-46 Redis 持久化 RDB AOF 配置参数 混合模式 具体原理 触发方式 优点与缺点
大数据-46 Redis 持久化 RDB AOF 配置参数 混合模式 具体原理 触发方式 优点与缺点
56 1
|
3月前
|
缓存 NoSQL 测试技术
【Azure Redis 缓存】Azure Redis 功能性讨论三: 调优参数配置
【Azure Redis 缓存】Azure Redis 功能性讨论三: 调优参数配置
|
3月前
|
缓存 NoSQL 网络协议
【Azure Redis 缓存】Redisson 连接 Azure Redis出现间歇性 java.net.UnknownHostException 异常
【Azure Redis 缓存】Redisson 连接 Azure Redis出现间歇性 java.net.UnknownHostException 异常
|
3月前
|
监控 NoSQL Redis
【Azure Redis】Redis服务负载达到100%后的影响及有何优化方法
【Azure Redis】Redis服务负载达到100%后的影响及有何优化方法
|
3月前
|
NoSQL 网络协议 Linux
【Azure Redis】Redis客户端出现15分钟的超时异常
【Azure Redis】Redis客户端出现15分钟的超时异常