目录
Redis作为缓存
1.什么是缓存?
缓存 (cache) 是计算机中的⼀个经典的概念. 在很多场景中都会涉及到。
核⼼思路就是把⼀些常⽤的数据放到触⼿可及(访问速度更快)的地⽅, ⽅便随时读取。
对于计算机硬件来说, 往往访问速度越快的设备, 成本越⾼, 存储空间越⼩.
缓存是更快, 但是空间上往往是不⾜的. 因此⼤部分的时候, 缓存只放⼀些 热点数据 (访问频繁的数据),就⾮常有⽤了。
众所周知,咱们日常使用的关系型数据库比如MySQL是非常“娇嫩”的,操作他比起操作缓存是非常耗时的,而且很容易在一瞬间遭受到大量数据操作时,因忙不过来而宕机,数据库很多时候直接成为了整个程序的性能瓶颈。为了给MySQL减少压力,提高程序的效率和稳定性,业内通常使用Redis作为MySQL的缓存,这样就能大大减少MySQL的压力,提高程序性能和稳定性。
2.缓存的更新策略
接下来还有⼀个重要的问题, 到底哪些数据才是 "热点数据" 呢?
对于热点数据的挑选一般有两种方式:
- 定期生成
- 实时生成
定期生成:
每隔⼀定的周期(⽐如⼀天/⼀周/⼀个⽉), 对于访问的数据频次进⾏统计. 挑选出访问频次最⾼的前 N%的数据。
实时生成:
先给缓存设定容量上限(可以通过 Redis 配置⽂件的 maxmemory 参数设定).
接下来把⽤⼾每次查询:
- 如果在 Redis 查到了, 就直接返回.
- 如果 Redis 中不存在, 就从数据库查, 把查到的结果同时也写⼊ Redis.
如果缓存已经满了(达到上限), 就触发缓存淘汰策略, 把⼀些 "相对不那么热⻔" 的数据淘汰掉.
按照上述过程, 持续⼀段时间之后 Redis内部的数据⾃然就是 "热⻔数据" 了。
常用的缓存淘汰策略主要有以下几种:
- FIFO (First In First Out) 先进先出 :把缓存中存在时间最久的 (也就是先来的数据) 淘汰掉.
- LRU (Least Recently Used) 淘汰最久未使⽤的 :记录每个 key 的最近访问时间. 把最近访问时间最⽼的 key 淘汰掉.
- LFU (Least Frequently Used) 淘汰访问次数最少的 :记录每个 key 最近⼀段时间的访问次数. 把访问次数最少的淘汰掉.
- Random 随机淘汰 :从所有的 key 中抽取幸运⼉被随机淘汰掉
3.缓存预热,缓存穿透,缓存雪崩和缓存击穿
缓存预热
什么是缓存预热?
缓存穿透
什么是缓存穿透?
因为什么产生?
如何解决?
缓存雪崩
什么是缓存雪崩?
为何产⽣?
如何解决?
缓存击穿
什么是缓存击穿?
如何解决?
Redis作为分布式锁
1.什么是分布式锁?
在⼀个分布式的系统中, 也会涉及到多个节点访问同⼀个公共资源的情况. 此时就需要通过 锁 来做互斥控制, 避免出现类似于 "线程安全" 的问题.
⽽ java 的 synchronized 或者 C++ 的 std::mutex, 这样的锁都是只能在当前进程中⽣效, 在分布式的这种多个进程多个主机的场景下就⽆能为力了。
2.分布式锁的实现过程
1.首先我们可以使用Redis的键值对功能进行简单的加锁功能。
2.在上述加锁过程中我们可以引入过期时间。
3. 对于Redis写入的加锁键值对,其他节点也是可以删除的,此时我们需要引入校验id。
4.引入Redis的Lua脚本功能是锁操作具有原子性。
5.引入watch dog(看门狗)使过期时间更准确。
6.引入Redlock算法,使用Redis集群参与分布式锁。
Redlock 算法的核⼼就是, 加锁操作不能只写给⼀个 Redis 节点, ⽽要写个多个!! 分布式系统中任何⼀个节点都是不可靠的. 最终的加锁成功结论是 "少数服从多数的"。
由于⼀个分布式系统不⾄于⼤部分节点都同时出现故障, 因此这样的可靠性要⽐单个节点来说靠谱不少.