Redis缓存

Redis缓存

一、为什么使用缓存?

1.在数据库之前加一层redis缓存。提高查询性能和效率,比如把查询比较频繁的页面放在redis里面。

2.高并发情况下,数据库往往成为查询的瓶颈,并发请求一多就会容易把数据库打崩。因此如果有一层缓存可以对数据库起到保护的作用。

二、什么是缓存穿透?缓存击穿?缓存雪崩?怎么解决?

1.缓存穿透指的是缓存中查不到,数据库也查不到

解决方案:① 对查找参数进行合法性的校验。②对于数据库中确实没有的数据,把它也写入到redis缓存中并记录其值为null。但是这种方法有一个问题,redis中容易被无效数据占满,因此可以把无效数据的有效期设置短一些。③在redis之前引入布隆过滤器BloomFilter,它可以快速判断查询数据是否在集合中

布隆过滤器:可以认为是一个值只为0或1的数组,添加数据时,比如说我要添加A,就会同通过一个hash散列映射为一个0101的字符串,写入数组的时候只需要在字符串对应为1的位置记为1即可(0位置是否为0不需要关注)。查询数据时,假设我要查询B,就会先通过hash散列映射为一个字符串,然后在布隆过滤器数组中查看字符串所有对应为1的位置是否都为1,如果存在不为1的说明该数据不在集合中。这种方法只能加数据不能减数据,也会存在误判,在于如果映射的字符串为0100,那么就会出现误判。因此误判率高低取决于hash散列的复杂程度,以及数组的长度

2.缓存击穿指查找时Redis没有,但是数据库中有。一般出现在在缓存第一次初始化或是缓存中数据过期的情况。 问题在于高并发情况下,DB写入缓存需要时间,如果此时瞬间出现很多的请求,redis查不到就会全部进入DB查询,给数据库造成很大的压力。

解决方案: ①在redis中设置一个热点数据,永不过期。(注意在value中包含一个逻辑上的过期时间,然后另起一个线程定期更新数据)。②在读redis操作和DB写redis过程中,可以加一个锁,每次只能有一个线程对redis访问。

3.缓存雪崩指缓存大面积过期,导致查询请求瞬间打到DB。

解决方案:①把缓存的失效时间分散开,例如可以在统一失效时间下,增加一个随机值。redis一个一个失效,此时对DB是不会有太大压力的。②热点数据。

三、如何保证Redis和数据库数据一致性?

数据一致性问题其实就是要解决高并发情况下,到底是先删缓存,还是先修改数据库?

1.如果是先删除缓存,再写数据库。高并发场景下,如果第一个线程删除完后还没来得及写数据库,第二个线程就来了,他会直接读数据库并把数据库的脏数据写到缓存中。这样缓存中数据为修改前的值,DB中为修改后数据,造成不一致性。

解决方案:①可以在第一个线程修改时,缓存中的数据不删除,而是置为一个和业务无关的状态位,目的就是告诉后面要读数据的线程当前这个数据正在修改,然后让它们休眠一小会,再去重新查一次Redis。可能存在的问题时,线程可能会多次休眠,影响某个业务效率和吞吐。

延时双删。删缓存写完数据库之后,延时一小会,再删除一次缓存,目的是保证最新的数据一定是在数据库中

2.先写数据库再删除缓存的问题在于,如果缓存删除失败会造成数据不一致性。

解决方案:①给缓存中数据设置一个较小的过期时间。(问题在于过期时间内依旧不能保证一致性)

②引入MQ。缓存和DB操作分别由不同消费者进行操作,删除缓存失败但是消息仍在MQ中,可以进行重试,以此保证缓存和DB操作的原子性

③引入热点数据,value中写入一个逻辑上过期时间,后台起一个线程定期扫描这些Key,如果过期则删除。(删除已经不由业务来做,通过后台线程删除)

四、Redis有哪几种常见数据结构?Redis如何实现分布式锁?

1.String:作为常规的Key-value类型。

Hash:是一个field-value对应的映射表,类似于JAVA中的HashMap,可以用来存储一个对象信息,比如id=1,name=xx,age=22等等。可以减少字段,如果使用string那么每一个key都需要创建一个新的字段。

List :是一个基于双向链表实现的一个链表,比如粉丝列表,关注列表都可以使用list

Set:相当于一个自动去重的List列表,可以轻易实现交集、并集等操作。比如实现QQ的好友推荐,把A的好友放在一个set中,B的好友放在一个set中,只需要两个set做交集就可以得到A与B的共同好友。

ZSet:是一个可以按照某一个权重参数排序的Set。

2.Redis实现分布式锁:

SETNX (key ,value):当key不存在,就将key设置为value并返回1,如果key已存在则返回0.

EXPIRE (key ,locktime):设置key的有效时长,过了locktime时间之后key就失效了。

DEL(key):删除key

GETSET (key, value):先GET返回key对应的value(如果没有则返回空),然后再将key设置为value。

①给SETNX加锁,执行完之后通过DEL解 锁让其他进程获得。但是会出现如下情况:

如果当前获取锁的进程执行时还未释放就挂了,那么这个锁就永远锁死了。解决方法可以通过给每个获取锁的key通过EXPIRE指令设置一个过期时间,过期后锁就失效了。如果是在EXPIRE之前就挂了,还可以通过使用set指令把SETNX和EXPIRE合成一条指令使用,保证原子性

五、Redis如何配置key的过期时间?实现原理是什么?

1.定期删除:每隔一段时间,执行一次删除过期key操作。Redis中要控制执行效率和执行时长。删除时会遍历所有数据库,检查DB中指定个数的key,随机抽查这些key,过期则删除。

2.懒汉式删除,通过getset等指令,用到时再去判断是否过期。

六、海量数据库如何快速查找一条记录?

1.对于无效数据,通过布隆过滤器进行过滤。

2.对于有效数据,我们希望要读的数据它是在缓存中的。就会涉及到热点数据,过期时长,数据修改顺序等等问题。



今日总结

学习知识

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值