redis 面经详解

1.Redis

1.1 Redis可以用来做什么?

1.它可以作为数据库。实现点赞,关注,排行等对性能要求极高的互联网需求
2.它最长用来做缓存,是实现分布式缓存的首先中间件。
3.它可以用来做计算工具,能用很少的代价计算用户在线的天数等数据。
4.它还可以实现分布式锁,可以作为消息队列使用。

1.2 Redis和传统的关系型数据库有什么不同?

	redis是一种基于键值对的NoSQL数据库,而键值对的值有多种数据结构和算法构成
redis存放在内存中,因此它的速度非常惊人,远超关系型数据库。
	关系型数据库是基于二维数据表来存储数据的,他的数据格式更加严谨,并且支持关系查询
关系型数据库的数据存储在硬盘上,可以存放大量数据,但是他的性能没有redis强大。

1.3 Redis有哪些数据类型?

1.redis支持5种核心的数据类型。分别是列表,字符串,哈希,集合,有序集合。
2.redis还提供了Geo,Bitmap,HyperLogLog等。他们都是有上面的5种核心数据类型来实现的。
3.redis在5.0新增加了Streams数据类型,他是一个功能强大的,支持多播的,可持久化的消息队列。

1.4 Redis是单线程的,为什么还能这么快?

1.redis的大部分操作都是在内存中实现的。
2.对服务端程序来说,切换线程和锁通常是性能杀手,而单线程避免了线程切换和竞争所产生的消耗。
3.redis在IO多路复用的机制。使其在网络IO操作中能并发的处理大量的客户端请求,实现高吞吐率。

关于Redis的单线程架构实现,如下图:
在这里插入图片描述

1.5 Redis在持久化时fork出一个子进程,这时已经有两个进程了,怎么能说是单线程呢?

	redis是单线程的,主要指的是网络IO和键值对的读写是有一个线程实现的,
而Redis的其他功能如持久化,异步删除,集群数据同步等,则是依赖其他线程来执行的
所以说redis是单线程的只是一种说法,而它的底部实现并不是单线程的。

1.6 set和zset有什么区别?

set
	1.集合中的元素是无序的,不可重复的。一个集合中最多保存2^32-1个元素。
	2.除了支持元素的增删改查,还支持对多个集合去交集,并集,差集。
zset
	1.有序集合保留了元素不可重复的特点。
	2.有序集合给每个元素一个分数,并以此作为排序的依据。
	3.有序集合不能包含相同的元素,但是元素的分数可以相同。

1.7 说一下Redis中的watch命令

很多时候,要确保事务中的数据没有被其他客户端修改才执行该事务。redis提供了watch命令来解决这类问题。
这是一种乐观锁的机制,客户端通过watch命令,要求服务器对一个或多个key进行监视。
如果客户端在执行事务之前,这些key值发生了变化,则服务器将拒绝执行客户端提交的事务,并向他返回一个空值。

1.8 说说Redis中List结构的相关操作

列表是线性有序的数据结构,它内部的元素是可以重复的,并且一个列表最多存储2^32-1个元素。
列表的常用命令:
	lpop/rpop	: 从列表的左侧或右侧弹出一个元素。
	lpush/rpush : 从列表的左侧或右侧添加数据。
	lindex		: 返回指定索引处的数据。
	lrange		: 指定索引范围,并返回这个范围内的数据。
	blpop/brpop : 从列表左侧或右侧弹出一个元素,若列表为空,则进入阻塞状态。
	

1.9 你要如何设计Redis的过期时间?

1.对于热点数据不设置过期时间。使其达到"物理"上的永不过期,进而避免缓存击穿的问题。
2.在设置过期时间时,附加一个随机数,避免大量的key同时过期,导致缓存雪崩。

1.10 Redis中,sexnx命令的返回值是什么,如何使用该命令实现分布式锁?

sexnx返回的是整数类型,返回1表示设置值成功。返回0表示设置值失败(key已经存在)。
一般我们不建议使用sexne来实现分布式锁。为了避免出现死锁的情况,我们要给锁设置一个过期时间。
而sexnx命令和设置过期时间的命令不是原子的。可能加锁成功,而设置过期时间失败,依然存在死锁隐患。
对与这种情况,redis改进了set命令,给他增加了nx选项,启用该选项set命令的效果就跟setnx一样了。

采用redis实现分布式锁,就是在redis里村一份代表锁的数据,通常用字符串即可。采用改进后setnx来实现。

问题:

看起来已经很完美了,但实际上还有隐患,如下图。进程A在任务没有执行完毕时,锁已经到期被释放了。等进程A的任务执行结束后,它依然会尝试释放锁,因为它的代码逻辑就是任务结束后释放锁。但是,它的锁早已自动释放过了,它此时释放的可能是其他线程的锁。

在这里插入图片描述
在加锁时就要给锁设置一个标识,进程要记住这个标识。当进程解锁的时候,要进行判断,是自己持有的锁才能释放,否则不能释放。可以为key赋一个随机值,来充当进程的标识。

解锁时要先判断、再释放,这两步需要保证原子性,否则第二步失败的话,就会出现死锁。而获取和删除命令不是原子的,这就需要采用Lua脚本,通过Lua脚本将两个命令编排在一起,而整个Lua脚本的执行是原子的。

1.11 说一说Redis的持久化策略

redis支持RDB持久化,AOF持久化,RDB-AOF混合持久化这三种持久化方式。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值