Skip to content

基础

事物

支持事务, Redis的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过MULTI和EXEC指令包起来。

命令

  • setnx key value:只在 key 不存在的时候将值设为 value

分布式锁

  • redisson

优化:

  • 分段锁:Hash 运算 分段锁,或者商品id锁

存在问题:

  • 主从架构可能会存在主节点数据未同步从节点导致锁重复
    • redlock
    • zookeeper:CP一致性 数据同步时会段时间不可用

缓存淘汰

内存是有限的,如果有新的 key 进入内存不够,则需要淘汰部分缓存

  1. FIF0:先进先出,淘汰最先进入缓存的数据

  2. LRU:最近最少未使用

    1. LRU实现方法,这里给出其中一种实现思路:双向链表+哈希表的形式存储。
    2. 双向链表用于组织数据,数据采用链表节点进行组织,最经常访问的排在前面,哈希表用于存储键key和值链表节点
    3. 每次访问都会被移动也会浪费性能,所以引入 LRU-K

  1. LFU:最近不经常使用

过期删除

  1. 主动删除:设置删除间隔时间,在指定时间后进行主动删除工作
    1. 优点:易于理解,设置合理的间隔后不会使内存占用超标
    2. 缺点:当 Redis 比较忙时,设置删除时间碰巧到期了,主动删除会额外增加 Redis 负担。
  2. 惰性删除:当用到这个缓存,在检测它的过期时间,程序取值时查看该数据是否已经过期,如果没过期,则返回,如果过期,则删除
    1. 优点:服务器运算资源占用小
    2. 缺点:容易造成某些数据长期霸占在内存中,不被删除的情况。
  3. 定期删除=主动删除+惰性删除
    1. 每隔一段时间,跑主动删除,不跑主动删除时,执行惰性删除策略。

缓存一致

Cache Aside 的核心思想就是,当缓存的数据有更新值了,它采用的不是更新缓存数据,而是删除缓存数据

保证最终一致性

  1. 先删除在更新数据,但是这样其它线程如果速度足够快还是会读到脏数据,这个时候可以采用延迟双侧删除策略

  1. Read/Wite Through

  1. Writer behind

缓存击穿

查询某个数据的值,该值在缓存中无,在数据库中有

  1. 一般缓存都会设置个数据过期时间,所以缓存击穿的情况比较常见
  2. 缓存击穿带来的问题:如果对该值查询突然特别大,由于缓存中无该数据,所以请求就会打到后端数据库上
  3. 处理
    1. 从MySQL角度出发:减少击穿后的直接流量

  • 从Redis角度出发:
    • 设置热点数据永不过期
    • 热点数据后台启动一个异步线程,重新把数据回填缓存层

缓存穿透

查询一个数据库也不存在的数据,即缓存查不到,数据库也查不到所以透了

  1. 拦截非法查询请求
  2. 缓存空对象
  3. 布隆过滤器
    1. 设计思路:设计k个hash映射函数,这k个映射函数各不相同,把在数据库中的有效数据通过这个映射函数得到数组指定位置,并置为1
    2. 查询思路:输入查询数据,通过这一系列hash函数,判断对应位置是否全为1。如果是,则很大概率就是我们的有效请求了,如果有一位为0,则该查询一定是无效查询
    3. 提前查询数据库做一个布隆表

缓存雪崩

一大批被缓存的数据,同时失效,此时对于这一批的数据请求就全打到数据库上,导致数据库宕机

和缓存击穿类似

  1. 从MySQL角度出发

  1. redis
    1. 设置热点数据永不过期
    2. 分析失效时间,尽量让失效时间点分散
    3. 缓存预热,即在上线前,根据当天的情况分析,将热数据直接加载到缓存系统