常见的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映射关系。

而在redis中,expire分为主动和被动两种实现:

被动:每次访问key时,先去dict字典表中查看key是否存在,如果存在再去expires字典表中判断对应key有没有过期时间,如果已过期,则清除并返回nil。不过存在问题,如果某个key一直不被访问,就永远不会删除,造成空间浪费

主动:定期扫描expires表,主动清除已过期key(dict+expire两个表)

这时候对方会告诉你说你回答得不错,然后接着问如果在setnx之后执行expire之前进程意外crash或者要重启维护了,那会怎么样?

这时候你要给予惊讶的反馈:唉,是喔,这个锁就永远得不到释放了。紧接着你需要抓一抓自己得脑袋,故作思考片刻,好像接下来的结果是你主动思考出来的,然后回答:我记得set指令有非常复杂的参数,这个应该是可以同时把setnx和expire合成一条指令来用的!对方这时会显露笑容,心里开始默念:摁,这小子还不错。

# 从 2.6.12 起,SET 涵盖了 SETEX 的功能,并且 SET 本身已经包含了设置过期时间的功能,也就是说,我们前面需要的功能只用 SET 就可以实现。

set($key, $value, array('nx', 'ex' => $ttl)); # time to live

你可能感兴趣的:(常见的Redis面试"刁难"问题-附个人实操之一)