1.redis是什么

redis是基于内存存储Key-Value键值对的高性能缓存数据库,它是一个Nosql类型非关系型数据库,它的数据完全在内存当中,所以存取非常快,被后端人才经常用做缓存数据库这块,而且他是单线程的,采用的队列模式将并发访问变为串行访问,消除了关系型数据库串行控制的开销。

2.redis的特点

由于它是一个基于内存存储的缓存数据库,所以速度超级快,他的查找和操作的时间复杂度都是O(1),并且支持多种数据类型的存储,能存储String、list、set,、hash、sorted set。但是缺点是它受到物理内存的限制,不能用来存储海量的数据进行读写。

3.redis存储的数据类型

1.String:以下是操作它的常用命令:
set/get/decr/incr/mget等。
2.List:以下是操作它的常用命令:
lpush/rpush/lpop/lrange等。
这个类型让redis可以有很多的应用场景,如关注列表,微博的粉丝列表,消息队列等,都可以用list来实现。
3.Set,操作它常用的命令有sadd/spop/smembers等。这个数据类型和List类似,都可以做列表功能,但是set是可以自动去重的,当需要有去重的时候,我们可以选择它来存储。
4.Hash,操作它常用命令有hget/hset/hgetall等。hash适合我们存储一些对象的时候使用,比如我们可以存储一些商品的信息,格式:key=productId ,value={“id”:1,“name”:“苹果”,“price”:10}
5.Sorted set ,操作它常用命令有zadd/zrange/zrem等。使用场景跟set类似,但它是自动有序的,它提供了一个额外的优先级score参数来提供排序,并且可以自动排序,可以用来做排行榜。
他的内部实现:sorted set的底层使用HashMap和跳跃表来保证数据的存储和有序,HashMap里放的是成员到score的映射,而跳跃表放的是所有成员,排序是根据HashMap里的score,使用跳跃表可以让查询更加高效。

4.Redis 挂掉之后,如何再重启服务器数据可以恢复

redis有自己的持久化机制,可以将内存中的数据持久化到硬盘里面去来保证数据持久化,当redis服务器重启时候可以读取硬盘里面的文件来重新加载的内存中,就可以恢复原来的数据。
RDB是redis默认的持久化机制,它是以快照的形式将数据保存到硬盘的二进制文件里的,产生一个dump.rdb文件,可以通过配置文件中的save来定义快照的周期。这种方式性能好,但是数据不是很完整,容易丢失一部分。
AOF也是redis的一种持久化机制,它是通过Write函数来将操作过redis数据库的命令追加到文件的最后,当重启服务器时候会重新执行文件中的写的命令来重建数据库的数据。这个方式数据完整,但是执行的文件比较大时,会很慢,可能导致服务卡顿。
如果这两种都开启了,重启时候会优先选择AOF这种方式。

5.缓存雪崩

定义:在同一时间出现了大面积缓存过期,本应该访问缓存的的数据请求都去访问数据库了,造成数据库压力太大而使数据库宕机,系统崩溃。
解决方案:可以考虑用加锁的方式或队列的方式来保证大量的线程不会对数据库一次性进行读写操作,从而避免失效时大量的请求落到数据库上。

6.缓存穿透

定义:是指用户先在缓存中查询不到数据,然后又在数据库查不到数据,两次都没有命中,如果是很多用户,这样会给数据库压力造成很大,这个就属于缓存穿透。
解决方案:最常用的办法布隆过滤器,将所有可能存在的数据哈希到一个超级大的bitmap中,一个不存在的数据会被这个bitmap拦截,从而避免了对数据库的查询压力。

7.缓存击穿

定义:指一个很热点的key,大量的并发请求同时对这个key进行访问,当这个key在失效的瞬间,仍然有大量的请求访问就会穿破缓存,从而直接请求数据库。
解决方案:在访问key之前,采用setnx(set if not exists)来设置另一个短期key来锁住当前key的访问,访问结束再删除该短期key。

8.业务需要将大量的key设置相同过期时间,应当注意什么

大量的key过期时间设置相同,刚好到时间时候,redis可能会出现短暂的卡顿,我们可以在时间上加一个随机值,让过期时间分散一些。

9.Redis分布式锁

先用setnx来争抢锁,抢到之后,再用expire给锁加一个过期时间防止锁忘记了释放,我们也可以使用del key 来释放锁。

10.Redis如何做消息队列

正常情况使用list数据类型作为队列,rpush用来生产消息,lpop用来消费消息。当lpop没有消息的时候,可以让他sleep,当然List中还有个指令叫blpop,在没有消息的时候,也可以使用它来阻塞,一直到消息过来。
如果是做延时队列的话,我们可以使用它的Sorted set数据类型,用时间戳来作为score,消息内容作为key调用zadd指令来生产消息,消费者用zrangebyscore指令获取N秒之前的数据轮询进行处理。

11.如何解决 Redis 的并发竞争问题

Redis的并发竞争问题是指多个系统同时对一个key进行的操作,但是最后执行的顺序和我们期望的顺序不同,这样也就导致了结果的不同。
解决方案:
1.客户端角度,为保证每个客户端间正常有序与Redis进行通信,对客户端读写Redis操作采用内部锁synchronized。
2.服务器角度,利用setnx实现锁(分布式锁)

12.redis的过期策略以及内存淘汰机制

过期策略采用的是定期删除和惰性删除策略,定期删除是redis默认每过100ms检查是否有过期的key,如果有就删除,它是随机抽取进行检查,并不是对所有的key都进行检查,如果只用定期删除策略,会造成很多key到时间没有被删除。这个时候惰性删除就闪亮登场了,当你获取某个key时,redis会检查这个key是否已经过期,如果过期就会删除。当然也有一种情况就是定期删除没有删除key(定期删除失效),你也没有请求key(惰性删除也失效)这样就会导致redis的内存会越来越高,这个时候就应该采用内存淘汰机制。

内存淘汰策略有6种:
volatile-lru:从已设置过期时间的数据集中挑选最近最少使用的数据淘汰
volatile-ttl:从已设置过期时间的数据集中挑选将要过期的数据淘汰
volatile-random:从已设置过期时间的数据集中随机选择数据淘汰
allkeys-lru:从数据集中挑选最近最少使用的数据淘汰
allkeys-random:从数据集中随机选择数据淘汰
no-enviction:禁止驱逐数据,新写入操作会报错

使用策略规则:
1、如果数据呈现幂律分布,也就是一部分数据访问频率高,一部分数据访问频率低,则使用allkeys-lru
2、如果数据呈现平等分布,也就是所有的数据访问频率都相同,则使用allkeys-random

以上是我总结面试过程中,经常被问到Redis的相关问题,大家可以参考一下,希望能够帮助到你们,让你们在这块准备的充分一点,因为这块问题是个难点加重点,基本上简历中出现Redis,面试官就会问关于它的相关问题。