Redis 学习笔记
Redis是非关系型的键值对数据库,数据是存储在内存中的,读写速度很快,广泛用于缓存方向,也可用于数据库的持久化。
MySQL是关系型的磁盘数据库。访问Redis的速度要更快一点,但受限于内存的大小,Redis不能用作海量数据的读写。
Redis优点
- 数据类型丰富,字符串String、哈希Hash、列表List、集合Set/有序集合sorted set
- 丰富的特性,支持发布订阅 通知 key过期等功能
- 读写速度快
- 支持持久化
Redis使用场景
数据缓存
缓存是Redis最常用的场景,因为其读写速度快,是高性能的内存数据库。
Redis作为缓存使用时:业务先从Redis拿数据,如果没有,再去数据库中拿数据,将数据库中的数据缓存到Redis中;业务更新数据时,会直接修改数据库中的数据,然后将Redis中旧的记录删除。
由于修改数据库后,Redis中还会保留一段时间的旧记录,所以这种模式的实时性较低。
避免缓存击穿
限时业务
Redis支持给key设置过期时间,客户端无法访问到过期的key,利用这一特性可以运用在限时的优惠活动、手机验证码等场景。
计数器
Redis中的INCRBY 命令可以实现原子性的递增,可以直接作为计数器存储和递增。 高并发的秒杀活动、分布式序列号的生成、限制手机发送短信次数等需要计数的功能都会需要用到计数器的概念。
分布式锁
排行榜功能
通过Redis的SortedSet可以实现排行榜功能。
延时队列
异步队列
缓存使用的三种特殊场景
使用缓存通常是为了 1. 提高响应速度和并发量 2. 减轻数据库的压力
缓存穿透
通常的访问流程是 :业务请求打过来,先去检查缓存,看是否有对应的数据,如果没有,再去数据库中检索对应的数据。如果数据库中有对应的数据,则先更新缓存并返回结果。如果数据库中也没有对应的数据,则返回空或者错误,不会更新缓存。
缓存穿透问题: 如果每次查询的数据都不在缓存中,就都会直接去访问数据库,缓存失去了其应有的功能。当有大量的这样的请求(访问不存在的key)或者有人恶意利用不存在的key进行访问攻击时,数据库的压力急剧增大,甚至崩溃。
缓存穿透发生的场景一般有两类:
- 本来存在的数据因为误删的操作导致在缓存和数据库层面没有了,但是前端或前置的应用程序依旧保有这些数据;
- 有人恶意攻击。
解决方案:
- 对于不存在的key,可以设置其value为null或者默认值。 当访问到缓存和数据库都不存在的key时,可以将其缓存为null或者默认值。针对空值的缓存时间不宜过长,当数据库更新时,缓存也要及时的得到更新,避免数据不一致。 思考: 当高并发访问的是不同的不存在的key的话,依然会给数据库造成大的压力。
- 业务逻辑前置校验。在业务请求的入口处就对请求参数进行 合法性校验,过滤掉一些明显不合法的情况以及恶意请求的情况等。提前有效阻断非法请求。
- 使用布隆过滤器请求白名单。 布隆过滤器是用来判断一个元素是否在一个集合中的,优点是空间效率和查询时间都比一般的算法要好的多,缺点是有一定的误识别率和删除困难。在业务请求的数据不在缓存中时,先通过布隆过滤器判断数据是否在白名单中,如果不在白名单内,则直接返回空/失败。
缓存雪崩
缓存中的key是有时效性的,通常是为了保持缓存和数据库数据的一致性,另一方面减少冷缓存占用过多的内存空间。
缓存雪崩: 当缓存中大量的热点数据在某一时刻同时失效,导致大量请求全部转发到数据库,从而导致数据库压力骤增,进而形成一系列的连锁反应导致服务器崩溃。
缓存雪崩发生的场景一般有两类:
- 大量热点数据同时失效
- 缓存服务故障
解决方案有多种:
- 在设置key的过期时间时,给每个key的过期时间后面加上一个随机数,让key均匀的失效。
- 热点数据可以考虑不失效,后台异步更新缓存,适用于不严格要求缓存一致性的场景。
- 考虑使用队列或者锁的方式,保证缓存单线程写,但这种方案可能会影响并发量。
- 构建缓存高可用集群,我理解的就是加机器
- 双key策略,主key设置过期时间,备key不设置过期时间,当主key失效时,直接返回备key值,存储重复数据会导致内存占用。
缓存击穿
缓存雪崩指的是多个热点数据失效。缓存击穿指的是 单个热点数据被高并发的访问,当这个热点数据失效时,大量请求击穿缓存,直接打到数据库,造成数据库压力骤增,甚至崩溃等。
缓存击穿的解决方案:
- 使用互斥锁,只让一个线程构建缓存,其他线程等待缓存构建完毕后,直接访问缓存数据。 就是说虽然是高并发访问,但是只有一个线程能去访问数据库更新缓存,其他线程就等着就行。
- 热点数据不设置过期时间,异步更新缓存数据。
- “提前”使用互斥锁:在value内部设置一个比缓存过期时间更短的过期时间标识,当异步线程发现该值快过期时,马上延长内置的这个时间,并从数据库加载数据,更新缓存。
总结
总的来讲,缓存穿透、缓存雪崩和缓存击穿都是因为在访问缓存的时候没有访问到对应的数据,从而去访问数据库,将流量直接打到了数据库层面。 其中,缓存穿透是因为访问的数据不存在,缓存雪崩和缓存击穿都是因为缓存数据失效。解决这些问题的方案有多种,要具体问题具体分析。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 【.NET】调用本地 Deepseek 模型
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库