数据库
PythonJava前端运维
Redis
Redis
  • Redis 简介
  • 安装和连接
  • Redis 键(key)
  • Redis 数据类型
    • 基本数据类型
      • String
      • Lists
      • Sets
      • zset
      • Hashs
    • 特殊类型
      • Bitmaps
      • HyperLogLog
      • Geospatial
    • Sorted sets
    • Streams
    • Geospatial
    • Bitfields
  • Redis 配置
  • Redis CLI
  • Redis 持久化
  • Redis 事务
  • Redis 管道
  • Redis 发布订阅
  • Redis 脚本
  • Redis 数据备份与恢复
  • Redis 缓存问题
  • Redis 运维监控
由 GitBook 提供支持
在本页
  • 缓存穿透
  • 缓存雪崩
  • 缓存污染(或满了)
  • 最大缓存设置多大
  • 缓存淘汰策略
  • 数据一致性

这有帮助吗?

Redis 缓存问题

Redis 最常用的一个场景就是作为缓存,在实践中可能会有哪些问题?比如一致性、击穿、穿透、雪崩、污染等。

在高并发的业务场景下,数据库大多数情况都是用户并发访问最薄弱的环节。所以,就需要 Redis 做一个缓冲操作,让请求先放问到 Redis,这样可以大大缓解数据库的压力。

当缓存出现时候,必须考虑到如下问题:缓存穿透、缓存击穿、缓存雪崩、缓存污染、缓存和数据库一致性

缓存穿透

缓存穿透事指缓存和数据库中都没有数据,而用户不断发请求。由于缓存是不命中时被动写的,摒弃饿处于容错考虑,如果从存储层查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到存储层去查询,失去了缓存的意义。

解决方案

  1. 接口层增加校验,如用户鉴权。

  2. 从缓存取不到的数据,在数据库中也没有取道,这时也可以将key-value对写为key-null,缓存有效时间可以设置短点,如30s

  3. 布隆过滤器。bloomfilter就类似于一个hash set,用于快速判某个元素是否存在于集合中,其典型的应用场景就是快速判断一个key是否存在于某容器,不存在就直接返回。布隆过滤器的关键就在于hash算法和容器大小,

缓存雪崩

缓存雪崩是指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至down机。和缓存击穿不同的是,缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。

解决方案

  1. 缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生。

  2. 如果缓存数据库是分布式部署,将热点数据均匀分布在不同的缓存数据库中。

  3. 设置热点数据永远不过期。

缓存污染(或满了)

缓存污染问题说的是缓存中一些只会被访问一次或者几次的的数据,被访问完后,再也不会被访问到,但这部分数据依然留存在缓存中,消耗缓存空间。

缓存污染会随着数据的持续增加而逐渐显露,随着服务的不断运行,缓存中会存在大量的永远不会再次被访问的数据。缓存空间是有限的,如果缓存空间满了,再往缓存里写数据时就会有额外开销,影响Redis性能。这部分额外开销主要是指写的时候判断淘汰策略,根据淘汰策略去选择要淘汰的数据,然后进行删除操作。

最大缓存设置多大

系统的设计选择是一个权衡的过程:大容量缓存是能带来性能加速的收益,但是成本也会更高,而小容量缓存不一定就起不到加速访问的效果。一般来说,我会建议把缓存容量设置为总数据量的 15% 到 30%,兼顾访问性能和内存空间开销。

对于 Redis 来说,一旦确定了缓存最大容量,比如 4GB,你就可以使用下面这个命令来设定缓存的大小了:

CONFIG SET maxmemory 4gb

不过,缓存被写满是不可避免的, 所以需要数据淘汰策略。

缓存淘汰策略

Redis共支持八种淘汰策略,分别是noeviction、volatile-random、volatile-ttl、volatile-lru、volatile-lfu、allkeys-lru、allkeys-random 和 allkeys-lfu 策略。

怎么理解呢?主要看分三类看:

  • 不淘汰

    • noeviction (v4.0后默认的)

  • 对设置了过期时间的数据中进行淘汰

    • 随机:volatile-random

    • ttl:volatile-ttl

    • lru:volatile-lru

    • lfu:volatile-lfu

  • 全部数据进行淘汰

    • 随机:allkeys-random

    • lru:allkeys-lru

    • lfu:allkeys-lfu、

数据一致性

读取缓存步骤通常没什么问题,但是一旦涉及到数据更新:数据库和缓存之间就会出现数据不一致问题,

不管是先写数据库,再删除Redis缓存,还是先删除缓存,再写数据库,都有可能出现数据不一致的情况

  1. 如果删除了缓存,还没来得及写数据库,另外一个线程就来读取,发现缓存为空,则去数据库读取数据写入缓存,此时缓存中为脏数据。

  2. 如果先写了数据库,在删除缓存之前,写数据库的县城宕机了,没有删除掉缓存,则也会出现数据不一致情况。

因为读和写是并发的,没法保证顺序,就会出现缓存和数据库不一致的问题。

上一页Redis 数据备份与恢复下一页Redis 运维监控

最后更新于8个月前

这有帮助吗?