Redis面试问题整理
redis的常见数据类型及应用场景
- String
- 计数器/分布式ID生成(因为有自增自减功能incr、decr)
- 分布式锁(setnx)
- 统计多单位的数量
- 粉丝数
- List
- 存储热点数据:最新评论,最新文章列表,使用list 存储,ltrim取出热点数据,删除老数据
- Set
- 通过交集得到共同好友
- 通过差集做可能认识的朋友推荐
- Hash
- 对象缓存存储,如用户信息的保存
- Zset(有序集合)
- 排行榜榜应用实现
- 普通消息、重要消息 带权重进行判断
- 存储班级成绩表,工资表排序进行判断
- 延时队列
使用 【当前时间戳 + 需要延迟的时长】做score, 消息内容作 为元素,调用zadd来生产消息,消费者使用zrangbyscore获取当前时间之前的数 据做轮询处理。
- geospatial 地理位置
- hyperloglog 做基数统计
- bitmap
统计用户信息 :活跃、不活跃! 登录、未登录! 打卡!
Redis实现分布式锁的问题
- 过期时间设置问题
- 过期时间不能设置过长,这样有可能会死锁
这个持有锁的进程死掉后,但锁还没过期,这段时间别的进程不能获取这个锁就发生死锁问题 - 要定期续命,以防业务没执行完锁已经过期了
- 过期时间不能设置过长,这样有可能会死锁
- 保证原子操作问题
setnx 和expire 执行时要保证原子性 如用lua语言,或用set k v - 客户端误删问题
在进行锁的释放(删除key)的时候,判断当前锁的拥有者是当前线程才可以删除 - 释放锁的原子操作
当前进程判断和删除不是原子性的,这样如果进了判断当前key失效,别的进程获取了这个key,那就会误删这个key - 主备架构,故障转移数据同步问题
由于Redis使用的是主从复制,所以当我们进程A成功获取锁后,master宕机,新的master选举出来后,原来的数据还没同步过来的时候,进程B就也能在新的master上获取这个key,这样就有两个进程都获取到了锁。
RedLock 为了解决Redis分布式锁的问题
对多个redis节点加锁成功才能获取到锁。
具体流程:
1.获取当前时间
2.按顺序依次向N个Redis节点获取锁,为确保某个Redis节点失败不影响算法继 续进行,获取锁还需要设置一个超时时间,Redis获取锁失败,立即尝试下一个 节点
3.计算加锁过程的耗时时间, 当前时间减第一步获取锁的时间如果小于锁的有 效时间,且客户端从大多数Redis节点都加锁成功,则认为加锁成功,否则认为 加锁失败
4.如果最终获取锁的操作成功,锁的有效时间应该重新计算,锁的有效时间=设 置的有效时间-加锁消耗的时间
5.如果加锁失败了,则客户端应该释放所有节点对应得锁
Redis 是如何处理过期数据的
- 惰性删除
访问键值时,再检查当前的键值是否过期,如果过期则执行删除并返回 null 给客户端 - 定期删除
Redis 服务器每隔一段时间会检查一下看看是否有过期 键可以被清除。
扫描是采用随机抽取的方式,并且会给扫描设置最大执行时间 防止线程卡死。
redis 内存淘汰机制/内存不够如何处理
Redis的内存超过最大允许的内存之后,会触发内存淘汰策略。
- noeviction:不淘汰任何数据,当内存不足时,执行缓存新增操作会报错,它是 Redis 默认内存淘汰策略。
- allkeys-lru:淘汰整个键值中最久未使用的键值。
- allkeys-random:随机淘汰任意键值。
- volatile-lru:淘汰所有设置了过期时间的键值中最久未使用的键值。
- volatile-r