关于java:Redis最常见的16道面试题与详解

1.什么是redis?

 Redis 是一个基于内存的高性能key-value数据库。 

2.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适宜的场景次要局限在较小数据量的高性能操作和运算上。

3.应用redis有哪些益处?   

(1) 速度快,因为数据存在内存中,相似于HashMap,HashMap的劣势就是查找和操作的工夫复杂度都是O(1) 
(2) 反对丰盛数据类型,反对string,list,set,sorted set,hash   
 (3) 反对事务,操作都是原子性,所谓的原子性就是对数据的更改要么全副执行,要么全副不执行   
(4) 丰盛的个性:可用于缓存,音讯,按key设置过期工夫,过期后将会主动删除

4.redis相比memcached有哪些劣势?

 (1) memcached所有的值均是简略的字符串,redis作为其替代者,反对更为丰盛的数据类型 
 (2) redis的速度比memcached快很多  (3) redis能够长久化其数据

5.Memcache与Redis的区别都有哪些?

 1)、存储形式 Memecache把数据全副存在内存之中,断电后会挂掉,数据不能超过内存大小。 Redis有部份存在硬盘上,这样能保证数据的持久性。 
 2)、数据反对类型   Memcache对数据类型反对绝对简略。  Redis有简单的数据类型。  
 3)、应用底层模型不同   它们之间底层实现形式 以及与客户端之间通信的利用协定不一样。   Redis间接本人构建了VM 机制 ,因为个别的零碎调用零碎函数的话,会节约肯定的工夫去挪动和申请。   

6.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最好在同一个局域网内

7. 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(驱赶):禁止驱赶数据

  8.请用Redis和任意语言实现一段歹意登录爱护的代码,限度1小时内每用户Id最多只能登录5次。具体登录函数或性能用空函数即可,不必具体写出。

    用列表实现:列表中每个元素代表登陆工夫,只有最初的第5次登陆工夫和当初时间差不超过1小时就禁止登陆.用Python写的代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

#!/usr/bin/env python3

import redis

import sys

import time

r = redis.StrictRedis(host=’`127.0.0.1′, port=6379, db=0`)

try`:`

id = sys.argv[`1`]

except:

print(‘input argument error’)

sys.exit(`0`)

if r.llen(id) >= 5 and time.time() – float`(r.lindex(id, 4)) <=3600`:

print(“you are forbidden logining”)

else`:`

print(‘you are allowed to login’)

r.lpush(id, time.time())

# login_func()

9.为什么redis须要把所有数据放到内存中?

   Redis为了达到最快的读写速度将数据都读到内存中,并通过异步的形式将数据写入磁盘。所以redis具备疾速和数据长久化的特色。如果不将数据放在内存中,磁盘I/O速度为重大影响redis的性能。在内存越来越便宜的明天,redis将会越来越受欢迎。

   如果设置了最大应用的内存,则数据已有记录数达到内存限值后不能持续插入新值。

10.Redis是单过程单线程的

   redis利用队列技术将并发拜访变为串行拜访,打消了传统数据库串行管制的开销

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

   Redis为单过程单线程模式,采纳队列模式将并发拜访变为串行拜访。Redis自身没有锁的概念,Redis对于多个客户端连贯并不存在竞争,然而在Jedis客户端对Redis进行并发拜访时会产生连贯超时、数据转换谬误、阻塞、客户端敞开连贯等问题,这些问题均是因为客户端连贯凌乱造成。对此有2种解决办法:

 1.客户端角度,为保障每个客户端间失常有序与Redis进行通信,对连贯进行池化,同时对客户端读写Redis操作采纳外部锁synchronized。

 2.服务器角度,利用setnx实现锁。
 注:对于第一种,须要应用程序本人解决资源的同步,能够应用的办法比拟艰深,能够应用synchronized也能够应用lock;第二种须要用到Redis的setnx命令,然而须要留神一些问题。

12.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服务器了。

13.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是否被从新设置胜利。

14.redis长久化的几种形式

1、快照(snapshots)
  缺省状况状况下,Redis把数据快照寄存在磁盘上的二进制文件中,文件名为dump.rdb。你能够配置Redis的长久化策略,例如数据集中每N秒钟有超过M次更新,就将数据写入磁盘;或者你能够手工调用命令SAVE或BGSAVE。
  工作原理
  . Redis forks.
  . 子过程开始将数据写到长期RDB文件中。
  . 当子过程实现写RDB文件,用新文件替换老文件。
  . 这种形式能够使Redis应用copy-on-write技术。
2、AOF
  快照模式并不非常强壮,当零碎进行,或者无心中Redis被kill掉,最初写入Redis的数据就会失落。这对某些利用兴许不是大问题,但对于要求高可靠性的利用来说,
  Redis就不是一个适合的抉择。
  Append-only文件模式是另一种抉择。
  你能够在配置文件中关上AOF模式
3、虚拟内存形式
  当你的key很小而value很大时,应用VM的成果会比拟好.因为这样节约的内存比拟大.
  当你的key不小时,能够思考应用一些十分办法将很大的key变成很大的value,比方你能够思考将key,value组合成一个新的value.
  vm-max-threads这个参数,能够设置拜访swap文件的线程数,设置最好不要超过机器的核数,如果设置为0,那么所有对swap文件的操作都是串行的.可能会造成比拟长时间的提早,然而对数据完整性有很好的保障.

  本人测试的时候发现用虚拟内存性能也不错。如果数据量很大,能够思考分布式或者其余数据库

15.redis的缓存生效策略和主键生效机制

作为缓存零碎都要定期清理有效数据,就须要一个主键生效和淘汰策略.
  在Redis当中,有生存期的key被称为volatile。在创立缓存时,要为给定的key设置生存期,当key过期的时候(生存期为0),它可能会被删除。
1、影响生存工夫的一些操作
  生存工夫能够通过应用 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 。
2、如何更新生存工夫
  能够对一个曾经带有生存工夫的 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永不回收的策略。
应用策略规定:
1、如果数据出现幂律散布,也就是一部分数据拜访频率高,一部分数据拜访频率低,则应用allkeys-lru
2、如果数据出现平等散布,也就是所有的数据拜访频率都雷同,则应用allkeys-random
三种数据淘汰策略:
  ttl和random比拟容易了解,实现也会比较简单。次要是Lru最近起码应用淘汰策略,设计上会对key 按生效工夫排序,而后取最先生效的key进行淘汰

16.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提供的所有个性中,我感觉这个是喜爱的人起码的一个,尽管它为用户提供如果此多功能。

看完三件事❤️

========

如果你感觉这篇内容对你还蛮有帮忙,我想邀请你帮我三个小忙:

点赞,转发,有你们的 『点赞和评论』,才是我发明的能源。

关注公众号 『 Java斗帝 』,不定期分享原创常识。

同时能够期待后续文章ing????

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理