Redis常见面试题总结

看了网上的redis的一些面试题,加上自己的一些理解,总结如下:

目录

什么是redis

Redis的五种数据类型

Redis常用命令

五种数据类型各自对应的操作命令

消息队列

Redis事务

Redis的持久化

Redis集群

主从复制的容灾处理

高可用sentinel哨兵

Redis与memcached区别:

为什么redis把所有数据存放到内存中

Redis常见的性能问题都有哪些?如何解决

Redis的五个常见应用场景

Redis的过期策略

Redis的淘汰机制

使用Redis的缺点

如何用Redis实现分布式锁


什么是redis

Remote dictonary server是一个开源的使用key-value存储的内存数据库服务器,redis的键是字符串,其值可以是string,hash,list,set,zset

Redis的五种数据类型

  1. string,string
  2. string,hash

eg; key-k1,value-id=1,name=”zhangsan”,age=21

  1. string,list

eg:key-k1,value=[北京,上海,深圳,北京]

  1. string,set

eg:key-k1,value=[北京,上海,深圳]

  1. string,zset同set,不同的是每个元素都会关联一个分数,分数可以重复,分数是double类型,redis通过分数来为集合中的成员进行有小到大的排序

eg: key-k1,[100北京,90上海,80深圳]

Redis常用命令

Redis的默认端口是6379

  1. 查看gcc编译器是否安装:yum list installed | grep gcc

 或者rmp -qa|grep gcc

  1. 启动redis进入到src目录下执行./redis-server ../redis.conf
  2. 查看redis有没有进程ps -ef | grep redis
  3. 结束redis进程 在src目录下执行./redis-cli shutdown

或者 ./redis-cli -h 127.0.0.1 -p 6379

  1. 输入ping,redis返回pong,表示正常
  2. 选择数据库  select
  3. 删除所有库的数据flush all
  4. 删除当前数据库的数据flushdb
  5. 退出exit,quit
  6. 得到当前数据库的数目dbsize
  7. 得到redis中的所有配置config get *
  8. 永久关闭/开启防火墙chkconfig iptables on/off
  9. 临时关闭防火墙service iptables start/stop
  10. 查找当前数据库下的key keys *[速度慢,最好不用]
  11. 查找某个key是否存在exist key
  12. 将当前的key移动到指定的数据库中move key db
  13. 设置key的过期时间expire key seconds
  14. 查看key还有多少秒过期ttl key
  15. 删除key del key
  16. 移除key的过期时间persist key
  17. 随机返回key空间的一个key randonmkey
  18. 返回key的类型type

五种数据类型各自对应的操作命令

 

  1. String-string:

设置key对应的值Set key value

得到某个key对应的值get k

incr key[用于计数器] 自增

decr key自减

incrby key increment指定增长值

decrby key increment指定减少值

Setex设置key的值,并设置多少秒过时

Setnx如果不存在,就设置

Getset返回key原来的值,并设置新值

  1. String-hash

设置单个hash类型hset key field value

设置多个hmset key field value field value

得到单个hget key field

得到多个hgetall key

删除单个hdel key属性名

删除多个hdelall key

  1. String-list

Lpush key v1 v2向链表的头部插入数据

Rpush key v1 v2向链表的尾部插入数据

Lrange key a b获取指定列表中指定区间的元素0表示第一个1表示第二个… -1表示倒数第一个 -2表示倒数第二个

Eg:lrange k1 0 -1获取k1从第一个到最后一个的元素

 

Lpop从左边获取列表key的一个元素,并将该元素移除

Lpush从右边获取该列表key的一个元素,并将该元素移除

Lindex获取下标为指定元素的值

Llen key获取指定key的长度

  1. String-set

Sadd:将一个或者朵儿member元素加入到集合key当中,已经存在于集合的member元素将不会再加入

Smembers key取集合中的所有元素

Sismember判断member元素是否为集合key中的成员sismember Beijing

Scard:取集合中的元素个数

Srem key value删除集合中的元素

随机移除集合中的数据spop key count

求两个集合的交集sinter k1 k2

求两个集合的并集sunion k1 k2

求两个集合的差集sdiff k1 k2

  1. String-zset

Zadd key weight value向集合中添加元素

Zrange key a b取集合中的元素按照从小到大的顺序

Zrevrange key a b取集合中的元素,按照从大到小

Zrank k1 v取某个元素在集合中的序号,按照从小到大的顺序

Zrevrank k1 v取某个元素在集合中的序号,按照从大到小的顺序

Zrem删除元素

Zcard获取集合中元素的个数

消息队列

消息队列是实现异构系统之间通信的一种方式,A系统将消息发送到消息队列服务器上,B系统从消息队列接收到消息

Java常用的消息队列有ActiveMQ RabbitMQ kafka

消息队列有两种模式  1.点对点 简称为p2p (point to point) 2.发布与订阅(publish/subsrcibe)简写为pub/sub

点对点;A发消息,B,C,D中有一个人拿到消息,消息就删除,其他人拿不到

发布-订阅 发消息B,C,D三个人都能拿到消息,三个人都拿到消息才删除

消息队列的核心三要素;

生产者producer消费者consumer消息服务broker

消息队列的两种用途 系统解耦,异步处理,不需要实时返回结果的场景

Redis事务

当一个client在一个连接中发出multi命令时,这个命令暂时不会被执行,放在一个队列中,当执行exec命令时,redis会顺序的执行队列中的所有命令

Discard放弃执行所有的,,命令

事务的复杂情况:悲观锁和乐观锁

悲观锁:每次拿数据之前都认为别人会修改锁,所以每次在拿数据的时候都会先上锁,这样别人想拿到这个数据就会block阻塞,直到拿到锁。行锁,表锁,读锁,写锁等都是在操作之前上锁,让别人无法操作该数据

乐观锁[版本控制的概念]每次拿数据都认为别人不会上锁,但是在更新的时候会判断一下再次期间别人有没有去更新这一条数据,一般使用版本号机制进行判断。乐观锁使用与多读的应用类型可以提高吞吐量。

Update users set money=money-50,version=verson+1 where  id=1 and verion=#{version}

Redis的watch机制实现乐观锁

Eg:set k1 1

Watch k1

Set k1 2

Multi

Set k1 3

Exec

提交事务,但是k1的值不会被修改为3,k1的值仍然是2,因为事务提交之k1的值已经被修改过了

乐观锁可以解决超卖问题

超卖是指没有库存了,但是仍然显示可以买

Redis的持久化

持久化是指把事务放在不会丢失的地方

Redis持久化的两个方式;RDB AOF

RDB:在指定的时间间隔内将内存中的所有数据的快照写入磁盘,保存为一个后缀.rdb的文件,数据恢复时,将从磁盘的筷子文件直接再读取到内存,redis已经默认开启rdb的持久化

Rdb实现过程;redis在将内部的数据写到磁盘的快照文件时,将当前fork分支分出一个子进程,然后在子进程中循环所有的内存数据,并且将内存数据先写到一个临时文件中,然后将这个临时文件重命名为.rdb文件,覆盖掉原来的rdb文件

总结rdb持久化:由于存储的是数据快照文件,直接将快照文件里的数据再放入内存中就好了,恢复数据很方便,也比较块,

缺点:会丢失最后一次快照以后更改的数据

如果能应用能容忍数据丢失,那么rdb是不错的选择

由于要经常操作磁盘,RDB经常会fork出一个子进程,如果你的redis数据库很大的话,fork占用比较多的时间,并且可能会影响redis暂停服务一些时间(millsecond),如果数据库超级大,并且你的服务器cpu比较弱,有可能会达到一秒

Aof方式(Append only file)redis每次接收到一条改变数据的命令时,它将 该命令写到一个AOF文件中,只记录写操作,读操作不记录,当redis重启时,它通过执行AOF文件中的所有命令里恢复数据

Redis没有开启默认Aof持久化

在redis的配置文件中,将appendonly中的aof改成yes就代表开启了持久化

Appendfilename指定aof文件名,默认文件名为appendonly.aof

Appendsync:配置向aof文件中命令数据的策略

  1. No不主动进行同步操作,而是完全交由操作系统来做,每30秒执行一次,比较快,但不是很安全
  2. Always每次执行都会执行同步,慢一些但是很安全
  3. Eveysec美秒执行以同步操作,比较平衡,介于速度和安全之间

Dir指定aof和rdb文件的目录

Auto-aof-rewrite-percentage当目前aof文件超过上一次重写的aof文件大小的百分之多少时会进行重写,如果之前没有进行重写,则以启动时的aof文件大小为依据

Auto-aof-rewrite-percentage当前aof文件超过一次重写的aof文件大小会进行重写,如果没有重写,则以启动时的aof文件大小为依据

总结:append-only持久化方式是一个可以提供完全数据保障的方案

对于一般性的业务需求,减一使用rdb的方式进行持久化,原因是rdb的开销比aof方式要低很多,对那些无法忍受数据丢失的应用,才使用aof方式

Redis集群

通过持久化,保持不会丢失数据,但是当电脑或服务器出故障,也会导致数据丢失

为了避免单点故障,将数据复制多分部署在不同的服务器上,即使有一台服务器出现故障,其他服务器依然可以提供服务,当一台服务器的数据更新后,自动将更新的数据部署到其他服务器上

如何实现:redis提供了复制功能来自动实现多台redis服务器的数据同步

我们可以通过部署多台redis,并在配置文件中指定这几台redis之间的主从关系,主负责写入数据,同时把写吐的数据实时同步到从机器,这种模式叫做主从复制,即master/slave,并且默认master用于写,slave用于读,向salve写数据会导致错误,实现redis的主从复制,只需要修改redis的主配置文件,即redis.conf

Redis主从复制的过程

  1. Slave与master建立连接,发送sync同步命令
  2. Master启动一个后台进程,将数据库快照保存到文件中,同时master主进程会开始执行写命令并缓存
  3. 后台完成保存后,就将此文件发送给slave
  4. Slave将此文件保存到硬盘上

主从复制的容灾处理

当master服务器发生故障,需要手动将slave中的一个提升为master,剩下的slave挂至新的master上,这种处理也叫冷处理(人工处理是冷处理)机器处理称为热处理

处理步骤;

  1. 执行命令slave of no one将其中一台服务器提升为master,剩下的slave挂至新的master上,
  2. 执行命令slaveof 127.0.0。1端口号 将slave挂至新的master上

 

主从复制模式小结:

  1. 主从复制的集群有一个master和多个slave构成,通过在redis.conf配置文件进行配置来实现主从关系
  2. 当从redis(slave)故障,请求的性能下降
  3. 当主redis(master)发生故障,写请求无法执行
  4. 当master发生故障,需要手动将其中一台slave使用slaveof on one命令提升为master,其他slave执行slaveof命令指向这个新的master,从而构成新的主从关系
  5. 主从复制模式的故障转移需要手动操作,这种处理并不智能,需要自动化处理,这就需要sentinel哨兵,实现故障自动转移

高可用sentinel哨兵

Sentinel哨兵是redis官方提供的高可用方案,使用sentinel哨兵可以监控多个redis服务实例的运行情况

哨兵的基本原理:

Sentinel哨兵用来监视redis的主从服务器,他会不断检查master和slave是否正常

如果是sentinel自身故障了,就无法监控,所以需要哨兵,组成sentinel网络

监控同一个master的各个sentinel哨兵会互相通信,组成一个分布式的sentinel哨兵网络,互相交换彼此关于被监控redis服务器的运行情况

当一个sentinel哨兵被认为监控的redis服务器出现故障时,他会向网络中的其他sentinel哨兵进行确认,判断该服务器是否是真的已故障

如果故障的redis服务器为主服务器,那么sentinel哨兵网络将对故障的热废水服务器进行自动故障转移,通过将故障的主redis服务器的某个服务器提升为新的主服务器,并让其他服务器转移到新的主服务器,以此来实现让系统重新回到正常的状态

待出现故障的旧主服务器重新启动上线时,sentinel哨兵让它变成一个从redis服务器,并挂到新的主redis服务器下

所以哨兵是自动实现故障转移,不需要人工转移,是高可用的一种集群方案

Redis与memcached区别:

  1. 存储方式不同,redis存在内存中,memcached存储在硬盘上
  2. 支持的数据类型不同redis支持复杂数据类型,memcached支持简单的数据类型
  3. Value值的大小不同,redis支持的value最大可以达到1G,memcached可以达到1M
  4. 使用底层模型不同 他们之间底层实现方式以及与客户端之间通信的应用协议不一样,redis直接自己构建了vm机制,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求

 

为什么redis把所有数据存放到内存中

Redis为了达到最快的读写速度将数据都读到内存中,并通过异步的方式将数据写入磁盘。所以redis具有快速和持久化的特征,磁盘I/O速度为严重影响redis的性能,在内存越来越便宜的今天,redis将会越来越受欢迎,则数据已有记录数达到内存限制后不能继续插入新值。

Redis常见的性能问题都有哪些?如何解决

  1. Master写内存快照,save命令调度rdbsave函数,会阻塞住主线程的工作,当快照比较大时,对性能影响是非常大的,会间断性暂停服务,所以master最好不要写内存快照
  2. Master aof持久化,如果补充协议aof文件,这个持久化方式对性能的影响是最小的,但是aof文件会不断增大,aof文件过大会影响master重启的恢复速度。Master最好不要做任何持久化工作,包括内存快照和aof日志文件,特别是不要启用内存快照做持久化,如果数据比较关键,某个slave开启aof备份数据,策略为每秒同步一次
  3. Master调用bgrewriteaof重写文件,aof在重写的时候会占大量的cpu和内存资源,导致服务load锅盖,出现短暂服务暂停现象
  4. Redis主从复制的性能问题,为了主从复制的速度和连接的稳定性,salve和master最好同一个局域网内

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

5、发布/订阅

最后(但肯定不是最不重要的)是 Redis 的发布/订阅功能。发布/订阅的使用场景确实非常多。我已

看见人们在社交网络连接中使用,还可作为基于发布/订阅的脚本触发器,甚至用 Redis 的发布/订阅

功能来建立聊天系统!

Redis的过期策略

Redis的过期策略是:定期删除+惰性删除

定期删除是指每隔多少秒去检查key,看是否过期,过期将其删除,但是是随机检查的,可能有很多key检查不到,然后就有了惰性删除策略,使用某个key之前,检查是否过期,但是即使是这样的情况,还是有很多过期的key没有删除,所以有了淘汰机制

Redis的淘汰机制

Redis提供6种数据淘汰策略:

1、volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰

2、volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰

3、volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰

4、allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰

5、allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰

6、no-enviction(驱逐):禁止驱逐数据(也就是说会报错)

Redis 确定驱逐某个键值对后,会删除这个数据,并将这个数据变更消息发布到本地(AOF 持久化)和从机(主从连接)。

使用Redis的缺点

        1. 缓存和数据库双写一致性问题

解决方法:采取正确的更新策略,先更新数据库,再删除缓存,有可能存在删除缓存失败的问题,可以利用消息队列

        1. 缓存击中问题(缓存穿透)

黑客故意去请求缓存中不存在的数据,导致所有的请求都堆到数据库上,导致数据库连接异常

  1. 互斥锁
  2. 异步更新,无论key是否取到值,都直接返回。Value值中维护一个缓存失效时间,缓存如果过期,异步起一个线程去读数据库,更新缓存
  3. 提供一个能迅速判断请求是否有效的拦截机制,比如利用布隆过滤器,内部维护一些合法的key。迅速判断出请求所携带的key是否合法有效,如果不合法,直接返回
        1. 缓存雪崩问题

同一时间缓存大面积失效,这时候又来了一拨请求,都堆到数据库上,导致数据库连接异常

  1. 给定缓存的失效时间,加上随机值,避免集体失效
  2. 互斥锁,但是吞吐量明显下降了
  3. 双缓存,缓存A和缓存B,一个缓存设计有效时间,另一个缓存不设置有效时间
        1. 缓存的并发竞争问题

事务的时候有可能多个key在不同的redis中,

期望按照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操作了

如何用Redis实现分布式锁

https://www.cnblogs.com/williamjie/p/9395659.html

使用redis命令set key value nx ex max-lock-time实现枷锁

使用redis命令eval实现解锁

Set只有key-value都比配才有删除锁的权利[保证安全性]

通过timeOut设置过期时间保证不会出现死锁

Set()加入了NX参数,可以保证如果已有key存在,则函数不会调用成功,也就是只有一个客户端持有锁,满足互斥性,其次,由于互斥锁设置了过期时间,即使锁的持有者后续发生崩溃而没有解锁,锁也会因为到了过期时间而自动解锁(即key被删除),不会发生死锁。最后,由于加锁的客户端请求标识,那么在客户端在解锁的时候就可以进行校验是否是同一个客户端。

不能使用jedis.del方法删除锁,要先判断锁的拥有者,客户端只能解自己的锁

参考:https://baijiahao.baidu.com/s?id=1616996633536597016&wfr=spider&for=pc

回答: Redis常见面试题包括但不限于以下几个方面: 1. Redis的特点和优势:Redis是一个基于内存的NoSQL数据库,支持多种数据结构和丰富的操作,具有高性能、高并发、持久化、主从同步等特点。 2. Redis的数据结构:Redis支持多种数据结构,包括字符串(string)、列表(list)、集合(set)、有序集合(sorted set)和哈希(hash),每种数据结构都有相应的操作方法。 3. Redis的持久化方式:Redis有两种持久化方式,分别是RDBRedis Database)和AOF(Append Only File)。RDB是将内存中的数据定期保存到磁盘上,而AOF是将每个写操作追加到文件末尾。 4. Redis的使用场景:Redis可以用于缓存、话管理、计数器、排行榜、消息队列等多种场景。它的高性能和丰富的数据结构使得它在处理大量并发请求和快速读写的场景下表现出色。 5. Redis的并发访问:Redis采用单进程单线程模式,通过队列模式将并发访问变为串行访问。在Jedis客户端对Redis进行并发访问时可能出现连接超时、数据转换错误、阻塞等问题,需要注意处理这些并发访问的情况。 综上所述,Redis是一个功能强大的基于内存的NoSQL数据库,具有多种数据结构和丰富的操作方法,适用于多种场景。在面试中,了解Redis的特点、数据结构、持久化方式、使用场景和并发访问等方面的知识是非常重要的。 #### 引用[.reference_title] - *1* *2* [redis面试题总结(附答案)](https://blog.csdn.net/guorui_java/article/details/117194603)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [精选 21道 Redis 最常问面试题!收藏一波 !](https://blog.csdn.net/w915209092/article/details/126035419)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值