redis面试题

本文介绍了Redis的几种关键数据类型,包括String、List、Set、Sorted Sets和Hash,比较了与Memcache的区别,重点讲解了Redis的持久化方法,以及如何应对缓存雪崩和穿透等问题。
摘要由CSDN通过智能技术生成

1、什么是redis?

redis是一个高性能的key-value数据库,具有非常高的读写性能,尤其在大数据量下,同样表现优秀。这得益于它的无关系性,数据库的结构简单。

2、redis支持几种数据类型?都有什么特点?

Stirng类型

概述:字符串类型是Redis中最为基础的数据存储类型,key-value存储

常用命令:

1set key value

设定key持有指定的字符串value,如果该key存在则进行覆盖操作。总是返回”OK”

2get key获取key的value。如果与该key关联的value不是String类型,redis将返回错误信息,因为get命令只能用于获取String value;如果该key不存在,返回null
3getset key value先获取该key的值,然后在设置该key的值
4incr key将指定的key的value原子性的递增1.如果该key不存在,其初始值为0,在incr之后其值为1。如果value的值不能转成整型,如hello,该操作将执行失败并返回相应的错误信息
5decr key将指定的key的value原子性的递减1.如果该key不存在,其初始值为0,在incr之后其值为-1。如果value的值不能转成整型,如hello,该操作将执行失败并返回相应的错误信息
6incrby key increment将指定的key的value原子性增加increment,如果该key不存在,器初始值为0,在incrby之后,该值为increment。如果该值不能转成整型,则失败并返回错误信息
7decrby key decrement将指定的key的value原子性减少decrement,如果该key不存在,器初始值为0,在decrby之后,该值为decrement。如果该值不能转成整型,如hello则失败并返回错误信息
8append key value如果该key存在,则在原有的value后追加该值;如果该key不存在,则重新创建一个key/value

List类型

概述:List类型是按照插入顺序排序的字符串链表

使用场景:

Redis链表经常会被用于消息队列的服务,以完成多程序之间的消息交换。假设一个应用程序正在执行LPUSH操作向链表中添加新的元素,我们通常将这样的程序称之为"生产者(Producer)",而另外一个应用程序正在执行RPOP操作从链表中取出元素,我们称这样的程序为"消费者(Consumer)"。如果此时,消费者程序在取出消息元素后立刻崩溃,由于该消息已经被取出且没有被正常处理,那么我们就可以认为该消息已经丢失,由此可能会导致业务数据丢失,或业务状态的不一致等现象的发生。然而通过使用RPOPLPUSH命令,消费者程序在从主消息队列中取出消息之后再将其插入到备份队列中,直到消费者程序完成正常的处理逻辑后再将该消息从备份队列中删除。同时我们还可以提供一个守护进程,当发现备份队列中的消息过期时,可以重新将其再放回到主消息队列中,以便其它的消费者程序继续处理;粉丝列表;关注列表等

常用命令:

1lpush key values[value1 value2…]在指定的key所关联的list的头部插入所有的values,如果该key不存在,该命令在插入的之前创建一个与该key关联的空链表,之后再向该链表的头部插入数据。插入成功,返回元素的个数
2lpushx key value仅当参数中指定的key存在时(如果与key管理的list中没有值时,则该key是不存在的)在指定的key所关联的list的头部插入value
3lrange key start end获取链表中从start到end的元素的值,start、end可为负数,若为-1则表示链表尾部的元素,-2则表示倒数第二个,依次类推…
4lpop key返回并弹出指定的key关联的链表中的第一个元素,即头部元素。如果该key不存在,返回nil;若key存在,则返回链表的头部元素
5llen key返回指定的key关联的链表中的元素的数量
6lrem key count value删除count个值为value的元素,如果count大于0,从头向尾遍历并删除count个值为value的元素,如果count小于0,则从尾向头遍历并删除。如果count等于0,则删除链表中所有等于value的元素
7lset key index value设置链表中的index的脚标的元素值,0代表链表的头元素,-1代表链表的尾元素。操作链表的脚标则放回错误信息
8linsert key before|after pivot value在pivot元素前或者后插入value这个元素
9rpush key values[value1、value2…]在该list的尾部添加元素
10rpushx key value在该list的尾部添加元素
11rpop key从尾部弹出元素
12rpoplpush resource destination将链表中的尾部元素弹出并添加到头部。[循环操作]

Set类型

概述:我们可以将Set类型看作为没有排序的字符集合,Set集合中不允许出现重复的元素

使用场景:对列表数据去重

常用命令:

1sadd key values[value1、value2…]向set中添加数据,如果该key的值已有则不会重复添加
2smembers key获取set中所有的成员
3scard key获取set中成员的数量
4sismember key member判断参数中指定的成员是否在该set中,1表示存在,0表示不存在或者该key本身就不存在
5srem key members[member1、member2…]删除set中指定的成员
6srandmember key随机返回set中的一个成员
7sdiff key[sdiff key1 key2…]返回key1与key2中相差的成员,而且与key的顺序有关。即返回差集
8sdiffstore destination key[key1、key2…]将key1、key2相差的成员存储在destination上
9sinter key[key1,key2…]返回交集
10sinterstore destination key[key…]将返回的交集存储在destination上
11sunion key[key1、key2…]返回并集
12sunionstore destination key[key…]将返回的并集存储在destination上

Sorted-Sets类型

概述:Sorted-Sets和Sets类型极为相似,它们都是字符串的集合,都不允许重复的成员出现在一个Set中。它们之间的主要差别是Sorted-Sets中的每一个成员都会有一个分数(score)与之关联,Redis正是通过分数来为集合中的成员进行从小到大的排序。然而需要额外指出的是,尽管Sorted-Sets中的成员必须是唯一的,但是分数(score)却是可以重复的

使用场景:游戏排名、微博热点话题等使用场景

常用命令:

1zadd key score member score2 member2 …将所有成员以及该成员的分数存放到sorted-set中
2zcard key获取集合中的成员数量
3zcount key min max获取分数在[min,max]之间的成员
4zincrby key increment member设置指定成员的增加的分数
5zrange key start end [withscores]获取集合中脚标为start-end的成员,[withscores]参数表明返回的成员包含其分数
6zrangebyscore key min max [withscores] [limit offset count]返回分数在[min,max]的成员并按照分数从低到高排序。[withscores]:显示分数;[limit offset count]:offset,表明从脚标为offset的元素开始并返回count个成员
7zrank key member返回成员在集合中的位置
8zrem key member[member…]移除集合中指定的成员,可以指定多个成员
9zscore key member返回指定成员的分数

Hash类型

概述:Redis中的Hashes类型可以看成具有String Key和String Value的map容器。所以该类型非常适合于存储值对象的信息。如Username、Password和Age等

使用场景:购物车,短信验证码

常用命令:

1hset key field value为指定的key设定field/value对(键值对)
2hget key field返回指定的key中的field的值
3hexists key field判断指定的key中的filed是否存在; 存在返回1 不存在返回0
4hlen key获取key所包含的field的数量
5hincrby key field increment设置key中filed的值增加increment,如:age增加20
6hmset key fields设置key中的多个filed/value
7hmget key fileds获取key中的多个filed的值
8hgetall获取全部的数据(就是key对应的map)

3、redis与memcache的区别?

1、存储方式:memcache把数据全部存储在内存中,掉电后数据就丢失了;redis把部分数据存储到硬盘,提供了持久化策略

2、数据类型:memcache所有的值都是字符串类型;redis支持多种数据类型

3、redis的速度比memcached快很多

4、Redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求

4、redis如何做持久化的?

1、RDB持久化(默认支持,无需配置)

该机制是指在指定的时间间隔内将内存中的数据集快照写入磁盘;是数据全量备份

2、AOF持久化

该机制将以日志的形式记录服务器所处理的每一个写操作,在Redis服务器启动之初会读取该文件来重新构建数据库,以保证启动后数据库中的数据是完整的;是执行命令的备份

实现原理:redis调用系统fork()函数创建一个子进程,子进程将数据写入一个临时的rdb文件,当子进程完成对临时的rdb文件的写入时,redis用新的rdb文件替换原有的rdb文件,并删除旧的rdb文件

5、单线程的redis为什么这么快?

1、纯内存操作

2、单线程操作,减少了频繁上下文的切换

3、采用了非阻塞I/O多路复用机制

6、什么是缓存雪崩?怎么解决?

缓存雪崩(多个热点key都过期)是:大量缓存集中在某一个时间段失效,在失效的时候,也会给后端系统(DB)带来很大压力

解决方法是:

1、缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生;

2、缓存预热;

3、互斥锁,实现代码请阅读:

互斥锁解决缓存雪崩问题(一)_zhangjia_happy的博客-CSDN博客

互斥锁解决缓存雪崩问题(二)_zhangjia_happy的博客-CSDN博客

7、什么是缓存穿透?怎么解决?

缓存穿透(查询不存在数据)是:key对应的数据在数据源并不存在,每次针对此key的请求从缓存获取不到,请求都会到数据源,从而可能压垮数据源。比如用一个不存在的用户id获取用户信息,不论缓存还是数据库都没有,若黑客利用此漏洞进行攻击可能压垮数据库

解决方法是:

1、从缓存取不到的数据,在数据库中也没有取到,这时也可以将key-value对写为key-null,缓存有效时间可以设置短点,如30秒(设置太长会导致正常情况也没法使用)。这样可以防止攻击用户反复用同一个id暴力攻击
2、采用布隆过滤器,将所有可能存在的数哈希到一个足够大的binmap中,一个一定不存在的数据会被这个bitmap拦截掉,从而避免了对底层存储系统的查询压力

8、什么是缓存击穿?怎么解决

缓存击穿(某个热点key缓存失效了)是:缓存中没有但数据库中有的数据,假如是热点数据,那key在缓存过期的一刻,同时有大量的请求,这些请求都会击穿到DB,造成瞬时DB请求量大、压力增大。

和缓存雪崩的区别在于这里针对某一key缓存,后者则是很多key。

解决方法是:

设置热点数据不过期,定时任务定时更新缓存,或者设置互斥锁

9、缓存预热

缓存预热就是系统上线后,将相关的缓存数据直接加载到缓存系统。这样就可以避免在用户请求的时候,先查询数据库,然后再将数据缓存的问题!用户直接查询事先被预热的缓存数据!

实现方法:

1、项目启动的时候把数据加载到缓存,参考

Springboot初始化加载数据的方法_zhangjia_happy的博客-CSDN博客

2、定时器把数据加载到缓存

10、缓存过期原理

1、定时去清理过期的数据

2、懒加载的方式清理数据,指的是当获取数据的时候,判断数据是否过期,若过期则删除

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhangjia_happy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值