Redis 缓存问题
Redis 最常用的一个场景就是作为缓存,在实践中可能会有哪些问题?比如一致性、击穿、穿透、雪崩、污染等。
在高并发的业务场景下,数据库大多数情况都是用户并发访问最薄弱的环节。所以,就需要 Redis 做一个缓冲操作,让请求先放问到 Redis,这样可以大大缓解数据库的压力。
当缓存出现时候,必须考虑到如下问题:缓存穿透、缓存击穿、缓存雪崩、缓存污染、缓存和数据库一致性
缓存穿透
缓存穿透事指缓存和数据库中都没有数据,而用户不断发请求。由于缓存是不命中时被动写的,摒弃饿处于容错考虑,如果从存储层查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到存储层去查询,失去了缓存的意义。
解决方案
接口层增加校验,如用户鉴权。
从缓存取不到的数据,在数据库中也没有取道,这时也可以将key-value对写为key-null,缓存有效时间可以设置短点,如30s
布隆过滤器。bloomfilter就类似于一个hash set,用于快速判某个元素是否存在于集合中,其典型的应用场景就是快速判断一个key是否存在于某容器,不存在就直接返回。布隆过滤器的关键就在于hash算法和容器大小,
缓存雪崩
缓存雪崩是指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至down机。和缓存击穿不同的是,缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。
解决方案
缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生。
如果缓存数据库是分布式部署,将热点数据均匀分布在不同的缓存数据库中。
设置热点数据永远不过期。
缓存污染(或满了)
缓存污染问题说的是缓存中一些只会被访问一次或者几次的的数据,被访问完后,再也不会被访问到,但这部分数据依然留存在缓存中,消耗缓存空间。
缓存污染会随着数据的持续增加而逐渐显露,随着服务的不断运行,缓存中会存在大量的永远不会再次被访问的数据。缓存空间是有限的,如果缓存空间满了,再往缓存里写数据时就会有额外开销,影响Redis性能。这部分额外开销主要是指写的时候判断淘汰策略,根据淘汰策略去选择要淘汰的数据,然后进行删除操作。
最大缓存设置多大
系统的设计选择是一个权衡的过程:大容量缓存是能带来性能加速的收益,但是成本也会更高,而小容量缓存不一定就起不到加速访问的效果。一般来说,我会建议把缓存容量设置为总数据量的 15% 到 30%,兼顾访问性能和内存空间开销。
对于 Redis 来说,一旦确定了缓存最大容量,比如 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缓存,还是先删除缓存,再写数据库,都有可能出现数据不一致的情况
如果删除了缓存,还没来得及写数据库,另外一个线程就来读取,发现缓存为空,则去数据库读取数据写入缓存,此时缓存中为脏数据。
如果先写了数据库,在删除缓存之前,写数据库的县城宕机了,没有删除掉缓存,则也会出现数据不一致情况。
因为读和写是并发的,没法保证顺序,就会出现缓存和数据库不一致的问题。
最后更新于
这有帮助吗?