一、为何使用redis面试
(一)性能redis
咱们在碰到须要执行耗时特别久,且结果不频繁变更的SQL,就特别适合将运行结果放入缓存。这样,后面的请求就去缓存中读取,使得请求可以迅速响应。数据库
(二)并发后端
在大并发的状况下,全部的请求直接访问数据库,数据库会出现链接异常。这个时候,就须要使用redis作一个缓冲操做,让请求先访问到redis,而不是直接访问数据库。缓存
2.使用redis有什么缺点服务器
(一)缓存和数据库双写一致性问题cookie
(二)缓存雪崩问题网络
(三)缓存击穿问题session
(四)缓存的并发竞争问题数据结构
三、单线程的redis为何这么快
(一)纯内存操做
(二)单线程操做,避免了频繁的上下文切换
(三)采用了非阻塞I/O多路复用机制
参照上图,简单来讲,就是。咱们的redis-client在操做的时候,会产生具备不一样事件类型的socket。在服务端,有一段I/0多路复用程序,将其置入队列之中。而后,文件事件分派器,依次去队列中取,转发到不一样的事件处理器中。
四、redis的数据类型,以及每种数据类型的使用场景
回答:一共五种
(一)String
这个其实没啥好说的,最常规的set/get操做,value能够是String也能够是数字。通常作一些复杂的计数功能的缓存。
(二)hash
这里value存放的是结构化的对象,比较方便的就是操做其中的某个字段。博主在作单点登陆的时候,就是用这种数据结构存储用户信息,以cookieId做为key,设置30分钟为缓存过时时间,能很好的模拟出相似session的效果。
(三)list
使用List的数据结构,能够作简单的消息队列的功能。另外还有一个就是,能够利用lrange命令,作基于redis的分页功能,性能极佳,用户体验好。本人还用一个场景,很合适---取行情信息。就也是个生产者和消费者的场景。LIST能够很好的完成排队,先进先出的原则。
(四)set
由于set堆放的是一堆不重复值的集合。因此能够作全局去重的功能。为何不用JVM自带的Set进行去重?由于咱们的系统通常都是集群部署,使用JVM自带的Set,比较麻烦,难道为了一个作一个全局去重,再起一个公共服务,太麻烦了。
另外,就是利用交集、并集、差集等操做,能够计算共同喜爱,所有的喜爱,本身独有的喜爱等功能。
(五)sorted set
sorted set多了一个权重参数score,集合中的元素可以按score进行排列。能够作排行榜应用,取TOP N操做。
五、redis的过时策略以及内存淘汰机制
redis采用的是按期删除+惰性删除策略。
为何不用定时删除策略?
定时删除,用一个定时器来负责监视key,过时则自动删除。虽然内存及时释放,可是十分消耗CPU资源。在大并发请求下,CPU要将时间应用在处理请求,而不是删除key,所以没有采用这一策略.
按期删除+惰性删除是如何工做的呢?
按期删除,redis默认每一个100ms检查,是否有过时的key,有过时key则删除。须要说明的是,redis不是每一个100ms将全部的key检查一次,而是随机抽取进行检查(若是每隔100ms,所有key进行检查,redis岂不是卡死)。所以,若是只采用按期删除策略,会致使不少key到时间没有删除。
因而,惰性删除派上用场。也就是说在你获取某个key的时候,redis会检查一下,这个key若是设置了过时时间那么是否过时了?若是过时了此时就会删除。
采用按期删除+惰性删除就没其余问题了么?
不是的,若是按期删除没删除key。而后你也没即时去请求key,也就是说惰性删除也没生效。这样,redis的内存会愈来愈高。那么就应该采用内存淘汰机制。
在redis.conf中有一行配置
# maxmemory-policy volatile-lru
该配置就是配内存淘汰策略的(什么,你没配过?好好检讨一下本身)
1)noeviction:当内存不足以容纳新写入数据时,新写入操做会报错。应该没人用吧。
2)allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key。推荐使用,目前项目在用这种。
3)allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个key。应该也没人用吧,你不删最少使用Key,去随机删。
4)volatile-lru:当内存不足以容纳新写入数据时,在设置了过时时间的键空间中,移除最近最少使用的key。这种状况通常是把redis既当缓存,又作持久化存储的时候才用。不推荐
5)volatile-random:当内存不足以容纳新写入数据时,在设置了过时时间的键空间中,随机移除某个key。依然不推荐
6)volatile-ttl:当内存不足以容纳新写入数据时,在设置了过时时间的键空间中,有更早过时时间的key优先移除。不推荐
ps:若是没有设置 expire 的key, 不知足先决条件(prerequisites); 那么 volatile-lru, volatile-random 和 volatile-ttl 策略的行为, 和 noeviction(不删除) 基本上一致。
六、redis和数据库双写一致性问题
分析:一致性问题是分布式常见问题,还能够再分为最终一致性和强一致性。数据库和缓存双写,就必然会存在不一致的问题。答这个问题,先明白一个前提。就是若是对数据有强一致性要求,不能放缓存。咱们所作的一切,只能保证最终一致性。另外,咱们所作的方案其实从根本上来讲,只能说下降不一致发生的几率,没法彻底避免。所以,有强一致性要求的数据,不能放缓存。
首先,采起正确更新策略,先更新数据库,再删缓存。其次,由于可能存在删除缓存失败的问题,提供一个补偿措施便可,例如利用消息队列。
七、如何应对缓存穿透和缓存雪崩问题
分析:这两个问题,说句实在话,通常中小型传统软件企业,很难碰到这个问题。若是有大并发的项目,流量有几百万左右。这两个问题必定要深入考虑。
回答:以下所示
缓存穿透,即黑客故意去请求缓存中不存在的数据,致使全部的请求都怼到数据库上,从而数据库链接异常。
解决方案:
(一)利用互斥锁,缓存失效的时候,先去得到锁,获得锁了,再去请求数据库。没获得锁,则休眠一段时间重试
(二)采用异步更新策略,不管key是否取到值,都直接返回。value值中维护一个缓存失效时间,缓存若是过时,异步起一个线程去读数据库,更新缓存。须要作缓存预热(项目启动前,先加载缓存)操做。
(三)提供一个能迅速判断请求是否有效的拦截机制,好比,利用布隆过滤器,内部维护一系列合法有效的key。迅速判断出,请求所携带的Key是否合法有效。若是不合法,则直接返回。
缓存雪崩,即缓存同一时间大面积的失效,这个时候又来了一波请求,结果请求都怼到数据库上,从而致使数据库链接异常。
解决方案:
(一)给缓存的失效时间,加上一个随机值,避免集体失效。
(二)使用互斥锁,可是该方案吞吐量明显降低了。
(三)双缓存。咱们有两个缓存,缓存A和缓存B。缓存A的失效时间为20分钟,缓存B不设失效时间。本身作缓存预热操做。而后细分如下几个小点
I 从缓存A读数据库,有则直接返回
II A没有数据,直接从B读数据,直接返回,而且异步启动一个更新线程。
III 更新线程同时更新缓存A和缓存B。
八、如何解决redis的并发竞争key问题
分析:这个问题大体就是,同时有多个子系统去set一个key。这个时候要注意什么呢?你们思考过么。须要说明一下,博主提早百度了一下,发现答案基本都是推荐用redis事务机制。博主不推荐使用redis的事务机制。由于咱们的生产环境,基本都是redis集群环境,作了数据分片操做。你一个事务中有涉及到多个key操做的时候,这多个key不必定都存储在同一个redis-server上。所以,redis的事务机制,十分鸡肋。
回答:以下所示
(1)若是对这个key操做,不要求顺序
这种状况下,准备一个分布式锁,你们去抢锁,抢到锁就作set操做便可,比较简单。
(2)若是对这个key操做,要求顺序
假设有一个key1,系统A须要将key1设置为valueA,系统B须要将key1设置为valueB,系统C须要将key1设置为valueC.
指望按照key1的value值按照 valueA–>valueB–>valueC的顺序变化。这种时候咱们在数据写入数据库的时候,须要保存一个时间戳。假设时间戳以下
系统A key 1 {valueA 3:00}
系统B key 1 {valueB 3:05}
系统C key 1 {valueC 3:10}
那么,假设这会系统B先抢到锁,将key1设置为{valueB 3:05}。接下来系统A抢到锁,发现本身的valueA的时间戳早于缓存中的时间戳,那就不作set操做了。以此类推。
其余方法,好比利用队列,将set方法变成串行访问也能够。总之,灵活变通。
9.Reids的特色
Redis本质上是一个Key-Value类型的内存数据库,很像memcached,整个数据库通通加载在内存当中进行操做,按期经过异步操做把数据库数据flush到硬盘上进行保存。由于是纯内存操做,Redis的性能很是出色,每秒能够处理超过 10万次读写操做,是已知性能最快的Key-Value DB。
Redis的出色之处不只仅是性能,Redis最大的魅力是支持保存多种数据结构,此外单个value的最大限制是1GB,不像 memcached只能保存1MB的数据,所以Redis能够用来实现不少有用的功能,比方说用他的List来作FIFO双向链表,实现一个轻量级的高性 能消息队列服务,用他的Set能够作高性能的tag系统等等。另外Redis也能够对存入的Key-Value设置expire时间,所以也能够被看成一 个功能增强版的memcached来用。
Redis的主要缺点是数据库容量受到物理内存的限制,不能用做海量数据的高性能读写,所以Redis适合的场景主要局限在较小数据量的高性能操做和运算上。
10.使用redis有哪些好处?
(1) 速度快,由于数据存在内存中,相似于HashMap,HashMap的优点就是查找和操做的时间复杂度都是O(1)
(2) 支持丰富数据类型,支持string,list,set,sorted set,hash
(3) 支持事务,操做都是原子性,所谓的原子性就是对数据的更改要么所有执行,要么所有不执行
(4) 丰富的特性:可用于缓存,消息,按key设置过时时间,过时后将会自动删除
11.redis相比memcached有哪些优点?
(1) memcached全部的值均是简单的字符串,redis做为其替代者,支持更为丰富的数据类型
(2) redis的速度比memcached快不少 (3) redis能够持久化其数据
12.Memcache与Redis的区别都有哪些?
1)、存储方式 Memecache把数据所有存在内存之中,断电后会挂掉,数据不能超过内存大小。 Redis有部份存在硬盘上,这样能保证数据的持久性。
2)、数据支持类型 Memcache对数据类型支持相对简单。 Redis有复杂的数据类型。
3)、使用底层模型不一样 它们之间底层实现方式 以及与客户端之间通讯的应用协议不同。 Redis直接本身构建了VM 机制 ,由于通常的系统调用系统函数的话,会浪费必定的时间去移动和请求。
13.redis常见性能问题和解决方案:
1).Master写内存快照,save命令调度rdbSave函数,会阻塞主线程的工做,当快照比较大时对性能影响是很是大的,会间断性暂停服务,因此Master最好不要写内存快照。
2).Master AOF持久化,若是不重写AOF文件,这个持久化方式对性能的影响是最小的,可是AOF文件会不断增大,AOF文件过大会影响Master重启的恢复速度。Master最好不要作任何持久化工做,包括内存快照和AOF日志文件,特别是不要启用内存快照作持久
化,若是数据比较关键,某个Slave开启AOF备份数据,策略为每秒同步一次。
3).Master调用BGREWRITEAOF重写AOF文件,AOF在重写的时候会占大量的CPU和内存资源,致使服务load太高,出现短暂服务暂停现象。
4). Redis主从复制的性能问题,为了主从复制的速度和链接的稳定性,Slave和Master最好在同一个局域网内
14. mySQL里有2000w数据,redis中只存20w的数据,如何保证redis中的数据都是热点数据
相关知识:redis 内存数据集大小上升到必定大小的时候,就会施行数据淘汰策略(回收策略)。redis 提供 6种数据淘汰策略:
volatile-lru:从已设置过时时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
volatile-ttl:从已设置过时时间的数据集(server.db[i].expires)中挑选将要过时的数据淘汰
volatile-random:从已设置过时时间的数据集(server.db[i].expires)中任意选择数据淘汰
allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰
allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
no-enviction(驱逐):禁止驱逐数据
15.redis事物的了解CAS(check-and-set 操做实现乐观锁 )?
和众多其它数据库同样,Redis做为NoSQL数据库也一样提供了事务机制。在Redis中,MULTI/EXEC/DISCARD/WATCH这四个命令是咱们实现事务的基石。相信对有关系型数据库开发经验的开发者而言这一律念并不陌生,即使如此,咱们仍是会简要的列出
Redis中
事务的实现特征:
1). 在事务中的全部命令都将会被串行化的顺序执行,事务执行期间,Redis不会再为其它客户端的请求提供任何服务,从而保证了事物中的全部命令被原子的执行。
2). 和关系型数据库中的事务相比,在Redis事务中若是有某一条命令执行失败,其后的命令仍然会被继续执行。
3). 咱们能够经过MULTI命令开启一个事务,有关系型数据库开发经验的人能够将其理解为"BEGIN TRANSACTION"语句。在该语句以后执行的命令都将被视为事务以内的操做,最后咱们能够经过执行EXEC/DISCARD命令来提交/回滚该事务内的全部操做。这两
个Redis命令可被视为等同于关系型数据库中的COMMIT/ROLLBACK语句。
4). 在事务开启以前,若是客户端与服务器之间出现通信故障并致使网络断开,其后全部待执行的语句都将不会被服务器执行。然而若是网络中断事件是发生在客户端执行EXEC命令以后,那么该事务中的全部命令都会被服务器执行。
5). 当使用Append-Only模式时,Redis会经过调用系统函数write将该事务内的全部写操做在本次调用中所有写入磁盘。然而若是在写入的过程当中出现系统崩溃,如电源故障致使的宕机,那么此时也许只有部分数据被写入到磁盘,而另一部分数据却已经丢失。
Redis服务器会在从新启动时执行一系列必要的一致性检测,一旦发现相似问题,就会当即退出并给出相应的错误提示。此时,咱们就要充分利用Redis工具包中提供的redis-check-aof工具,该工具能够帮助咱们定位到数据不一致的错误,并将已经写入的部
分数据进行回滚。修复以后咱们就能够再次从新启动Redis服务器了。
16.WATCH命令和基于CAS的乐观锁:
在Redis的事务中,WATCH命令可用于提供CAS(check-and-set)功能。假设咱们经过WATCH命令在事务执行以前监控了多个Keys,假若在WATCH以后有任何Key的值发生了变化,EXEC命令执行的事务都将被放弃,同时返回Null multi-bulk应答以通知调用者事务
执行失败。例如,咱们再次假设Redis中并未提供incr命令来完成键值的原子性递增,若是要实现该功能,咱们只能自行编写相应的代码。其伪码以下:
val = GET mykey
val = val + 1
SET mykey $val
以上代码只有在单链接的状况下才能够保证执行结果是正确的,由于若是在同一时刻有多个客户端在同时执行该段代码,那么就会出现多线程程序中常常出现的一种错误场景--竞态争用(race condition)。好比,客户端A和B都在同一时刻读取了mykey的原有值,假设该值为10,此后两个客户端又均将该值加一后set回Redis服务器,这样就会致使mykey的结果为11,而不是咱们认为的12。为了解决相似的问题,咱们须要借助WATCH命令的帮助,见以下代码:
WATCH mykey
val = GET mykey
val = val + 1
MULTI
SET mykey $val
EXEC
和此前代码不一样的是,新代码在获取mykey的值以前先经过WATCH命令监控了该键,此后又将set命令包围在事务中,这样就能够有效的保证每一个链接在执行EXEC以前,若是当前链接获取的mykey的值被其它链接的客户端修改,那么当前链接的EXEC命令将执行失败。这样调用者在判断返回值后就能够获悉val是否被从新设置成功。
17.redis持久化的几种方式
一、快照(snapshots)
缺省状况状况下,Redis把数据快照存放在磁盘上的二进制文件中,文件名为dump.rdb。你能够配置Redis的持久化策略,例如数据集中每N秒钟有超过M次更新,就将数据写入磁盘;或者你能够手工调用命令SAVE或BGSAVE。
工做原理
. Redis forks.
. 子进程开始将数据写到临时RDB文件中。
. 当子进程完成写RDB文件,用新文件替换老文件。
. 这种方式可使Redis使用copy-on-write技术。
二、AOF
快照模式并不十分健壮,当系统中止,或者无心中Redis被kill掉,最后写入Redis的数据就会丢失。这对某些应用也许不是大问题,但对于要求高可靠性的应用来讲,
Redis就不是一个合适的选择。
Append-only文件模式是另外一种选择。
你能够在配置文件中打开AOF模式
三、虚拟内存方式
当你的key很小而value很大时,使用VM的效果会比较好.由于这样节约的内存比较大.
当你的key不小时,能够考虑使用一些很是方法将很大的key变成很大的value,好比你能够考虑将key,value组合成一个新的value.
vm-max-threads这个参数,能够设置访问swap文件的线程数,设置最好不要超过机器的核数,若是设置为0,那么全部对swap文件的操做都是串行的.可能会形成比较长时间的延迟,可是对数据完整性有很好的保证.
本身测试的时候发现用虚拟内存性能也不错。若是数据量很大,能够考虑分布式或者其余数据库
18.redis的缓存失效策略和主键失效机制
做为缓存系统都要按期清理无效数据,就须要一个主键失效和淘汰策略.
在Redis当中,有生存期的key被称为volatile。在建立缓存时,要为给定的key设置生存期,当key过时的时候(生存期为0),它可能会被删除。
一、影响生存时间的一些操做
生存时间能够经过使用 DEL 命令来删除整个 key 来移除,或者被 SET 和 GETSET 命令覆盖原来的数据,也就是说,修改key对应的value和使用另外相同的key和value来覆盖之后,当前数据的生存时间不一样。
好比说,对一个 key 执行INCR命令,对一个列表进行LPUSH命令,或者对一个哈希表执行HSET命令,这类操做都不会修改 key 自己的生存时间。另外一方面,若是使用RENAME对一个 key 进行更名,那么更名后的 key的生存时间和更名前同样。
RENAME命令的另外一种多是,尝试将一个带生存时间的 key 更名成另外一个带生存时间的 another_key ,这时旧的 another_key (以及它的生存时间)会被删除,而后旧的 key 会更名为 another_key ,所以,新的 another_key 的生存时间也和本来的 key 同样。使用PERSIST命令能够在不删除 key 的状况下,移除 key 的生存时间,让 key 从新成为一个persistent key 。
二、如何更新生存时间
能够对一个已经带有生存时间的 key 执行EXPIRE命令,新指定的生存时间会取代旧的生存时间。过时时间的精度已经被控制在1ms以内,主键失效的时间复杂度是O(1),
EXPIRE和TTL命令搭配使用,TTL能够查看key的当前生存时间。设置成功返回 1;当 key 不存在或者不能为 key 设置生存时间时,返回 0 。
最大缓存配置
在 redis 中,容许用户设置最大使用内存大小
server.maxmemory
默认为0,没有指定最大缓存,若是有新的数据添加,超过最大内存,则会使redis崩溃,因此必定要设置。redis 内存数据集大小上升到必定大小的时候,就会实行数据淘汰策略。
redis 提供 6种数据淘汰策略:
. volatile-lru:从已设置过时时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
. volatile-ttl:从已设置过时时间的数据集(server.db[i].expires)中挑选将要过时的数据淘汰
. volatile-random:从已设置过时时间的数据集(server.db[i].expires)中任意选择数据淘汰
. allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰
. allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
. no-enviction(驱逐):禁止驱逐数据
注意这里的6种机制,volatile和allkeys规定了是对已设置过时时间的数据集淘汰数据仍是从所有数据集淘汰数据,后面的lru、ttl以及random是三种不一样的淘汰策略,再加上一种no-enviction永不回收的策略。
使用策略规则:
一、若是数据呈现幂律分布,也就是一部分数据访问频率高,一部分数据访问频率低,则使用allkeys-lru
二、若是数据呈现平等分布,也就是全部的数据访问频率都相同,则使用allkeys-random
三种数据淘汰策略:
ttl和random比较容易理解,实现也会比较简单。主要是Lru最近最少使用淘汰策略,设计上会对key 按失效时间排序,而后取最早失效的key进行淘汰
19.redis 最适合的场景
Redis最适合全部数据in-momory的场景,虽然Redis也提供持久化功能,但实际更多的是一个disk-backed的功能,跟传统意义上的持久化有比较大的差异,那么可能你们就会有疑问,彷佛Redis更像一个增强版的Memcached,那么什么时候使用Memcached,什么时候使用Redis呢?
若是简单地比较Redis与Memcached的区别,大多数都会获得如下观点:
1 、Redis不只仅支持简单的k/v类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
2 、Redis支持数据的备份,即master-slave模式的数据备份。
3 、Redis支持数据的持久化,能够将内存中的数据保持在磁盘中,重启的时候能够再次加载进行使用。
(1)会话缓存(Session Cache)
最经常使用的一种使用Redis的情景是会话缓存(session cache)。用Redis缓存会话比其余存储(如Memcached)的优点在于:Redis提供持久化。当维护一个不是严格要求一致性的缓存时,若是用户的购物车信息所有丢失,大部分人都会不高兴的,如今,
他们还会这样吗?
幸运的是,随着 Redis 这些年的改进,很容易找到怎么恰当的使用Redis来缓存会话的文档。甚至广为人知的商业平台Magento也提供Redis的插件。
(2)全页缓存(FPC)
除基本的会话token以外,Redis还提供很简便的FPC平台。回到一致性问题,即便重启了Redis实例,由于有磁盘的持久化,用户也不会看到页面加载速度的降低,这是一个极大改进,相似PHP本地FPC。
再次以Magento为例,Magento提供一个插件来使用Redis做为全页缓存后端。
此外,对WordPress的用户来讲,Pantheon有一个很是好的插件 wp-redis,这个插件能帮助你以最快速度加载你曾浏览过的页面。
(3)队列
Reids在内存存储引擎领域的一大优势是提供 list 和 set 操做,这使得Redis能做为一个很好的消息队列平台来使用。Redis做为队列使用的操做,就相似于本地程序语言(如Python)对 list 的 push/pop 操做。
若是你快速的在Google中搜索“Redis queues”,你立刻就能找到大量的开源项目,这些项目的目的就是利用Redis建立很是好的后端工具,以知足各类队列需求。例如,Celery有一个后台就是使用Redis做为broker,你能够从这里去查看。
(4)排行榜/计数器
Redis在内存中对数字进行递增或递减的操做实现的很是好。集合(Set)和有序集合(Sorted Set)也使得咱们在执行这些操做的时候变的很是简单,Redis只是正好提供了这两种数据结构。因此,咱们要从排序集合中获取到排名最靠前的10个用户–咱们
称之为“user_scores”,咱们只须要像下面同样执行便可:
固然,这是假定你是根据你用户的分数作递增的排序。若是你想返回用户及用户的分数,你须要这样执行:
ZRANGE user_scores 0 10 WITHSCORES
Agora Games就是一个很好的例子,用Ruby实现的,它的排行榜就是使用Redis来存储数据的,你能够在这里看到。
(5)发布/订阅
最后(但确定不是最不重要的)是Redis的发布/订阅功能。发布/订阅的使用场景确实很是多。我已看见人们在社交网络链接中使用,还可做为基于发布/订阅的脚本触发器,甚至用Redis的发布/订阅功能来创建聊天系统!(不,这是真的,你能够去核
实)。
Redis提供的全部特性中,我感受这个是喜欢的人最少的一个,虽然它为用户提供若是此多功能。
20.Reids的特色
Redis本质上是一个Key-Value类型的内存数据库,很像memcached,整个数据库通通加载在内存当中进行操做,按期经过异步操做把数据库数据flush到硬盘上进行保存。由于是纯内存操做,Redis的性能很是出色,每秒能够处理超过 10万次读写操做,是已知性能最快的Key-Value DB。
Redis的出色之处不只仅是性能,Redis最大的魅力是支持保存多种数据结构,此外单个value的最大限制是1GB,不像 memcached只能保存1MB的数据,所以Redis能够用来实现不少有用的功能,比方说用他的List来作FIFO双向链表,实现一个轻量级的高性 能消息队列服务,用他的Set能够作高性能的tag系统等等。另外Redis也能够对存入的Key-Value设置expire时间,所以也能够被看成一 个功能增强版的memcached来用。
Redis的主要缺点是数据库容量受到物理内存的限制,不能用做海量数据的高性能读写,所以Redis适合的场景主要局限在较小数据量的高性能操做和运算上。
21.读写分离模型
经过增长Slave DB的数量,读的性能能够线性增加。为了不Master DB的单点故障,集群通常都会采用两台Master DB作双机热备,因此整个集群的读和写的可用性都很是高。
读写分离架构的缺陷在于,无论是Master仍是Slave,每一个节点都必须保存完整的数据,若是在数据量很大的状况下,集群的扩展能力仍是受限于单个节点的存储能力,并且对于Write-intensive类型的应用,读写分离架构并不适合。
22.数据分片模型
为了解决读写分离模型的缺陷,能够将数据分片模型应用进来。
能够将每一个节点当作都是独立的master,而后经过业务实现数据分片。
结合上面两种模型,能够将每一个master设计成由一个master和多个slave组成的模型。
23.使用过Redis分布式锁么,它是什么回事?
先拿setnx来争抢锁,抢到以后,再用expire给锁加一个过时时间防止锁忘记了释放。
24.若是在setnx以后执行expire以前进程意外crash或者要重启维护了,那会怎么样?
25.若是这个redis正在给线上的业务提供服务,那使用keys指令会有什么问题?
这个时候你要回答redis关键的一个特性:redis的单线程的。keys指令会致使线程阻塞一段时间,线上服务会停顿,直到指令执行完毕,服务才能恢复。这个时候可使用scan指令,scan指令能够无阻塞的提取出指定模式的key列表,可是会有必定的重复几率,在客户端作一次去重就能够了,可是总体所花费的时间会比直接用keys指令长。
26.使用过Redis作异步队列么,你是怎么用的?
通常使用list结构做为队列,rpush生产消息,lpop消费消息。当lpop没有消息的时候,要适当sleep一会再重试。
若是对方追问可不能够不用sleep呢?list还有个指令叫blpop,在没有消息的时候,它会阻塞住直到消息到来。
若是对方追问能不能生产一次消费屡次呢?使用pub/sub主题订阅者模式,能够实现1:N的消息队列。
若是对方追问pub/sub有什么缺点?在消费者下线的状况下,生产的消息会丢失,得使用专业的消息队列如rabbitmq等。
若是对方追问redis如何实现延时队列?我估计如今你很想把面试官一棒打死若是你手上有一根棒球棍的话,怎么问的这么详细。可是你很克制,而后神态自若的回答道:使用sortedset,拿时间戳做为score,消息内容做为key调用zadd来生产消息,消费者用zrangebyscore指令获取N秒以前的数据轮询进行处理。
到这里,面试官暗地里已经对你竖起了大拇指。可是他不知道的是此刻你却竖起了中指,在椅子背后。
27.若是有大量的key须要设置同一时间过时,通常须要注意什么?
若是大量的key过时时间设置的过于集中,到过时的那个时间点,redis可能会出现短暂的卡顿现象。通常须要在时间上加一个随机值,使得过时时间分散一些。
28.Redis如何作持久化的?
bgsave作镜像全量持久化,aof作增量持久化。由于bgsave会耗费较长时间,不够实时,在停机的时候会致使大量丢失数据,因此须要aof来配合使用。在redis实例重启时,会使用bgsave持久化文件从新构建内存,再使用aof重放近期的操做指令来实现完整恢复重启以前的状态。
对方追问若是忽然机器掉电会怎样?取决于aof日志sync属性的配置,若是不要求性能,在每条写指令时都sync一下磁盘,就不会丢失数据。可是在高性能的要求下每次都sync是不现实的,通常都使用定时sync,好比1s1次,这个时候最多就会丢失1s的数据。
对方追问bgsave的原理是什么?你给出两个词汇就能够了,fork和cow。fork是指redis经过建立子进程来进行bgsave操做,cow指的是copy on write,子进程建立后,父子进程共享数据段,父进程继续提供读写服务,写脏的页面数据会逐渐和子进程分离开来。
29.Pipeline有什么好处,为何要用pipeline?
能够将屡次IO往返的时间缩减为一次,前提是pipeline执行的指令之间没有因果相关性。使用redis-benchmark进行压测的时候能够发现影响redis的QPS峰值的一个重要因素是pipeline批次指令的数目。
**附: 可是注意,若是使用`Pipeline`。当节点个数扩充后,会致使长链接数目成倍数上涨。**
30.Redis的同步机制了解么?
Redis可使用主从同步,从从同步。第一次同步时,主节点作一次bgsave,并同时将后续修改操做记录到内存buffer,待完成后将rdb文件全量同步到复制节点,复制节点接受完成后将rdb镜像加载到内存。加载完成后,再通知主节点将期间修改的操做记录同步到复制节点进行重放就完成了同步过程。
31.是否使用过Redis集群,集群的原理是什么?
Redis Sentinal着眼于高可用,在master宕机时会自动将slave提高为master,继续提供服务。
Redis Cluster着眼于扩展性,在单个redis内存不足时,使用Cluster进行分片存储。