常见的Redis面试"刁难"问题-附个人实操之一
之前在某个公众号下看到老钱的一篇文章,题目是《十个常见的Redis面试“刁难”问题》,感觉写的很好,不过里面的解答对于我这种小白来说并不是很全面,所以在这里实际操作、思考一番,并把自己的所得简单记录下来。
原文参考:https://mp.weixin.qq.com/s/Z4a8wbWvPDGFTkKJH0X9VQ
Redis有哪些数据结构?
字符串String、字典Hash、列表List、集合Set、有序集合SortedSet。
如果你是Redis中高级用户,还需要加上下面几种数据结构HyperLogLog、Geo、Pub/Sub。
如果你说还玩过Redis Module,像BloomFilter,RedisSearch,Redis-ML,面试官得眼睛就开始发亮了。
使用过Redis分布式锁么,它是什么回事?
先拿setnx来争抢锁,抢到之后,再用expire给锁加一个过期时间防止锁忘记了释放。
setnx —> set if not exist
设置成功,返回 1 。 设置失败,返回 0 。
127.0.0.1:6379> setnx jin siyu
(integer) 1
127.0.0.1:6379> setnx jin er
(integer) 0
127.0.0.1:6379> get jin
"siyu"
可以看到,数据还是最初设置的值,第二次setnx并未成功。
为了防止setnx一直不被释放,加入expire
127.0.0.1:6379> expire jin 20
(integer) 1
127.0.0.1:6379> get jin
"siyu"
127.0.0.1:6379> get jin
"siyu"
127.0.0.1:6379> get jin
(nil)
127.0.0.1:6379> setnx jin hello
(integer) 1
可以看到,通过设置过期时间,时间到了之后就会自动清除。
而expire是怎么实现的呢?
typedef struct redisDb {
dict *dict;
dict *expires;
dict *blocking_keys;
dict *ready_keys;
dict *watched_keys;
int id;
} redisDb;
可以看到,redis中存在expires这个dict字典表,当执行了expire后,会在这个dict中记录key—>expireTime映射关系。这时候对方会告诉你说你回答得不错,然后接着问如果在setnx之后执行expire之前进程意外crash或者要重启维护了,那会怎么样?
而在redis中,expire分为主动和被动两种实现:
被动:每次访问key时,先去dict字典表中查看key是否存在,如果存在再去expires字典表中判断对应key有没有过期时间,如果已过期,则清除并返回nil。不过存在问题,如果某个key一直不被访问,就永远不会删除,造成空间浪费
主动:定期扫描expires表,主动清除已过期key(dict+expire两个表)
【常见的Redis面试"刁难"问题-附个人实操之一】这时候你要给予惊讶的反馈:唉,是喔,这个锁就永远得不到释放了。紧接着你需要抓一抓自己得脑袋,故作思考片刻,好像接下来的结果是你主动思考出来的,然后回答:我记得set指令有非常复杂的参数,这个应该是可以同时把setnx和expire合成一条指令来用的!对方这时会显露笑容,心里开始默念:摁,这小子还不错。
# 从 2.6.12 起,SET 涵盖了 SETEX 的功能,并且 SET 本身已经包含了设置过期时间的功能,也就是说,我们前面需要的功能只用 SET 就可以实现。set($key, $value, array('nx', 'ex' => $ttl));
# time to live
推荐阅读
- 热闹中的孤独
- JAVA(抽象类与接口的区别&重载与重写&内存泄漏)
- 放屁有这三个特征的,请注意啦!这说明你的身体毒素太多
- 一个人的旅行,三亚
- 布丽吉特,人生绝对的赢家
- 慢慢的美丽
- 尽力
- 一个小故事,我的思考。
- 家乡的那条小河
- 《真与假的困惑》???|《真与假的困惑》??? ——致良知是一种伟大的力量