Java面试题-Redis和Memcache(持续更新)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lyhkmm/article/details/80322959

什么是redis?

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

redis淘汰策略

  Redis提供了下面几种淘汰策略供用户选择,其中默认的策略为noeviction策略:
  noeviction:当内存使用达到阈值的时候,所有引起申请内存的命令会报错。
  allkeys-lru:在主键空间中,优先移除最近未使用的key。
  volatile-lru:在设置了过期时间的键空间中,优先移除最近未使用的key。
  allkeys-random:在主键空间中,随机移除某个key。
  volatile-random:在设置了过期时间的键空间中,随机移除某个key。
  volatile-ttl:在设置了过期时间的键空间中,具有更早过期时间的key优先移除。

redis相比memcached有哪些优势?   

  memcached所有的值均是简单的字符串,redis作为其替代者,支持更为丰富的数据类型
  redis的速度比memcached快很多
  redis可以持久化其数据

redis相比memcached有哪些劣势

  由于Redis只使用单核,而Memcached可以使用多核;在100k以上的数据中,Memcached性能要高于Redis;对于key-value这样简单的数据储存,memcache的内存使用率更高。如果采用hash结构,redis的内存使用率会更高。

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

  Redis为单进程单线程模式,采用队列模式将并发访问变为串行访问。Redis本身没有锁的概念,Redis对于多个客户端连接并不存在竞争,但是在Jedis客户端对Redis进行并发访问时会发生连接超时、数据转换错误、阻塞、客户端关闭连接等问题,这些问题均是由于客户端连接混乱造成。

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模式

虚拟内存方式

  其实就是将内存上的数据保存到硬盘上,这样突然宕机数据也不会丢失

Redis 底层数据结构有一下数据类型:

 简单动态字符串(simple dynamic string)SDS

/*
* 保存字符串对象的结构
*/
struct sdshdr {
// buf 中已占用空间的长度
int len;
// buf 中剩余可用空间的长度
int free;
// 数据空间
char buf[];
};

 SDS 与 C 字符串的区别

  传统的C 字符串 使用长度为N+1 的字符串数组来表示长度为N 的字符串,这样做在获取字符串长度,字符串扩展等操作的时候效率低下,杜绝缓冲区溢出

 链表

  链表提供了高效的节点重排能力,以及顺序性的节点访问方式,并且可以通过增删节点来灵活地调整链表的长度。
  链表在Redis 中的应用非常广泛,比如列表键的底层实现之一就是链表。当一个列表键包含了数量较多的元素,又或者列表中包含的元素都是比较长的字符串时,Redis 就会使用链表作为列表键的底层实现。

 字典

字典,又称为符号表,关联数组,或者映射,是一种用于保存键值对的抽象数据结构。可以说Redis里所有的结构都是用字典来存储的。那么字典是如何来使先的呢?
字典的结构从高层到底层实现分别是:字典(dict),字典哈希表(dictht),哈希表节点(dictEntry)

 跳跃表

  跳跃表(skiplist)是一种有序数据结构,它通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问节点的目的。
  Redis 只在两个地方用到了跳跃表,一个是实现有序集合键,另外一个是在集群节点中用作内部数据结构

 整数集合

整数集合是集合建的底层实现之一,当一个集合中只包含整数,且这个集合中的元素数量不多时,redis就会使用整数集合intset作为集合的底层实现

 压缩列表

  压缩列表是列表键和哈希键的底层实现之一。当一个列表键只有少量列表项,并且每个列表项要么就是小整数,要么就是长度比较短的字符串,那么Redis 就会使用压缩列表来做列表键的底层实现。
  redis 3.2以后,quicklist作为列表键的实现底层实现之一,代替了压缩列表

 对象

redis面试经历(来着百度百家号 )

 Redis有哪些数据结构?

  字符串String、字典Hash、列表List、集合Set、有序集合SortedSet。如果你是Redis中高级用户,还需要加上下面几种数据结构HyperLogLog、Geo、Pub/Sub。如果你说还玩过Redis Module,像BloomFilter,RedisSearch,Redis-ML,面试官得眼睛就开始发亮了。

 使用过Redis分布式锁么,它是什么回事?

  先拿setnx来争抢锁,抢到之后,再用expire给锁加一个过期时间防止锁忘记了释放。这时候对方会告诉你说你回答得不错,然后接着问如果在setnx之后执行expire之前进程意外crash或者要重启维护了,那会怎么样?这时候你要给予惊讶的反馈:唉,是喔,这个锁就永远得不到释放了。紧接着你需要抓一抓自己得脑袋,故作思考片刻,好像接下来的结果是你主动思考出来的,然后回答:我记得set指令有非常复杂的参数,这个应该是可以同时把setnx和expire合成一条指令来用的!对方这时会显露笑容,心里开始默念:摁,这小子还不错。

 假如Redis里面有1亿个key,其中有10w个key是以某个固定的已知的前缀开头的,如果将它们全部找出来?

  使用keys指令可以扫出指定模式的key列表。对方接着追问:如果这个redis正在给线上的业务提供服务,那使用keys指令会有什么问题?这个时候你要回答redis关键的一个特性:redis的单线程的。keys指令会导致线程阻塞一段时间,线上服务会停顿,直到指令执行完毕,服务才能恢复。这个时候可以使用scan指令,scan指令可以无阻塞的提取出指定模式的key列表,但是会有一定的重复概率,在客户端做一次去重就可以了,但是整体所花费的时间会比直接用keys指令长。

 使用过Redis做异步队列么,你是怎么用的?

  一般使用list结构作为队列,rpush生产消息,lpop消费消息。当lpop没有消息的时候,要适当sleep一会再重试。如果对方追问可不可以不用sleep呢?list还有个指令叫blpop,在没有消息的时候,它会阻塞住直到消息到来。

 如果对方追问能不能生产一次消费多次呢?

  使用pub/sub主题订阅者模式,可以实现1:N的消息队列。如果对方追问pub/sub有什么缺点?在消费者下线的情况下,生产的消息会丢失,得使用专业的消息队列如rabbitmq等。

 如果对方追问redis如何实现延时队列?

  我估计现在你很想把面试官一棒打死如果你手上有一根棒球棍的话,怎么问的这么详细。但是你很克制,然后神态自若的回答道:使用sortedset,拿时间戳作为score,消息内容作为key调用zadd来生产消息,消费者用zrangebyscore指令获取N秒之前的数据轮询进行处理。到这里,面试官暗地里已经对你竖起了大拇指。但是他不知道的是此刻你却竖起了中指,在椅子背后。

 如果有大量的key需要设置同一时间过期,一般需要注意什么?

  如果大量的key过期时间设置的过于集中,到过期的那个时间点,redis可能会出现短暂的卡顿现象。一般需要在时间上加一个随机值,使得过期时间分散一些。

 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,子进程创建后,父子进程共享数据段,父进程继续提供读写服务,写脏的页面数据会逐渐和子进程分离开来。

 Pipeline有什么好处,为什么要用pipeline?

  可以将多次IO往返的时间缩减为一次,前提是pipeline执行的指令之间没有因果相关性。使用redis-benchmark进行压测的时候可以发现影响redis的QPS峰值的一个重要因素是pipeline批次指令的数目。

 Redis的同步机制了解么?

  Redis可以使用主从同步,从从同步。第一次同步时,主节点做一次bgsave,并同时将后续修改操作记录到内存buffer,待完成后将rdb文件全量同步到复制节点,复制节点接受完成后将rdb镜像加载到内存。加载完成后,再通知主节点将期间修改的操作记录同步到复制节点进行重放就完成了同步过程。

 是否使用过Redis集群,集群的原理是什么?

  Redis Sentinal着眼于高可用,在master宕机时会自动将slave提升为master,继续提供服务。
  Redis Cluster着眼于扩展性,在单个redis内存不足时,使用Cluster进行分片存储。
  
原文来自:lyhkmm.com

猜你喜欢

转载自blog.csdn.net/lyhkmm/article/details/80322959