面试题-Redis篇
Redis是一个非关系数据库,我们项目中主要用它来存储热点数据的,减轻数据库的压 力.我们项目中很多地方用到了redis,比如说APP端首页热点数据的展示,还有在以前 的项目中我们也用过redis来实现单点登录,至于redis为什么快?主要有这么几点, 第一呢就redis的数据都是存储到内存中的加载比较快,第二点呢是redis中数据结构 比较简单,还有第三个原因是他是单线程的,避免了上下文进行切换和竞争条件,第四 点他使用的是多路I/O复用模型,非阻塞IO(红色字体作为理解).第五来说redis使用 的底层模型不同,Redis直接自己构建的VM机制
(1)多路 I/O 复用模型 多路I/O复用模型是利用 select、poll、epoll 可以同时监察多个流的 I/O 事件 的能力,在空闲的时候,会把当前线程阻塞掉,当有一个或多个流有 I/O 事件时, 就从阻塞态中唤醒,于是程序就会轮询一遍所有的流(epoll 是只轮询那些真正发 出了事件的流),并且只依次顺序的处理就绪的流,这种做法就避免了大量的无用操 作。
这里“多路”指的是多个网络连接,“复用”指的是复用同一个线程。 采用多路 I/O 复用技术可以让单个线程高效的处理多个连接请求(尽量减少网络 IO 的时间消 耗),且 Redis 在内存中操作数据的速度非常快,也就是说内存内的操作不会成为 影响Redis性能的瓶颈,主要由以上几点造就了 Redis 具有很高的吞吐量。
2.你们在项目中是怎么操作redis的?有过封装 么?
项目中,我们一般都通过springData操作的redis,他底层也是整合redis官方提供 的jedis工具包来操作redis,我们开发的时候用的是单机版。
3.redis持久化方式有几种?
有RDB和AOF这两种,RDB是一种快照的方式来存储的,这也是redis的默认的持久化 方式,每隔一段对数据进行一次存储,
save 900 1 #在900秒(15分钟)之后,如果至少有1个key发生变化,则dump内存快 照。 save 300 10 #在300秒(5分钟)之后,如果至少有10个key发生变化,则dump内存 快照。 save 60 10000#在60秒(1分钟)之后,如果至少有10000个key发生变化,则dump 内存快照。 还有一种是AOF是,通过配置appendfsync的三种状态,always: 每次操作都会立 即写入aof文件中 everysec: 每秒持久化一次(默认配置)no: 不主动进行同步操 作,默认30s一次只要数据发生改变都会保存到硬盘一份,这种方式对数据的保存完 整性比较高,但是性能比较差。而RDB存在的问题主要是服务器宕机或者断电,会造 成数据丢失
4.使用redis缓存有没有遇到什么问题 ?
你是说的那个缓存雪崩和缓存穿透,,我知道缓存雪崩是因为redis中多个key同时失 效后,又遇到高并发后就会造成大量的请求直接请求数据库,导致数据库服务器宕机 的情况,一般这种情况我们会给redis中的key设置不同的生命周期就能解决,或者是 我们给使用分布式锁来解决;还有缓存穿透的话就是大并发请求过来,查询一个连数 据库都没有的数据,频繁的请求数据库导致数据库宕机,这种解决方案是我们会存到 缓存一个key值value为空,给个失效时间,也可以避免这种问题.
5.说一下redis集群吗?
Redis本身就支持集群操作redis_cluster,另外redis还支持主从复制,以前的老 版本中有一个哨兵模式,在主服务器宕机时,从服务器可以自动转换为主服务器。我 们公司搭建的redis集群是用的ruby脚本配合搭建的,我们一共搭建了6台服务器,3 主3备,他们之间通信的原理是有一个乒乓协议进行通信的,他们判断一个节点的状态 是用投票选举机制判断的,半数以上判断一个接口是宕机了的话,备用节点就会启动, 对,我再给你说下一他们往里存储数据的机制吧,其实这个redis搭建好集群以后每个 节点都存放着一个hash槽,每次往里存储数据的时候,redis都会根据存储进来的key 值算出一个hash值,通过这个hash值可以判断到底应该存储到哪一个哈希槽中,取的 时候也是这么取的,这就是我了解的redis集群.
6.在项目那一块用过,使用场景?
我们在项目的活动模块用过,APP端的首页展示的数据都是使用redis存储的热点数 据,因为用户进入APP的时候首先进入是首页,使用的hash数据类型存储首页信息,特 卖模块中也用过redis,用它的list数据类型.
7.redis的数据类型?
我了解的有
string,list、set、hash、sortedSet list,
我们可以向list的两端添加数据 集合set,存放的数据是无序的,集合中的数据是不重复的,由于它是无序的,所以 不能通过下标来获取制定元素、
order set有序集合、 hash 实际上
我们常用的也就是string 和hash redis是通过key-value存储的
set key value string hset key value hget key value
8.Redis中的事务如何实现? redis中的分布式 锁如何实现?
我知道你说的那个redis的事务,就那个命令multi开启事务exec执行事务中的所有 操作什么的命令,我们开发的时候没有用到过,我们用的是Redis的分布式锁,用过里 面的setnx结合的lua脚本去使用的,但是这种锁单节点的Redis服务器使用没有问 题,我们测过差不多能抗住3000的并发,如果是Redis集群就不行了,因为他那个锁有 可能在主服务还没有同步到从服务器的时候,主服务器宕机了,锁就找不到了,我们就 得用Redisson这个框架去实现了,他里面提供的一个监控锁的机制,这个框架提供了 很多种分布式锁的解决方案,比如可重入锁,还有读写锁,还有什么异步锁,直接使用 就行.里面我的记的有trylock和unlock这些个方法,
9.如何使用redis去实现一个消息队列
我知道的redis实现消息队列的方式有两种,第一种是用他本身的list数据类型,他 有一个lpush和rpuop命令,可以使用lpush从集合左边添加进去数据,使用rpop命令 从右边拿取数据。 第二种实现方式:redis还提供了一组命令可以让开发者实现"发布/订阅" (publish/subscribe)模式。"发布/订阅"模式也可以实现进程间的消息传递,但 是我们没有用过这种,我们项目中的消息队列都是用RabbitMQ实现的
10.Redis和mongoDB的区别?
mongodb是非关系型数据库最像关系型数据库的一种数据库,有数据库,集合和文档 的关联,集合就相当于咱们关系型数据库里的表,文档就是一条数据,他存储数据的 方式是以bson方式进行存储的。但是Redis是key和value方式存储的,在项目中我们 可以把一些频繁访问的数据存到redis中,不频繁的访问数据存到mysql数据库中,可 以给mysql数据库减轻压力.
11.Redis在你们项目中起到的主要作用是什么?
主要就是缓存热点数据的,减轻服务器压力.
12.Redis是如何同步的?
其实redis里的数据来源于数据库,比如说我们前台的广告位展示的时候,数据是存 在redis中的,数据库里的数据更新以后,我们会把redis里的缓存清空一下。让他 第一次查的时候从数据库里查,第二用户再进来的时候就是从redis中取了。
13.Redis的自动清理机制?Redis 的内存回收 机制?
你是说的是redis服务器内存满了如何清理是吧,可以在配置文件中设置: redis最大内存不足"时,数据清除策略,默认为"volatile-lru"。volatile-lru - >对"过期集合"中的数据采取LRU(近期最少使用)算法.还有一个策略是volatilerandom ->对"过期集合"中的数据采取"随即选取"算法,并移除选中的K-V,直到"内
存足够"为止.
14、Redis缓存雪崩、缓存穿透、缓存击穿
缓存雪崩:缓存时采用了相同的过期时间,在同一时刻出现大面积的缓存过期,数据 库压力大,雪崩; 解决:1加锁( 最多的解决方案)或者队列来保证不会有大量的线程对数据库一次 性进行读写,2缓存失效时间分散开 缓存穿透:相当于进行了两次无用的查询。缓存命中率问题。解决:1布隆过滤器 (Bitmap: 典型的就是哈希表)2存空设置过期时间 缓存击穿:指一个key非常热点,大并发集中对这个key进行访问,当这个key在失效 的瞬间,仍然持续的大并发访问就穿破缓存,转而直接请求数据库。解决:set if not exists来设置另一个短期key来锁住当前key的访问,访问结束再删除该短期 key。SETNX lock-key value1使用redis锁,redis的缓存每命中一次,就给命中 的缓存增加一定过期时间
15、redis工作原理
1纯内存操作 2单线程操作,避免了频繁的上下文切换 3采用了非阻塞I/O多路复用 机制(AIO)
16、Redis事务
MULTI(开启一个事务,它总是返回OK)、EXEC(执行所有事务块内的命令)、 DISCARD(清空事务队列,并放弃执行事务)和WATCH (CAS)
17、redis原子性
1单线程 2API原子操作 3使用redis事务