RSS

Redis 缓存

缓存问题

Redis 高可用,主从+哨兵,Redis cluster,避免全盘崩溃

本地 ehcache 缓存 + hystrix 限流&降级,避免 MySQL 被打死

缓存穿透

缓存穿透是指用户请求的数据在缓存中不存在即没有命中,同时在数据库中也不存在,导致用户每次请求该数据都要去数据库中查询一遍,然后返回空

  1. 布隆过滤器

布隆过滤器(Bloom Filter,简称BF),是一种空间效率高的概率型数据结构,用来检测集合中是否存在特定的元素

布隆过滤器由一个长度为m比特的位数组(bit array)与k个哈希函数(hash function)组成的数据结构。位数组初始化均为0,所有的哈希函数都可以分别把输入数据尽量均匀地散列。当要向布隆过滤器中插入一个元素时,该元素经过k个哈希函数计算产生k个哈希值,以哈希值作为位数组中的下标,将所有k个对应的比特值由0置为1

当要查询一个元素时,同样将其经过哈希函数计算产生哈希值,然后检查对应的k个比特值:如果有任意一个比特为0,表明该元素一定不在集合中;如果所有比特均为1,表明该集合有可能性在集合中(哈希碰撞)

  1. 返回空对象

当缓存未命中,查询持久层也为空,可以将返回的空对象写到缓存中。为了避免存储过多空对象,通常会给空对象设置一个过期时间

缓存击穿

缓存击穿,是指一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库

  1. 使用互斥锁(mutex key)

让一个线程回写缓存,其他线程等待回写缓存线程执行完,重新读缓存

  1. 热点数据永不过期

针对热点key不设置过期时间,或者把过期时间存在key对应的value里,如果发现要过期了,通过一个后台的异步线程进行缓存的构建

缓存雪崩

缓存雪崩是指缓存中数据大批量到过期时间,而查询数据量巨大,请求直接落到数据库上

  1. 均匀过期 设置不同的过期时间,让缓存失效的时间点尽量均匀。通常可以为有效期增加随机值或者统一规划有效期
  2. 双层缓存策略
  3. 加互斥锁
  4. 缓存永不过期

缓存预热

缓存预热就是系统上线后,将相关的缓存数据直接加载到缓存系统

缓存降级

缓存降级是指缓存失效或缓存服务器挂掉的情况下,不去访问数据库,直接返回默认数据或访问服务的内存数据

Redis的内存淘汰机制

maxmemory 0,在64位操作系统下最大内存为操作系统剩余内存

淘汰策略

  1. noeviction 默认策略,对于写请求直接返回错误,不进行淘汰
  2. allkeys-lru 从所有的key中使用近似LRU算法(最近最少使用)进行淘汰
  3. volatile-lru 从设置了过期时间的key中使用近似LRU算法进行淘汰
  4. allkeys-random 从所有的key中随机淘汰
  5. volatile-random 从设置了过期时间的key中随机淘汰
  6. volatile-ttl 在设置了过期时间的key中根据key的过期时间进行淘汰,越早过期的越优先被淘汰
  7. allkeys-lfu 从所有的key中使用近似LFU算法(最少使用频率)进行淘汰
  8. volatile-lfu 设置了过期时间的key中使用近似LFU算法进行淘汰

缓存更新机制

Cache aside 旁路缓存

读请求:应用首先会判断缓存是否有该数据,缓存命中直接返回数据,缓存未命中即缓存穿透到数据库,从数据库查询数据然后回写到缓存中,最后返回数据给客户端 写请求:首先更新数据库,然后从缓存中删除该数据

更新缓存的时间要远大于数据库,故如果读请求早于写请求读到数据库的旧值,则会更早地把旧值写到缓存中,紧接着,写请求从缓存删除该旧值

  1. 先更新数据库,再更新缓存:写请求冲突,旧的写请求会在更新缓存时覆盖新的写请求
  2. 先删缓存,再更新数据库(或先更新数据库,再删除缓存):旧的读请求会在新的写请求删完缓存中的旧值之后,又写入自己读取到的旧值

Read/Write through

将数据库的同步委托给缓存提供程序Cache Provider

Write behind/back

延迟写入,应用程序更新数据时只更新缓存,Cache Provider每隔一段时间将数据刷新到数据库中