Redis面经(持续更新中)
首先来说Redis的话是一个基于内存的高性能K-V数据库,并且开源免费,Redis支持五种数据类型,非集合的是String,集合的有List、Set、Zset、Hash
Redis支持持久化AOF、RDB,Redis默认的话是使用RDB做持久化,建议采用AOF方式,因为AOF支持三种追加方式能够更好的恢复信息,分别是appendfsync:alawys、everysec、no,而alawys会严重降低redis的效率,所以使用everysec。
Redis4.0之后优化了持久化的方式可以支持RDB+AOF同时进行,但是产生的文件格式不太友好。
Redis的过期策略:因为redis中设置过期时间后redis会进行定期删除+惰性删除,但是这两种方式有volatile:Iru(最近最少使用)、ttl(即将过期)、random;allkeys:Iru、random。我们常用的是volatile-Iru。
另外Redis可以设置主从模式来做数据备份:一主两从,当主机宕机时,通过选举机制在slave中选出新的master(主机宕机时还又分为了主观宕机和客官宕机)
Redis事务:ACID:原子性、一致性、隔离性、持久性
缓存雪崩和缓存穿透问题的话首先要说的是这两者的区别,他们最主要的区别就是
添加链接描述
缓存穿透是大面积请求的数据不存在于数据库和缓存中,导致数据库压力激增而崩溃,有效的解决办法一是使用布隆过滤器,因为布隆过滤器首先需要k个hash函数每个函数可以将key散裂成一个整数,另外在初识化的时候需要一个长度为n比特的数组,每个比特位初始为0,当某个key加入集合时,用k个hash函数计算出k个散列值,并把数组中对应的比特位置标记为1,当查询某个key是否存在与集合中时如果所有比特位置的值都是1就说明在集合中。虽然布隆过滤器不需要存储key节省了空间,但是这个算法有一定几率虽然比特位置值都是1但是key是不在集合中的。二是缓存空值, 之所以会发生穿透,就是因为缓存中没有存储这些空数据的key。从而导致每次查询都到数据库去了。那么我们就可以为这些key对应的值设置为null 丢到缓存里面去。后面再出现查询这个key 的请求的时候,直接返回null 。这样,就不用在到数据库中去走一圈了,但是别忘了设置过期时间。
缓存雪崩的话是缓存里没有但是数据库中有,这样也会导致数据库的压力瞬间激增从而导致数据库瘫痪,对于这个问题的话有三个阶段的解决方案,首先是事前要选择合适的淘汰策略,事中用ehcache缓存和Hystrix做限流和降级,事后使用redis持久化特性进行恢复
key大面积失效问题
大量key的过期时间设置的相同,导致同时有很多key过期,然后还去访问这些key,可以给key的过期时间进行Hash离散,或者用一个固定值加一个随机小数来做。
也可以通过版本号机制来处理
Redis集群没有用一致性Hash算法添加链接描述
Redis提供了2的14次方个(16384)卡槽,Redis 会根据节点数量大致均等的将哈希槽映射到不同的节点。
其实导致缓存雪崩的主要原因就是key的大面积失效问题,也有可能出现的场景就是在redis集群增减机器时出现的,这个也有有效的解决办法,就是使用一致性hash算法来均衡的散列key,从底层原理来说redis提供了16384个插槽,使用一致性hash算法时虚拟了2的32次方个虚拟节点与之对应,而当key存入时首先要经过hash算出它的哈希值,然后通过函数计算出对应的数组节点下标,从而完成均衡的分布key,增集群的时候通过向已有机器申请虚拟节点,并且进行rehash,避免key的大面积失效。一致性Hash算法:
如何解决Redis的并发竞争key问题?分布式锁:Redisson自带lua脚本(或者加时间戳)
如何保证缓存与数据库双写一致性
延时双删
Redis主从一致性问题
Redis集群的方式
哨兵
分片
Java客户端
Jedis
