1、Redis如何实现延时队列

使用sortedset,使用时间戳做score, 消息内容作为key,调用zadd来生产消息,消费者使用zrangbyscore获取n秒之前的数据做轮询处理。

2、redis缓存击穿是什么?如何解决?

缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力。和缓存雪崩不同的是,缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。
解决方案:
设置热点数据永远不过期。

3、redis缓存穿透是什么?如何解决?

缓存穿透是指缓存和数据库中都没有的数据,导致所有的请求都落到数据库上,造成数据库短时间内承受大量请求而崩掉。
解决方案

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

4 redis缓存雪崩是什么?如何解决?

缓存雪崩是指缓存同一时间大面积的失效,所以,后面的请求都会落到数据库上,造成数据库短时间内承受大量请求而崩掉。
解决方案
缓存数据的过期时间进行错开,防止同一时间大量数据过期现象发生。

5、Redis事务保证原子性吗,支持回滚吗

Redis中,单条命令是原子性执行的,但事务不保证原子性,且没有回滚。事务中任意命令执行失败,其余的命令可以仍会被执行。

6、Redis事务支持隔离性吗

Redis 是单进程程序,并且它保证在执行事务时,不会对事务进行中断,事务可以运行直到执行完所有事务队列中的命令为止。因此,Redis 的事务是总是带有隔离性的。

7、Redis的线程模型是咋样的?

redis基于Reactor模式开发了网络事件处理器,这个处理器被称为文件事件处理器(file event handler)。它的组成结构为4部分:多个套接字、IO多路复用程序、文件事件分派器、事件处理器。因为文件事件分派器队列的消费是单线程的,所以Redis才叫单线程模型。

  • 文件事件处理器使用 I/O 多路复用(multiplexing)程序来同时监听多个套接字,并根据套接字目前执行的任务来为套接字关联不同的事件处理器。
  • 当被监听的套接字准备好执行连接应答(accept)、读取(read)、写入(write)、关闭(close)等操作时,与操作相对应的文件事件就会产生,这时文件事件处理器就会调用套接字之前关联好的事件处理器来处理这些事件

虽然文件事件处理器以单线程方式运行,但通过使用 I/O 多路复用程序来监听多个套接字,文件事件处理器既实现了高性能的网络通信模型,又可以很好地与 redis 服务器中其他同样以单线程方式运行的模块进行对接,这保持了Redis 内部单线程设计的简单性。

8、Redis的内存淘汰策略有哪些

Redis的内存淘汰策略是指在Redis的用于缓存的内存不足时,怎么处理需要新写入且需要申请额外空间的数据。全局的键空间选择性移除

  • noeviction:当内存不足以容纳新写入数据时,新写入操作会报错
  • allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key。(这个是最常用的)
  • allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个key

设置过期时间的键空间选择性移除

  • volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的key
  • volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个key
  • volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的key优先移除

9、Redis的内存用完了会发生什么?

如果达到设置的上限,Redis的写命令会返回错误信息(但是读命令还可以正常返回。)或者你可以配置内存淘汰机制,当Redis达到内存上限时会冲刷掉旧的内容。

10、请对比下redis持久化之RDB和AOF?

  1. redis默认开启RDB持久化方式,在指定的时间间隔内,执行指定次数的写操作,则将内存数据写入到磁盘中
  2. RDB持久化适合大规模的数据恢复但他的数据一致性和完整性较差
  3. redis需要手动开启AOF持久化方式,默认是每秒将写操作日志追加到AOF文件中
  4. AOF的数据完整性比RDB高,但记录数据多了,会影响恢复的效率
  5. Redis针对AOF文件大的问题,提供重写的瘦身机制
  6. 若只打算用Redis做缓存,可以关闭持久化
  7. 若打算用Redis的持久化,建议RDB和AOF都开启。其实RDB更适合做数据的备份,留一手,AOF出问题了,还有RDB.

11 请说说对redis事务的理解?

Redis事务的概念:
Redis事务的本质是一组命令的集合。事务支持一次执行多个命令。一个事务中所有命令都会被序列化。在事务执行过程,会按照顺序串行化执行队列中的命令,其他客户端提交的命令请求不会插入到事务执行命令序列中。
总结:Redis事务就是一次性、顺序性、排他性的执行一个队列中的一系列命令

Redis事务没有隔离级别的概念:
edis没有事务隔离界别

Redis不保证原子性:
Redis中,单条命令是原子性执行的,但事务不保证原子性,且没有回滚。事务中任意命令执行失败,其余的命令仍会被执行。

Redis事务的三个阶段:
1.开始事务
2.命令入队
3.执行事务

Redis事务相关命令:
watch key1 key2 … : 监视一或多个key,如果在事务执行之前,被监视的key被其他命令改动,则事务被打断(类似乐观锁)
multi: 标记一个事务块的开始(queued)
exec: 执行所有事务块的命令(一旦执行exec后,之前加的监控锁都会被取消掉)
discard: 取消事务,放弃事务块中的所有命令
unwatch: 取消watch对所有key的监控

Redis事务使用案例:
(1)正常执行

multi   //开启事务
//命令入队
set k1 v1
set k2 v2
set k3 v3
//执行事务
exec

(2)放弃事务

multi   //开启事务
//命令入队
set k1 v1
set k2 v2
set k3 v3
//取消事务
discard

(3)若在事务队列中存在命令性错误,则执行exec命令时,所有命令都不会执行

multi   //开启事务
//命令入队
set k1 v1
set k2 v2
set k3 v3
getset k3 //错误命令
set k4 v4
//执行事务,报错
exec

get k4 //命令未执行

(4)若在事务队列中存在语法性错误,则执行exec命令时,其他正确命令会被执行 ,错误命令抛出异常

multi   //开启事务
//命令入队
incr k1 //语法错误
set k2 v2
set k3 v3
getset k3 //错误命令
set k4 v4
//执行事务,第一条命令报错,其他正确执行
exec

(5)使用watch
案例一:使用watch检测balance,事务期间balance数据未变动,事务执行成功

watch balance //检测可用余额数,初始为100
multi //开启事务
decrby balane 20 //消费20后,可用余额-20
incrby debt 20 //应还余额+20
exec
结果
balance 80
debt 20

案例二:使用watch检测balance,在开启事务后(标注1处),在新窗口执行标注2中的操作,更改balance的值,模拟其他客户端在事务执行期间更改watch监控的数据,然后再执行标注1后命令,执行EXEC后,事务未成功执行

watch balance //检测balance 的值,初始为80
multi //开启事务 标注1
decrby balance 20 //可用余额-20
incrby debt 20 //应还余额+20
exec //执行事务
结果 事务执行失败

一旦执行exec开启事务的执行后,无论事务是否执行成功,watch对变量的监控都将被取消。故当事务执行失败后,需重新执行watch命令对变量进行监控,并开启新的事务进行操作。

总结:
watch指令类似于乐观锁,在事务提交时,如果watch监控的多个key中任意key的值已经被其他客户端更改,则使用exec执行事务时,事务队列将不会被执行,同时返回nullmulti-bulk应答以通知调用者事务执行失败。

12 Redis有哪些优缺点

优点

  • 读写性能优异。
  • 支持数据持久化,支持AOF和RDB两种持久化方式。
  • 支持事务,Redis的所有操作都是原子性的,同时Redis还支持对几个操作合并后的原子性执行
  • 数据结构丰富,除了支持string类型的value外还支持hash、set、zset、list等数据结构
  • 支持主从复制,主机会自动将数据同步到从机,可以进行读写分离

缺点

  • 数据库容量受到物理内存的限制,不能用作海量数据的高性能读写,因此Redis适合的场景主要局限在较小数据量的高性能操作和运算上
  • Redis 不具备自动容错和恢复功能,主机从机的宕机都会导致前端部分读写请求失败,需要等待机器重启或者手动切换前端的IP才能恢复
  • 主机宕机,宕机前有部分数据未能及时同步到从机,切换IP后还会引入数据不一致的问题,降低了系统的可用性
  • Redis 较难支持在线扩容,在集群容量达到上限时在线扩容会变得很复杂。为避免这一问题,运维人员在系统上线时必须确保有足够的空间,这对资源造成了很大的浪费

13 redis的list队列先进先出如何解决插队问题?

通常使用一个list来实现队列操作,这样有一个小限制,所以的任务统一都是先进先出,如果想优先处理某个任务就不太好处理了,这就需要让队列有优先级的概念,我们就可以优先处理高级别的任务,实现方式有以下几种方式:

1)单一列表实现:队列正常的操作是左进右出(lpush,rpop)为了先处理高优先级任务,在遇到高级别任务时,可以直接插队,直接放入队列头部(rpush),这样,从队列头部(右侧)获取任务时,取到的就是高优先级的任务(rpop)

2)使用两个队列,一个普通队列,一个高级队列,针对任务的级别放入不同的队列,获取任务时也很简单,redis的BRPOP命令可以按顺序从多个队列中取值,BRPOP会按照给出的 key 顺序查看,并在找到的第一个非空 list 的尾部弹出一个元素,redis> BRPOP list1 list2 0
list1 做为高优先级任务队列 list2 做为普通任务队列
这样就实现了先处理高优先级任务,当没有高优先级任务时,就去获取普通任务
方式1最简单,但实际应用比较局限,方式3可以实现复杂优先级,但实现比较复杂,不利于维护方式2是推荐用法,实际应用最为合适

14 redis如何优化

1、建立redis连接池
2、建立redis集群和一主多从
3、设置key有效期
4、设置bit级别的存储,如GETBIT 和 SETBIT等
5、想要一次添加多条数据的时候可以使用管道
6、根据业务需要选择合适的数据类型,并为不同的应用场景设置相应的紧凑存储参数。
7、当业务场景不需要数据持久化时,关闭所有的持久化方式可以获得最佳的性能以及最大的内存使用量
8、如果需要使用持久化,根据是否可以容忍重启丢失部分数据在快照方式与语句追加方式之间选择其一,不要使用虚拟内存以及diskstore方式
9、不要让你的Redis所在机器物理内存使用超过实际内存总量的3/5

15 使用redis你lpop一条数据后,插入数据库失败怎么办?

一般使用list结构作为队列,rpush生产消息,lpop消费消息。当lpop没有消息的时候,要适当sleep一会再重试。
缺点:在消费者下线的情况下,生产的消息会丢失,得使用专业的消息队列如rabbitmq等。

16 redis支持哪几种常见数据类型?

string 字符串
hash 哈希
list 列表
set 集合
zset 有序集合

17 使用过Redis分布式锁么,它是怎么实现的?

先拿setnx来争抢锁,抢到之后,再用expire给锁加一个过期时间防止锁忘记了释放

Redis为单进程单线程模式,采用队列模式将并发访问变成串行访问,且多客户端对Redis的连接并不存在竞争关系Redis中可以使用SETNX命令实现分布式锁

当且仅当 key 不存在,将 key 的值设为 value。若给定的 key 已经存在,则 SETNX 不做任何动作

ETNX 是『SET if Not eXists』(如果不存在,则 SET)的简写。

返回值:设置成功,返回 1 。设置失败,返回 0 。

Redis面试题_缓存

使用SETNX完成同步锁的流程及事项如下:
使用SETNX命令获取锁,若返回0(key已存在,锁已存在)则获取失败,反之获取成功
为了防止获取锁后程序出现异常,导致其他线程/进程调用SETNX命令总是返回0而进入死锁状态,需要为该key设置一个“合理”的过期时间
释放锁,使用DEL命令将锁数据删除

18 Redis与Memcached的2个主要区别

  1. Redis不仅支持简单的k/v类型的数据,同时还支持list、set、zset(sorted set)、hash等数据结构的存储,使得它拥有更广阔的应用场景
  2. Redis最大的亮点是支持数据持久化,它在运行的时候可以将数据备份在磁盘中,断电或重启后,缓存数据可以再次加载到内存中,只要Redis配置的合理,基本上不会丢失数据

19 说说你对redis哨兵的理解

redis服务器毫无征兆的罢工是麻烦事,如何保证备份的机器是原始服务器的完整备份呢?这时候就需要哨兵和复制。
Sentinel可以管理多个Redis服务器,它提供了监控,提醒以及自动故障转移的功能,Replication则是负责让一个Redis服务器可以配备多个备份的服务器。

  1. Redis为什么快?

1)内存数据库.数据存储在内存中,不需要磁盘的IO
2)单线程,避免了线程切换的上下文开销
3)高效的数据结构
4)合理的数据编码
5)采用多路IO复用,非阻塞IO

  1. Redis为什么是单线程?
    Redis是内存数据库,CPU不会成为Redis的瓶颈,而采用多线程,会引起CPU资源的竞争,线程之间切换也会增加开销。