1.Redis有那些数据结构

​ 字符串、字典Hash、列表List、集和Set、有序集和SortedSet。

​ ….加分项

​ BitMap、Geo、HyperLogLog、

应用场景补充

​ 字符串:常规的key-value缓存应用。常用计数器:微博数,粉丝数

​ hash: 存储部分变更数据,如用户信息等。

​ list: 可以构建消息队列

​ set: 交集、并集、差集,去重,找共同的爱好……

​ sortedset: 通过score对元素进行优先排序,带权重的消息队列

2.大量key同一时间过期

​ 如果大量的key在同一时间过期,那么到过期的时间点Redis会发生卡顿现象,严重的话会造成缓存雪崩,解决方法是在设置失效时间时加上一个随机值。

3.Redis分布式锁

​ 分布式锁是为了解决多进程之间的同步,redis可以实现分布式锁。可以用setnx原子操作来获得锁(),抢到之后用expire给锁添加过期时间。

1
2
setnx k v
expire k timeout

追问:如果setnx获取锁成功,但线程执行expire之前崩溃,会如何,怎样解决?

​ 此时,这个锁将一直被持有,无法释放。可以用同时具有setnx和expire的原子指令***解决:

1
set k v nx[key必须不存在] [ex t 秒级]/[px t 毫秒级]

4.如何在Redis中查询大量的具有固定前缀的key

​ 可以利用keys指令查询,但该指令会一次性查找全部符合条件的key,会造成卡顿(Redis是单线程的):

1
keys [pattern]

​ 因为keys指令需要全部遍历,数据量很大的话,需要一定的执行时间。由于Redis是单线程,所以其他服务会暂停,直到keys指令结束。为避免此情况发生,可以使用scan指令,scan指令可以无阻塞的取出指定模式的key列表(每次执行会找到若干个符合条件的key),但会出现重复,所以客户端需要去重:

1
scan cursor[0代表从头开始] [MATCH pattern] [COUNT num]

​ 由于scan不是一次性遍历(增量式迭代),所以在全部扫描完成时可能有些key会发生变化。

5.Redis异步队列

​ Redis可以实现异步队列,一般用List实现,rpush生产消息,lpop消费消息。当lpop没有消息可消费时,需要sleep一会儿重试。

​ 除了sleep还可以使用blpop指令,在没有消息时,他会阻塞住直到消息到来。

一次生产,多次消费如何实现?

​ 可以使用pub/sub主题订阅模式,可以实现1:N的消息队列

pub/sub有何问题

​ 在消费者下线情况下,生产的消息会丢失,可以使用RabbitMQ。

如何实现延时队列

​ 可以使用有序集和sortedset,将时间作为score,消息内容作为key,调用zadd来生产消息,消费者通过zrangebyscore指令获取N秒前的消息.

6.Redis持久化

​ Redis持久化有两种方式:RDB镜像全量持久化、AOF增量持久化。

RDB:

​ Redis每隔一段时间可以将所有数据备份到磁盘,Redis会fork一个子线程进行RDB操作,子线程创建后,父子线程共享数据段,父线程将继续提供服务,写脏的页面数据会和子线程分开(cow, copy on write)。cow数据未发生变化时,父子线程共享数据,一旦发生变化,子线程才会分配空间存储数据。

​ 自动触发:配置文件中,可以配置经过多少次save就触发;

​ 手动触发:通过bgsave命令,会fork一个子进程。

AOF:

​ 将Redis执行的指令记录到磁盘,sync属性可以支持每条指令都写到磁盘,但代价较高。可以设置每秒sync,这样最多会丢失1s的数据。

​ AOF日志会随着时间不断变大,可以通过AOF重写解决。首先读取数据库中所有键值的状态,使用一条命令替代前面多条操作语句。使用bgrewriteaof命令进行重写,重写时会fork一个子进程进行重写,主进程将重写期间的命令放到重写缓冲区中,待重写完成将其添加到AOF文件中。

​ RDB无法实时持久化,AOF文件较大(AOF重写解决)。

7.Pipline是什么

​ 普通的请求中,每次请求都对应一次IO操作等待(往返时延),而Pipline会将所有请求转化为一次IO操作(一次往返)。使用前提是指令之间没有因果相关性。

8.Redis的同步机制

​ Redis同步机制有两种:主从同步

主从同步:

  • 从服务器向主服务器发送sync命令
  • 主服务器收到sync命令,开始执行bgsave命令生成RDB文件,并用缓存开始记录此后执行的所有写命令
  • 主服务器bgsave完成之后,向从服务器发送RDB文件,继续在缓存中记录写命令
  • 从服务器收到RDB文件,丢弃所有旧数据,载入RDB
  • 主服务器向从服务器发送缓存中的命令
  • 从服务器载入RDB后开始接收命令请求,执行来自主服务器中的缓存命令

通过以上操作,全量同步完成,以后主服务器向从服务器发送所有的写操作进行增量同步

9.Redis集群

​ Redis Sentinal着眼于高可用,在master宕机时会自动将slave提升为master,继续提供服务。

​ Redis Cluster着眼于扩展性,在单个Redis内存不足时,使用Cluster进行分片存储。

10.Redis为什么快

  • 数据放在内存中,而且其存储数据类似HashMap,所以速度很快

  • 单线程,没有线程上下文切换开销

  • 多路IO复用,可以一个线程监听多路IO

    研究表明,redis的瓶颈在网络时延

11.Redis与memcached区别

  • memcached只支持字符串,redis支持更丰富的数据类型
  • redis支持数据持久化
  • redis支持数据备份,即master-slave

12.redis数据过期回收

  • 定期回收

    没过一段时间去抽查一部分数据是否过期,过期就删除。

  • 惰性删除

    使用key时,先判断是否过期,过期则删除。