前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >线上问题 | Redis哈希结构踩坑

线上问题 | Redis哈希结构踩坑

作者头像
编程大道
发布于 2023-03-17 04:36:57
发布于 2023-03-17 04:36:57
5020
举报
文章被收录于专栏:编程大道编程大道

背景

休假期间收到公司同事的信息说系统日志有大量的报错,且收到邮件告警。

同事排查不到原因,迫不得已联系到正在休假的我。幸亏我带着电脑呢!(打工人的觉悟真高,休假都带着电脑)于是我打开电脑,连上V**,连接远程桌面,登录日志系统,查看一番,又翻了翻代码,发现是因为从Redis中查询的数据为字符串null(这种情况是Redis中不存在且数据库也不存在时,避免缓存穿透而临时缓存的字符串null),导致抛出业务异常,打印错误日志,从而触发邮件告警。接口调用量一上来,报错就多了,于是就收到了千余封告警邮件。

由于我在休假,所以告诉同事几个排查思路,去看看Redis为啥为空(正常情况下,这种配置数据应该是在数据库中的)。

解决

于是同事最后找到了原因,是因为数据库未初始化相应数据(上线了新接口,需要增加配置,新人忘记加了),然后紧急修复了一下。

但是修复后,接下来的国庆假期,每天还是会收到上千封告警邮件(缓存的接口开关数据,且实际为关,不影响实际业务),于是同事在值班邮件中写道:xx月xx日已修复,但缓存中为空,缓存设置了过期时间,到期会自动清除,同步数据库中数据后即不再报错。于是大家都不再关注这个问题了。

再现

细心的我发现到了过期时间之后,还是会报相应的错,还是会每天收到告警邮件,为什么呢?不是设置了过期时间吗?空值咋还在缓存中呢?

首先我们排除了数据库查不到数据的嫌疑,我们确保按线上SQL的查询条件能够查到数据。其次,我们查询了key的过期时间,换算一下还有4天过期,经过推算,从缓存null值开始计算,三天前就该过期了,为啥现在查还是4天呢?

继续排查

我们排查了代码,发现该缓存key使用的是Redis哈希结构,field是不同的用户id,value是对应的数据库记录,并设置了过期时间5天。乍一看没什么问题,但是仔细再看看,发现了猫腻。

当从Redis执行hget无法获取到数据时,会查数据库然后执行hset将用户id和对应的数据缓存,并设置过期时间为5天。原因就在这,每次执行hset时都设置过期时间,这样就导致缓存可能很久才会过期,因为过期时间可能会一直被重置。

举个例子,最初哈希无数据,用户1查询后缓存了用户1,设置5天过期,当快过期时,用户2又来查询然后缓存用户2的数据,设置5天过期,那么此时用户1的数据过期时间相当于又被重置为了5天。以此类推,最坏的情况就是,用户1的数据在哈希key每次快过期时都被重置过期时间,那么用户1的数据将会缓存(N+1)*5天才过期。即,直至所有用户数据都在哈希中且再过5天后整个hash数据才被清除。

为了验证这个观点,我们又执行了一次ttl命令,发现这次过期时间换算后为4.9天,再结合日志,发现确实有新的field被缓存!于是证实了上述猜想!

最终解决

到此,问题原因已经排查到。剩下的就是解决,思路就是:

首先删除缓存为null的field,让业务先正常走下去。为了仅提交一次工单一次性全部删除,我们排查了有多少这样的field(缓存为null但数据库有值),一次性处理完。

其次优化代码。目前存在的问题是可能导致缓存为字符串null的数据很久很久都不过期。优化方案:执行hset后判断key没有设置过期时间,再执行expire,防止过期时间被覆盖。

总结一下

问题原因:

1.数据库未初始化数据,导致缓存了null字符串,抛出业务异常导致告警

2.缓存过期时间一直被重置,导致缓存一直不刷新

3.修复问题时仅为数据库初始化数据,未主动清缓存

解决办法:

  1. 判断key设置过过期时间不再重复设置

感悟:

  1. 解决线上问题要严谨,不要只解决一半

至此,本次问题排查并解决完毕,这个坑你遇到过吗?希望对你有帮助!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-10-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 BiggerBoy 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Redis面试题总结(超详细)
针对以上的问题,Redis集群提供了较为完善的方案,解决了存储能力受到单机限制,写操作无法负载均衡的问题。
是阿超
2021/11/10
4.2K0
《Redis常见问题》带刚接触nosql的你解决Redis经典问题
一个一定不存在缓存及查询不到的数据,由于缓存是不命中时被动写的,并且出于容错考虑,如果从存储层查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到存储层去查询,失去了缓存的意义。 (1) 对空值缓存:如果一个查询返回的数据为空(不管是数据是否不存在),我们仍然把这个空结果(null)进行缓存,设置空结果的过期时间会很短,最长不超过五分钟
冷环渊
2021/10/19
5420
Redis中缓存雪崩、缓存穿透等问题的解决方案
缓存雪崩是指缓存同一时间大面积的失效,所以,后面的请求都会落到数据库上,造成数据库短时间内承受大量请求而崩掉。
码农编程进阶笔记
2021/07/20
8280
颠覆认知——Redis会遇到的15个「坑」,你踩过几个?
如果你在使用 Redis 时,也遇到过以下这些「诡异」的场景,那很大概率是踩到「坑」了:
JAVA日知录
2021/04/07
1K0
颠覆认知——Redis会遇到的15个「坑」,你踩过几个?
Redis核心知识点
​ RedisTemplate底层默认使用JDK序列化来将key和value输出为字节数组:
大忽悠爱学习
2023/02/13
4610
Redis核心知识点
深入剖析Redis系列:Redis数据结构之哈希
大部分编程语言都提供了 哈希(hash)类型,它们的叫法可能是 哈希、字典、关联数组。在 Redis 中,哈希类型 是指键值本身又是一个 键值对结构。
用户5546570
2019/06/06
1K0
深入剖析Redis系列:Redis数据结构之哈希
redis的穿透&雪崩
缓存穿透是指查询一个一定不存在的数据(比如连mysql都没得数据,Redis怎么也查不到啊),由于缓存是不命中时被动写的,并且出于容错考虑,如果从存储层查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到存储层去查询,失去了缓存的意义。 在流量大时,可能数据库就挂掉了,要是有人利用不存在的key频繁攻击我们的应用,这就是漏洞。
名字是乱打的
2022/05/13
2610
redis的穿透&雪崩
Redis详解
    1.Redis 是一个基于内存的高性能 key-value 数据库。是完全开源免费的,用C语言编写的,遵守BSD协议
忧愁的chafry
2022/10/30
1.3K0
Redis详解
Redis讲解以及测试要点
redis适合放一些频繁使用,比较热的数据,因为是放在内存中,读写速度都非常快,一般会应用在下面一些场景,排行榜、计数器、消息队列推送、好友关注、粉丝。
互联网金融打杂
2018/12/27
1.4K0
经常用Redis,这些坑你知道吗?
作者简介:曾任职于阿里巴巴,每日优鲜等互联网公司,任技术总监,15年电商互联网经历。
用户7927337
2020/11/04
4260
经常用Redis,这些坑你知道吗?
redis学习之redis应用(四)
Redis Java客户端有很多的开源产品比如Redission、Jedis、lettuce
周杰伦本人
2022/10/25
4770
redis学习之redis应用(四)
redis笔记第一次课
背景:早起的网站使用的都是单机版MySQL,不需要考虑太多的数据量问题;目前大数据时代,数据量急增,单机版数据库就出现了瓶颈:
张哥编程
2024/12/13
880
Redis:09---Hash对象
hsetnx:它们的关系就像set和setnx命令一样,只不过作用域由键变为field
用户3479834
2021/02/03
1K0
Redis:09---Hash对象
redis 知识总结
willsonchen
2024/01/25
2210
面试官:熟悉Redis?请讲讲Redis缓存穿透、缓存击穿、缓存雪崩有什么区别
参加过面试的同学们都应该知道,Redis常见面试题:Redis缓存穿透、缓存击穿、缓存雪崩是面试官最最最最常问的问题之一,搞懂这几个名词之间的区别无疑会为你的面试过程增光添彩,接下来就这几个点进行详述。
百思不得小赵
2022/12/01
5140
面试官:熟悉Redis?请讲讲Redis缓存穿透、缓存击穿、缓存雪崩有什么区别
Redis 缓存优化:提升应用性能的不二选择
在现代的软件开发中,性能一直是开发者们追求的目标之一。对于数据库访问频繁、数据读取较慢的场景,使用缓存是提升性能的有效手段之一。而 Redis 作为一款高性能的内存数据库,被广泛用作缓存工具。本文将围绕 Redis 缓存优化进行详解,为你揭示如何通过优化缓存提升应用性能的奥秘。
繁依Fanyi
2023/12/29
5060
《Java面试题集中营》- Redis
单线程能够避免线程切换和竞态产生的消耗,而且单线程可以简化数据结构和算法的实现 至于单线程还快,是因为Redis是基于内存的数据库,内存响应速度是很快的,并且采用epoll作为I/O多路复用技术,再加上Redis自身的事件处理模型将epoll中的连接、读写、关闭都转换为事件,不在网络I/O上浪费过多时间
阿提说说
2024/09/06
1140
《Java面试题集中营》- Redis
缓存之Redis了解及使用
redis是一种支持Key-Value等多种数据结构的存储系统。可用于缓存,事件发布或订阅,高速队列等场景。该数据库使用ANSI C语言编写,支持网络,提供字符串,哈希,列表,队列,集合结构直接存取,基于内存,可持久化。
sucl
2019/08/07
5470
缓存之Redis了解及使用
Redis进阶-Redis缓存优化
查询一个根本不存在的数据, 缓存和DB都不会命中, 白嫖了缓存层和DB 。 通常出于容错的考虑, 如果从存储层查不到数据则不写入缓存层。
小小工匠
2021/08/17
1.3K0
Redis数据库
MySQL的缓存系统就可以胜任大部分的数据存储工作。但是MySQL的数据始终是存储在硬盘上的,如果是快速更新或是频繁使用的数据,MySQL的磁盘IO读写性能完全不能满足上面的需求,能够满足上述需求的只有内存,因为速度远高于磁盘IO。
用户9645905
2023/11/07
2260
Redis数据库
相关推荐
Redis面试题总结(超详细)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档