redis面试题(持续更新)

网友投稿 682 2022-05-28

大量的数据请求可能造成数据库的宕机(如秒杀,热点数据,),Redis是使用内存存贮,每秒的运行次数可以达到10w+,可以减少数据库的压力。

String、Hash、List、Set、SortedSet。

要设置随机的过期时间,否则造成雪崩。

使用set语法,加入jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);

也可以用setnx然后在使用expire设置过期时间,但是如果在setnx后服务挂掉了,就会造成死锁。

使用keys指令。

keys指令会导致线程阻塞一段时间,线上服务会停顿,直到指令执行完毕,服务才能恢复。

使用rpush生产消息,lpop消费消息。当lpop没有消息的时候,要适当sleep一会再重试。

list还有个指令叫blpop,在没有消息的时候,它会阻塞住直到消息到来。

使用pub/sub主题订阅者模式,可以实现 1:N 的消息队列。

在消费者下线的情况下,生产的消息会丢失,得使用专业的消息队列如RocketMQ等。

使用zset score放入要延时的时间 ,然后使用rangebyscore轮询获取。

使用pub/sub。

redisTemplate.convertAndSend(“testkafka”, data); 放入队列。

请参考上文。

Redis 高可用,主从+哨兵,Redis cluster,避免全盘崩溃。

本地 ehcache 缓存 + Hystrix 限流+降级,避免** MySQL** -。

Redis 持久化 RDB+AOF,一旦重启,自动从磁盘上加载数据,快速恢复缓存数据。

请参考上文。

Redis Cluster:主要为扩展分片 当内存不足使用Cluster扩展。

Redis Sentinal:高可用,当主机死掉后选举从机为主机。

首先进行RDB全局持久化存放于内存,然后将RDB文件发送给从机,同时,在接下来使用AOF逐步同步。

redis管道,可以将多次请求放于pipeline,然后一起读取出来,这样可以增加redis吞吐量。

本地缓存就是在进程的内存中进行缓存,比如我们的 JVM 堆中,可以用 LRUMap 来实现,也可以使用 Ehcache 这样的工具来实现。本地缓存是内存访问,没有远程交互开销,性能最好,但是受限于单机容量,一般缓存较小且无法扩展。

分布式缓存一般都具有良好的水平扩展能力,对较大数据量的场景也能应付自如。缺点就是需要进行远程请求,性能不如本地缓存。

为了平衡这种情况,实际业务中一般采用多级缓存,本地缓存只保存访问频率最高的部分热点数据,其他的热点数据放在分布式缓存中。

不管是本地缓存还是分布式缓存,为了保证较高性能,都是使用内存来保存数据,由于成本和内存限制,当存储的数据超过缓存容量时,需要对缓存的数据进行剔除。

一般的剔除策略有 FIFO 淘汰最早数据、LRU 剔除最近最少使用、和 LFU 剔除最近使用频率最低的数据几种策略。

noeviction:返回错误当内存限制达到并且客户端尝试执行会让更多内存被使用的命令(大部分的写入指令,但DEL和几个例外)

allkeys-lru: 尝试回收最少使用的键(LRU),使得新添加的数据有空间存放。

volatile-lru: 尝试回收最少使用的键(LRU),但仅限于在过期集合的键,使得新添加的数据有空间存放。

allkeys-random: 回收随机的键使得新添加的数据有空间存放。

volatile-random: 回收随机的键使得新添加的数据有空间存放,但仅限于在过期集合的键。

volatile-ttl: 回收在过期集合的键,并且优先回收存活时间(TTL)较短的键,使得新添加的数据有空间存放。

如果没有键满足回收的前提条件的话,策略volatile-lru, volatile-random以及volatile-ttl就和noeviction 差不多了。

使用Redis cluster,主从同步读写分离,类似Mysql的主从同步,Redis cluster 支撑 N 个 Redis master node,每个master node都可以挂载多个 slave node。

你启动一台slave 的时候,他会发送一个psync命令给master ,如果是这个slave第一次连接到master,他会触发一个全量复制。master就会启动一个线程,生成RDB快照,还会把新的写请求都缓存在内存中,RDB文件生成后,master会将这个RDB发送给slave的,slave拿到之后做的第一件事情就是写进本地的磁盘,然后加载进内存,然后master会把内存里面缓存的那些新命名都发给slave。

是有定期删除+惰性删除两种。

定期好理解,默认100ms就随机抽一些设置了过期时间的key,去检查是否过期,过期了就删了。

惰性策略:请求时判断是否过去。

假如Redis里面所有的key都有过期时间,都扫描一遍?那太恐怖了,而且我们线上基本上也都是会设置一定的过期时间的。全扫描跟你去查数据库不带where条件不走索引全表扫描一样,100ms一次,Redis累都累死了。

好问题,惰性删除,见名知意,惰性嘛,我不主动删,我懒,我等你来查询了我看看你过期没,过期就删了还不给你返回,没过期该怎么样就怎么样。

传输过程中有什么网络问题啥的,会自动重连的,并且连接之后会把缺少的数据补上的。

如果第一个请求网络延迟了 可能覆盖之后的请求,造成数据不一致

1 使用分布式锁

2 输入时加入时间戳 通过时间戳判断

在不要求效率的情况下,可以放入队列中。 但是会引起阻塞。

读缓存 ,缓存没有读db,保存到缓存

更新 先更新数据库在删除缓存

缓存来源不一定是一个操作,而且如果多次操作db,同时多次操作db同时多次更新缓存会造成很多冷数据。

Redis 内部使用文件事件处理器 file event handler,这个文件事件处理器是单线程的,所以 Redis 才叫做单线程的模型。它采用 IO 多路复用机制同时监听多个 Socket,根据 Socket 上的事件来选择对应的事件处理器进行处理。

文件事件处理器的结构包含 4 个部分:

多个 Socket

IO 多路复用程序

文件事件分派器

redis面试题(持续更新)

事件处理器(连接应答处理器、命令请求处理器、命令回复处理器)

多个 Socket 可能会并发产生不同的操作,每个操作对应不同的文件事件,但是 IO 多路复用程序会监听多个 Socket,会将 Socket 产生的事件放入队列中排队,事件分派器每次从队列中取出一个事件,把该事件交给对应的事件处理器进行处理。

第二个问题是数据不一致的问题,可以说只要使用缓存,就要考虑如何面对这个问题。缓存不一致产生的原因一般是主动更新失败,例如更新 DB 后,更新 Redis 因为网络原因请求超时;或者是异步更新失败导致。

解决的办法是,如果服务对耗时不是特别敏感可以增加重试;如果服务对耗时敏感可以通过异步补偿任务来处理失败的更新,或者短期的数据不一致不会影响业务,那么只要下次更新时可以成功,能保证最终一致性就可以。

比如 Redis 是单线程处理请求,应尽量避免耗时较高的单个请求任务,防止相互影响;Redis 服务应避免和其他 CPU 密集型的进程部署在同一机器;或者禁用 Swap 内存交换,防止 Redis 的缓存数据交换到硬盘上,影响性能。

Redis

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:错误信息:FATAL: No bootable medium found! System halted.
下一篇:【玩转镜像】一键上云是种怎样的体验
相关文章