Redis

1、缓存穿透

查询一个不存在的数据,mysql查询不到数据也不会直接写入缓存,就会导致每次请求都查数据库

解决方法:

  • 缓存空数据,查询返回的数据为空,仍把这个空结果进行缓存。{key:1, value:null}
  • 使用布隆过滤器

2、缓存击穿

给某一个key设置了过期时间,当key过期的时候,恰好这时间点对这个key有大量的并发请求过来,这些并发的请求可能会瞬间把DB压垮

解决方法:

  • 使用互斥锁,强一致,性能差,让其中一个线程获取锁并访问数据库加载数据并缓存,其他线程获取不到锁便重试获取缓存,获取到锁的线程则会加载数据到缓存中

  • 逻辑过期,高可用,性能优,不能保证数据绝对一致。设置当前key逻辑过期
    • 在设置key的时候,设置一个过期时间字段一块存入缓存中,不给当前key设置过期时间
    • 当查询的时候,从redis取出数据后判断时间是否过期
    • 如果过期则开通另外一个线程进行数据同步,当前线程正常返回数据,这个数据不是最新

3、缓存雪崩

缓存雪崩是指在同一时段大量的缓存key同时失效或者Redis服务宕机,导致大量请求到达数据库,带来巨大压力。

解决方法:

  • 给不同的Key的TTL添加随机值
  • 给缓存业务添加降级限流策略

4、先删除缓存,还是先修改数据库

4.1、先更新缓存,再更新数据库

原因是更新缓存成功后,数据库可能更新失败,出现数据库为旧值,缓存为新值,导致数据库与缓存数据不一致

4.2、先更新数据库,再更新缓存

数据库更新成功,缓存更新失败,导致数据库与缓存数据不一致。

4.3、先删缓存,再更新数据库

当线程A已经删除了缓存,但还没有更新DB时。

线程B来了,看缓存里面没有,就会去数据库读数据,创建缓存,这时B读取到的还是数据库里面的旧值。后续所有读取的线程都是读到缓存中的旧值。

4.4、缓存延时双删

先删缓存,再更新数据库,然后过一段时间再删除缓存

这个方案可以避免旧的数据被回种,相当于如果线程B将旧的数据给回种到缓存了,

A线程延迟一段时间,又给缓存里面的数据删掉了。从而保证后面的读取线程能读到最新的值。

缺点:
过多长时间再删除缓存,这个时间不好控制,过短或者过长,都有可能造成数据不一致的问题

4.5、先更新数据库,再删除缓存

先修改数据库的信息,然后再删除对应的缓存,在修改数据库期间,可以允许一定时间的缓存

不一致(修改数据库到删除缓存这段时间,缓存里面还是旧的数据,其它请求能读到旧数据,

数据库与缓存数据不一致)。

保证数据的最终一致性。

用户体验比先删除缓存后更新数据库要好点:

在“先删除缓存,再更新数据库”的情况下,如果数据库更新失败,用户可能会一直看到旧数

据,直到缓存过期。相比之下,“先更新数据库,再删除缓存”可以在某种程度上避免这种情

况。

也存在不一致性的问题:

1.当数据库的数据被更新后,缓存也被删除。接下来的出现读请求1和写请求2同时进来。

读请求先读了缓存发现缓存无命中,则查询数据库并在准备更新缓存时,2写请求已经完成了

数据的更新和删除缓存的动作,之后1这个读请求才更新了缓存。最后导致了数据库中的值为

新值,缓存中的值为旧值。

2.数据库更新成功,删除缓存失败,也会导致数据库与缓存不一致。

4.6、先更新数据库,通过binlog,异步更新缓存

数据库的更新操作都会记录到binlog里面,可以通过阿里开源的框架canal监听binlong,得到具体要操作的数据之后,再执行删除缓存,删除的时候,借助消息队列,如果删除失败的话,可以进行重试

4.7、加锁

读的时候,加共享锁
写的时候,加排他锁

5、Redis持久化

在Redis中提供了两种数据持久化的方式:1.RDB 2.AOF

还有一种是RDB,AOF混合式

5.1、RDB

RDB全称Redis Database Backup file(Redis数据备份文件),也被叫做Redis数据快照。简单来说就是把内存中的所有数据都记录到磁盘中。当Redis实例故障重启后,从磁盘读取快照文件,恢复数据。

Redis的配置文件中有设置触发RDB的机制

bgsave开始时会fork主进程得到子进程,子进程共享主进程的内存数据。完成fork后读取内存数据并写入 RDB 文件。fork采用的是copy-on-write技术:

  • 当主进程执行读操作时,访问共享内存;
  • 当主进程执行写操作时,则会拷贝一份数据,执行写操作。

5.2、AOF

AOF全称为Append Only File(追加文件)。Redis处理的每一个写命令都会记录在AOF文件,可以看做是命令日志文件。

AOF默认是关闭的,需要修改redis.conf配置文件来开启AOF:

AOF的命令记录的频率也可以通过redis.conf文件来配:

Redis也会在触发阈值时自动去重写AOF文件。阈值也可以在redis.conf中配置:

5.3、RDB和AOF对比

5.4、RDB,AOF混合式

首先Redis会以AOF的形式去记录数据,当达到重写的阈值后会将前面写入的AOF格式的数据重写成RDB快照二进制数据,而后续写入的命令依旧是AOF形式,直到下一次阈值触发时,这部分AOF数据才会重写成RDB格式的数据

优点:继承了RDB恢复数据快的优势,也继承了AOF在宕机时数据丢失最少的优势

6、Redis过期策略

Redis的键到期后过期后如何删除可通过策略去设置

6.1、惰性删除

设置该key过期时间后,我们不去管它,当需要该key时,我们在检查其是否过期,如果过期,我们就删掉它,反之返回该key

6.2、定期删除

每隔一段时间,我们就对一些key进行检查,删除里面过期的key(从一定数量的数据库中取出一定数量的随机key进行检查,并删除其中的过期key)。

7、Redis数据淘汰策略

当Redis中的内存不够用时,此时在向Redis中添加新的key,那么Redis就会按照某一种规则将内存中的数据删除掉,这种数据的删除规则被称之为内存的淘汰策略。

Redis支持8种不同策略来选择要删除的key:

  • noeviction: 不淘汰任何key,但是内存满时不允许写入新数据,默认就是这种策略
  • volatile-ttl: 对设置了TTL的key,比较key的剩余TTL值,TTL越小越先被淘汰
  • allkeys-random:对全体key ,随机进行淘汰
  • volatile-random:对设置了TTL的key ,随机进行淘汰
  • allkeys-lru: 对全体key,基于LRU算法进行淘汰
  • volatile-lru: 对设置了TTL的key,基于LRU算法进行淘汰
  • allkeys-lfu: 对全体key,基于LFU算法进行淘汰
  • volatile-lfu: 对设置了TTL的key,基于LFU算法进行淘汰

LRULeast Recently Used)最近最少使用。用当前时间减去最后一次访问时间,这个值越大则淘汰优先级越高

LFULeast Frequently Used)最少频率使用。会统计每个key的访问频率,值越小淘汰优先级越高

LRU:key1是在3s之前访问的, key2是在9s之前访问的,删除的就是key2

LFU:key1最近5s访问了4次, key2最近5s访问了9次, 删除的就是key1

8、分布式锁实现

redis分布式锁主要依赖于 setnx key values 这个命令,如果存在key则无法添加(锁被占用),如果不存在key则添加(获得锁),删除key(释放锁)。

设计锁案例


已发布

分类

, , ,

来自

标签:

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注