及时行乐|这些Redis面试题是不是让你有很多问号?一文带你吊打面试官( 五 )


然后呢 , 另外的客户端 2 就可以尝试完成加锁了 。 这就是所谓的分布式锁的开源 Redisson 框架的实现机制 。 一般我们在生产系统中 , 可以用 Redisson 框架提供的这个类库来基于 redis 进行分布式锁的加锁与释放锁 。
33.上述 Redis 分布式锁的缺点
其实上面那种方案最大的问题 , 就是如果你对某个 redis master 实例 , 写入了 myLock 这种锁key 的 value , 此时会异步复制给对应的 master slave 实例 。 但是这个过程中一旦发生 redis master 宕机 , 主备切换 , redis slave 变为了 redis master 。
接着就会导致 , 客户端 2 来尝试加锁的时候 , 在新的 redis master 上完成了加锁 , 而客户端 1也以为自己成功加了锁 。 此时就会导致多个客户端对一个分布式锁完成了加锁 。 这时系统在业务语义上一定会出现问题 , 导致各种脏数据的产生 。
所以这个就是 redis cluster , 或者是 redis master-slave 架构的主从异步复制导致的 redis 分布式锁的最大缺陷:在 redis master 实例宕机的时候 , 可能导致多个客户端同时完成加锁 。
34.使用过 Redis 分布式锁么 , 它是怎么实现的?
先拿 setnx 来争抢锁 , 抢到之后 , 再用 expire 给锁加一个过期时间防止锁忘记了释放 。 如果在 setnx 之后执行 expire 之前进程意外 crash 或者要重启维护了 , 那会怎么样?set 指令有非常复杂的参数 , 这个应该是可以同时把 setnx 和 expire 合成一条指令来用的!
35.使用过 Redis 做异步队列么 , 你是怎么用的?有什么缺点?
一般使用 list 结构作为队列 , rpush 生产消息 , lpop 消费消息 。 当 lpop 没有消息的时候 , 要适当 sleep一会再重试 。
缺点:
在消费者下线的情况下 , 生产的消息会丢失 , 得使用专业的消息队列如 rabbitmq 等 。
能不能生产一次消费多次呢?
使用 pub/sub 主题订阅者模式 , 可以实现 1:N 的消息队列 。
36.什么是缓存穿透?如何避免?什么是缓存雪崩?何如避免?
缓存穿透
一般的缓存系统 , 都是按照 key 去缓存查询 , 如果不存在对应的 value , 就应该去后端系统查找(比如DB) 。 一些恶意的请求会故意查询不存在的 key,请求量很大 , 就会对后端系统造成很大的压力 。 这就叫做缓存穿透 。
如何避免?
1:对查询结果为空的情况也进行缓存 , 缓存时间设置短一点 , 或者该 key 对应的数据 insert 了之后清理缓存 。
2:对一定不存在的 key 进行过滤 。 可以把所有的可能存在的 key 放到一个大的 Bitmap 中 , 查询时通过该 bitmap 过滤 。
缓存雪崩
当缓存服务器重启或者大量缓存集中在某一个时间段失效 , 这样在失效的时候 , 会给后端系统带来很大压力 。 导致系统崩溃 。
如何避免?
1:在缓存失效后 , 通过加锁或者队列来控制读数据库写缓存的线程数量 。 比如对某个 key 只允许一个线程查询数据和写缓存 , 其他线程等待 。
2:做二级缓存 , A1 为原始缓存 , A2 为拷贝缓存 , A1 失效时 , 可以访问 A2 , A1 缓存失效时间设置为短期 , A2 设置为长期
3:不同的 key , 设置不同的过期时间 , 让缓存失效的时间点尽量均匀
及时行乐|这些Redis面试题是不是让你有很多问号?一文带你吊打面试官


推荐阅读