1 背景

项目中使用了 redis 做旁路缓存。读请求到来时,有以下操作:1.检查缓存,有则返回2.没有则读取数据库,将结果回写到缓存中。

写请求到来时,有以下操作:1.更新数据库 2.更新缓存(实际上删缓存更合适,具体参见 高并发场景下,到底先更新缓存还是先更新数据库)。

使用该方案 redis 正常运行,一段时间后,服务器宕机,提示 aborted core dumped 错误。

2 问题排查

  • 问题定位

错误提示明显的定位了错误位置,根据提示找到相关代码

 await  client.setAsync(key,JSON.stringfy(value));

原来是在 redis 写入时引发的,那就先查看下内存占用情况。

  • 检查内存

 info memory

输出结果很长,就不一一展开了。这里面有几个关键指标:

  • used_memory :当前 redis 使用内存大小。这部分内存包含 redis 内部开销和数据占用的内存。单位是字节(byte), 由 redis 分配器分配

  • used_memory_rss :向操作系统申请的内存大小,即 redis 使用的物理内存大小。这个值和 top 、ps 命令得到的结果一致。

  • mem_fragmentation_ratio :内存碎片率,ratio = used_memory_rss/used_memory。通常 used_memory_rss 会稍高于 used_memory。ratio 指数>1表明有内存碎片,越大表明越多,ratio 指数<1表明正在使用虚拟内存,虚拟内存其实就是硬盘,性能比内存低得多,这是应该增强机器的内存以提高性能。一般来说,ratio 的数值在1 ~ 1.5之间是比较健康的。

查看 key 回收策略

首先了解 redis 控制 key 回收策略的配置项:maxmemory-policy。它的作用是:当内存占用到达最大限制时,redis 会根据设定的回收策略移除 keys。命令行查看memory-policy:

  config get maxmemory-policy

得到结果是 "noeviction",noeviction 是默认值,表示禁止淘汰数据。

当内存到达上限后,如果调用了 set、lpush 等需要占用内存的命令,noeviction 策略则会返回 error。

noeviction 策略一般使用情况如下:

  • 使用 redis 作为 LRU 或者 LFU 缓存
  • 对一个实例设置了严格的内存限制

3 解决方法

查看了内存占用情况和 key 回收策略,可以判断,这是由于 redis 中 key 占用内存过大,并且没进行回收,导致内存占满崩溃。

因此解决方案从这两个角度入手:

  • 增大 redis 内存上限

    maxmemory 默认是0,不限制最大内存。64位系统是不限制内存的,32位系统最多使用3GB内存。一般推荐 redis 内存设置为最大物理内存的一半

    命令行设置:(当前实例无需重启,立即生效)

     config set maxmemory 1024

    更改 redis.config (实例重启后生效)

     maxmemory 1024
  • 设置 key 回收策略

    redis 有以下回收策略:

    • volatile-lru -> 使用 LRU 算法删除(范围:设置了生存时间的键)
    • allkeys-lru -> 使用 LRU 算法删除键(范围:所有键)
    • volatile-lfu -> 使用 LFU 算法删除(范围:设置了生存时间的键)
    • allkeys-lfu -> 使用 LFU 算法删除键(范围:所有键)
    • volatile-random -> 随机删除一个键(范围:设置了生存时间的键)
    • allkeys-random -> 随机删除一个键(范围:所有键)
    • volatile-ttl -> 删除生存时间最近的一个键
    • noeviction -> 不删除,直接在写操作时返回错误(默认)

一般使用 volatile-lru 和 allkeys-lru 算法居多,LRU 是最近最久未使用算法。但它不是精准的 LRU 算法。

实际上,redis 为了节省内存,使用了 合适的LRU 算法。具体实现是:采样5个 key,通过 LRU 算法获得最近最久未使用的 key 并回收。采样大小可通过 maxmemory-samples 调整,默认是5.

注意:设置了 key 回收策略,不代表不会报错。当没有合适的 key 回收时,redis 同样会返回错误。

4 写在最后

服务器出现了崩溃,定位错误为 redis 的 set 操作。解决方案则是:增大 redis 内存上限或者设置 key 回收策略。

实际上,错误背后反应的是 redis 的内存管理机制。而除了 key 回收,redis 内存管理还有过期删除机制。其内部实现使用的是惰性删除和定期删除。(不在本文讨论范围内,有时间会另写一篇文章~)

随着 redis 使用的深入,其背后的原理面纱也一层层揭开。Daemon 的心得是:结合实际遇到的问题,再针对性的查看原理性知识,成长会更快~

大家如果有什么疑问或者其他任何事情,欢迎添加 Daemon 的个人微信号交流~

查看redis缓存大小_一个 bug 引发了服务器崩溃,对应 redis 的 key 回收原理你清楚了吗?...相关推荐

  1. std::uniform_real_distribution的一个bug引发的服务器崩溃

    文章目录 前言 崩溃问题 std::uniform_real_distribution<> 的bug bug 重现方法 总结 前言 近日发生一次线上游戏服务器宕机问题,通过日志和core文 ...

  2. 『转』度百死去飞秋一个BUG引发的血案

    作了一篇文章度百死去飞秋一个BUG引发的血案,昨天,度百死去的美国客户发邮件给我,说我的软件出问题了,我查来查去,发现居然是服务器上一个目录无法删除,一删除就报 cannot read from th ...

  3. 计算一个image的大小_一个方案提升Flutter内存利用率(干货)

    简介:拿什么拯救你,flutter内存 作者:闲鱼技术--靖书 背景 我们闲鱼使用的图片方案是自研的外接纹理方案: Android侧创建SurfaceTexture,通过FlutterJNI注册到Fl ...

  4. linux查看cpu缓存大小,如何在Linux中获取CPU Cache的大小

    对于运行Linux的ARM CPU(在具有Raspbian(32位)的Raspberry Pi 3B +上测试): "Arm®Cortex®-A53MPCore处理器技术参考手册" ...

  5. 修改console缓存大小_更改缓存的行大小将如何影响其他参数?

    修改console缓存大小 Prerequisites: Memory mapping and its types 先决条件: 内存映射及其类型 While designing a cache sys ...

  6. 查看mysql缓存命中_【转】MySQL如何检查缓存命中

    MySQL如何检查缓存命中 MySQL如何检查缓存命中 How MySQL Checks for a Cache Hit MySQL检查缓存命中的方式相当简单快捷.缓存就是一个查找表(Lookup T ...

  7. redis存储图片_一不小心肝出了4W字的Redis面试教程

    本文脑图 redis基本数据结构 本文脑图 前言 Redis是基于c语言编写的开源非关系型内存数据库,可以用作数据库.缓存.消息中间件,这么优秀的东西客定要一点一点的吃透它. 这是关于Redis五种数 ...

  8. redis缓存路由为空_Springboot使用RedisTemplate优雅地操作redis

    作者:Jantihttp://cnblogs.com/superfj/p/9232482.html 概述 本文内容主要 关于spring-redis 关于redis的key设计 redis的基本数据结 ...

  9. .net Redis缓存优化提高加载速度和服务器性能(二)

    上文详细测试了每次都读取数据库的接口和通过缓存读取接口的性能对比 这里我们就准备实际简介肿么将原来的数据库加上Redis缓存优化部分接口 1.下载Redis和Redis视图管理工具 点击下载 提取码: ...

最新文章

  1. 18 Java面试之 Oracle 和 Mysql 数据库
  2. LINQ TO ENTITY 根据Birthday获取Age
  3. mysql keepalived主主同步_KEEPALIVED+MYSQL主主同步=MYSQL高可用(HA)集群
  4. 经济和信息化谋定研究-左晓栋:国家网络安全事件应急预案
  5. PHP——大话PHP设计模式——SPL数据结构
  6. Collection和Map中易考的一些知识点
  7. python集合数据对象_python学习第七天 基础数据类型补充 深浅copy 集合 关键字后面加可迭代对象...
  8. 为什么我的JVM访问的内存少于通过-Xmx指定的内存?
  9. (95)Vivado时序约束TCL命令-all
  10. canvas drawbitmap不出现_JS实现简单的画板(canvas),可在PC和移动端实现。
  11. Java基础学习总结(38)——Lombok(消除冗长的 java 代码)的使用和原理及安装、入门使用
  12. Solaris 图形化界面登陆的控制
  13. hdu 6118 最小费用可行流(注意与最大流的区别)
  14. Linux SOCKET编程详解
  15. linux vim替换指定字符串
  16. 基于AT89S52单片机的GPS液晶显示定位系统
  17. 高级前端面试100问(必会)
  18. 计算机怎么设置加密文件,电脑文件夹怎么设置密码 电脑文件夹加密的3种方法...
  19. 【C++】C++入门
  20. 电脑系统坏了怎么修复

热门文章

  1. 完成users中的models
  2. HTML5----简易贪吃蛇小游戏
  3. 图片点击放大并可点击旋转插件(1)-jquery.artZoom.js
  4. Intellij idea generate builder 插件-用于自动生成builder模式代码
  5. Swift - 做一个简单的无线U盘(手机端Http服务器搭建)
  6. elasticsearch hbase
  7. TikTok时代细分需求 牛逼亚马逊运营团队打造新爆款
  8. AD不能复制提示目标主要名称不正确
  9. Go语言Flag的简单示例
  10. ListListObject list = new ArrayListListObject(); 求回答补充问题 list.get(position).add(Object);为什么会...