JAVA互联搬砖工人▲快看看这40道面试题,面试还搞不懂Redis( 五 )


3、队列
Reids在内存存储引擎领域的一大优点是提供list和set操作 , 这使得Redis能作为一个很好的消息队列平台来使用 。 Redis作为队列使用的操作 , 就类似于本地程序语言(如Python)对list的push/pop操作 。 如果你快速的在Google中搜索“Redisqueues” , 你马上就能找到大量的开源项目 , 这些项目的目的就是利用Redis创建非常好的后端工具 , 以满足各种队列需求 。 例如 , Celery有一个后台就是使用Redis作为broker , 你可以从这里去查看 。
4 , 排行榜/计数器
Redis在内存中对数字进行递增或递减的操作实现的非常好 。 集合(Set)和有序集合(SortedSet)也使得我们在执行这些操作的时候变的非常简单 , Redis只是正好提供了这两种数据结构 。 所以 , 我们要从排序集合中获取到排名最靠前的10个用户–我们称之为“user_scores” , 我们只需要像下面一样执行即可:当然 , 这是假定你是根据你用户的分数做递增的排序 。 如果你想返回用户及用户的分数 , 你需要这样执行:ZRANGEuser_scores010WITHSCORESAgoraGames就是一个很好的例子 , 用Ruby实现的 , 它的排行榜就是使用Redis来存储数据的 , 你可以在这里看到 。
5、发布/订阅
最后(但肯定不是最不重要的)是Redis的发布/订阅功能 。 发布/订阅的使用场景确实非常多 。 我已看见人们在社交网络连接中使用 , 还可作为基于发布/订阅的脚本触发器 , 甚至用Redis的发布/订阅功能来建立聊天系统!
假如Redis里面有1亿个key , 其中有10w个key是以某个固定的已知的前缀开头的 , 如果将它们全部找出来?
答:使用keys指令可以扫出指定模式的key列表 。
对方接着追问:如果这个redis正在给线上的业务提供服务 , 那使用keys指令会有什么问题?
这个时候你要回答redis关键的一个特性:redis的单线程的 。 keys指令会导致线程阻塞一段时间 , 线上服务会停顿 , 直到指令执行完毕 , 服务才能恢复 。 这个时候可以使用scan指令 , scan指令可以无阻塞的提取出指定模式的key列表 , 但是会有一定的重复概率 , 在客户端做一次去重就可以了 , 但是整体所花费的时间会比直接用keys指令长 。
如果有大量的key需要设置同一时间过期 , 一般需要注意什么?
答:如果大量的key过期时间设置的过于集中 , 到过期的那个时间点 , redis可能会出现短暂的卡顿现象 。 一般需要在时间上加一个随机值 , 使得过期时间分散一些 。
使用过Redis做异步队列么 , 你是怎么用的?
答:一般使用list结构作为队列 , rpush生产消息 , lpop消费消息 。 当lpop没有消息的时候 , 要适当sleep一会再重试 。 如果对方追问可不可以不用sleep呢?list还有个指令叫blpop , 在没有消息的时候 , 它会阻塞住直到消息到来 。 如果对方追问能不能生产一次消费多次呢?使用pub/sub主题订阅者模式 , 可以实现1:N的消息队列 。
如果对方追问pub/sub有什么缺点?
在消费者下线的情况下 , 生产的消息会丢失 , 得使用专业的消息队列如RabbitMQ等 。
如果对方追问redis如何实现延时队列?
我估计现在你很想把面试官一棒打死 , 怎么问的这么详细 。 但是你很克制 , 然后神态自若的回答道:使用sortedset , 拿时间戳作为score , 消息内容作为key调用zadd来生产消息 , 消费者用zrangebyscore指令获取N秒之前的数据轮询进行处理 。 到这里 , 面试官暗地里已经对你竖起了大拇指 。 但是他不知道的是此刻你却竖起了中指 , 在椅子背后 。
使用过Redis分布式锁么 , 它是什么回事?
先拿setnx来争抢锁 , 抢到之后 , 再用expire给锁加一个过期时间防止锁忘记了释放 。
这时候对方会告诉你说你回答得不错 , 然后接着问如果在setnx之后执行expire之前进程意外crash或者要重启维护了 , 那会怎么样?这时候你要给予惊讶的反馈:唉 , 是喔 , 这个锁就永远得不到释放了 。 紧接着你需要抓一抓自己得脑袋 , 故作思考片刻 , 好像接下来的结果是你主动思考出来的 , 然后回答:我记得set指令有非常复杂的参数 , 这个应该是可以同时把setnx和expire合成一条指令来用的!对方这时会显露笑容 , 心里开始默念:嗯 , 位面试者还不错 。


推荐阅读