Redis 面试题

导读:本篇文章讲解 Redis 面试题,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

Redis 部署

集群加哨兵: 哨兵发现master down 并选举。
哨兵怎么发现Master挂了:哨兵启动后根据配置向 master 发送info指令,获取并且保存所有哨兵状态,主节点和从节点的信息;

Redis 动态扩容、缩容

Redis 没有使用一致性hash 引入了哈希槽的概念,Redis集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽,集群的每个节点负责一部分hash槽。

有个卡槽、槽位的概念。具体就算了,太偏运维了,脱离主业了。

集群间如何复制

采用异步复制。 fork个子进程。

Redis 集群脑裂问题怎么解决

min-slaves-to-write 1
min-slaves-max-lag 10

第一个参数表示连接到master的最少slave数量
(判断有多少个从服务器,达到了要求才发送信息
避免了主服务器失连后依旧写入数据)

第二个参数表示slave连接到master的最大延迟时间
(减少同步间隔时间,在失连前同步完成)

Redis AOF文件过大怎么办

执行BGREWRITEAOF命令对redis的AOF进行重写。(BG_REWRITE_AOF这样看这个命令就好记了)
从 Redis 2.4 开始,AOF 重写由 Redis 自行触发, BGREWRITEAOF 仅仅用于手动触发重写操作。

RDB和AOF如何选择

通常来说,应该同时使用两种持久化方案,以保证数据安全。

如果数据不敏感,且可以从其他地方重新生成,可以关闭持久化。
如果数据比较重要,且能够承受几分钟的数据丢失,比如缓存等,只需要使用RDB即可。
如果是用做内存数据,要使用Redis的持久化,建议是RDB和AOF都开启。
如果只用AOF,优先使用everysec的配置选择,因为它在可靠性和性能之间取了一个平衡。
当RDB与AOF两种方式都开启时,Redis会优先使用AOF恢复数据,因为AOF保存的文件比RDB文件更完整。

Redis 分布式锁

直接就是用Redisson,setnx啥的说说,老八股了。

Redis几种数据类型

8种
常用的5种
string 字符串类型;
list 列表类型;
set 集合类型;
sorted set 有序集合类型;
hash 类型;
加 三种特殊的
bitmap 位图类型;
geo 地理位置类型;
HyperLogLog 基数统计类型。

ZSet数据结构

zset的编码有ziplist和skiplist两种。

当zset满足以下两个条件的时候,使用ziplist:
保存的元素少于128个
保存的所有元素大小都小于64字节

ziplist编码的有序集合使用压缩列表作为底层实现,每个集合元素使用两个紧挨着一起的两个压缩列表节点表示,第一个节点保存元素的成员(member),第二个节点保存元素的分值(score)。

skiplist编码的有序集合对象使用zset结构作为底层实现,一个zset结构同时包含一个字典和一个跳跃表。
跳跃表就是多存了好几份,类似二分的思想。用跳跃表还有一个优点插入块。缺点就是费内存。
问题:为什么用跳表不用红黑树。答案就是上边说的插入块
高度 : 每次创建一个新跳跃表节点的时候, 程序都根据幂次定律 (power law,越大的数出现的概率越小) 随机生成一个介于 1 和 32 之间的值作为 level 数组的大小, 这个大小就是层的“高度”。

Redis string 数据结构注意的事项

序列化,尤其是java的。
还有就是大key问题。
不要用keys去匹配。

什么样的key算大ke

redis自己限制String的value不要大于512M,开发中不要大于10k。
string长度大于10K,list长度大于10240认为是big bigkeys。
参考使用redis-cli的“–bigkeys”选项查找大Key
redis-cli -h b.redis -p 1959 –bigkeys 可以参考下,还有就是自己业务中发现的。
redis-cli -h b.redis -p 1959 –hotkeys 热key。自己执行没成功。

大key怎么对待

  1. 直接改名 就谁都访问不到了,达到了删除的效果。
  2. 小步批次删除。
  3. UNLINK
    UNLINK 工作思路:
    (1)在所有命名空间中把 key 删掉,立即返回,不阻塞。
    (2)后台线程执行真正的释放空间的操作。

内存淘汰策略

主要分俩大类 allkeys、volatile
noeviction内存不足写入报错、all-keys-LRU 最近最久未使用、allkeys-random随机淘汰volatile-lru 设置了过期时间的LRU、volatile-random设置了过期时间的随机、volatile-ttl过期时间内最早的先移除。
又新加了LFU(Least Frequently Used)的策略最少使用频率算法
对应volatile-lfu 只针对设置 expire 过期的 key 进行 lfu 淘、allkeys-lfu 对所有的 key 进行 lfu 淘汰
一共八种

  • volatile-lru 只针对设置 expire 过期的 key 进行 lru 淘汰
  • allkeys-lru 对所有的 key 进行 lru 淘汰
  • volatile-lfu 只针对设置 expire 过期的 key 进行 lfu 淘汰
  • allkeys-lfu 对所有的 key 进行 lfu 淘汰
  • volatile-random 只针对设置 expire 过期的进行随机淘汰
  • allkeys-random 所有的 key 随机淘汰
  • volatile-ttl 淘汰 ttl 过期时间最小的 key
  • noeviction 什么都不做,如果此时内存已满,系统无法写入

过期删除策略

和上边的内存淘汰策略区分开来,这是删除过期key、上边是内存不够用了。
立即删除(需要定时器、耗费cpu)、惰性删除(再次被访问才删除,耗费内存)、定期过期(折中了下)

事务

这个和Mysql是不一样的,Redis的事务就是一些命令放到一起执行,保证别的不插入,错误了也不回滚,就是执行正确的。
事务的三个阶段 事务开始 MULT、命令入、事务执行 EXE。

内存碎片 怎么办

参考 : redis线上问题记录
分析原因:
redis实例启动会配置个内存大小,当写命令发生没有可用内存后,会开启内存淘汰策略一般是LRU,但是由于满载情况下,这是LRU释放的内存暂时不会立刻给内存分配器使用,内存分配器会继续想os申请内存,保障同时的写入指令,这样会导致申请的内存变多,实际使用的内存变少,这样碎片率也就高了;

解决办法:
1、redis 4.0之前只能重启服务,我们采取的措施是切换到从,重启主;
2、redis 4.0之后修改内存分配器。Redis支持glibc’s malloc、jemalloc11、tcmalloc几种不同的内存分配器,每个分配器在内存分配和碎片上都有不同的实现。不建议普通管理员修改Redis默认内存分配器,因为这需要完全理解这几种内存分配器的差异,也要重新编译Redis。

Redis4版本之后开始支持内存碎片的清理,默认情况下自动清理碎片的参数是关闭的:config get activedefrag应该得到no的输出,开启:config set activedefrag yes,再次输入config get activedefrag验证输出是否为yes。

开启后,后台会启动进程,也可以手动清理:memory purge
总结:这个问题无法解决,只能通过加更多的资源解决;

Redis可以实现啥

分布式锁

这就不说了,烂大街了。

限流 (滑动窗口)

  • ZSet结构 course(分数) 存时间戳的秒数,value(最好存个唯一值)uid啥的,结果有相同course,一个course对应多个Value。
  • ZSet 可以有相同course不可有相同的value。所以是一个course对应多个Value。
    Pipeline保证原子性。
    添加命令 : ZADD key score1 member1
    ZCARD KEY_NAME 统计集合有多少的数据。
  • List数据结构:令牌桶
    leftPop来获取令牌,定时往List中rightPush令牌。

关联知识:参考:《面试补习》- 你来说说什么是限流?人人都能看懂的 6 种限流实现方案!(纯干货)

  • RateLimiter:Google开源项目Guava中的RateLimiter使用的就是令牌桶控制算法。
  • Nginx 限流,Nginx自带了两个限流模块:
    连接数限流模块 ngx_http_limit_conn_module
    漏桶算法实现的请求限流模块 ngx_http_limit_req_module。
  • Tomcat 限流
  • 限流中间件
    Sentinel 是阿里中间件团队研发的面向分布式服务架构的轻量级高可用流量控制组件,主要以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度来帮助用户保护服务的稳定性。

排行榜

ZSet 数据结构。
原子加score(分数)
命令格式:ZINCRBY key increment member 实例 :ZINCRBY key 1 value
描述:为有序集 key 的成员 member 的 score 值加上增量 increment 。
时间复杂度:O(log(N))
返回值: 返回member 成员的新 score 值,以字符串形式表示。

获取排名前几的值:ZRANGE key start stop [WITHSCORES]

简单那消息队列

使用list类型保存数据信息,rpush生产消息,lpop消费消息,当lpop没有消息时,可以sleep一段时间,然后再检查有没有信息,如果不想sleep的话,可以使用blpop, 在没有信息的时候,会一直阻塞,直到信息的到来。redis可以通过pub/sub主题订阅模式实现一个生产者,多个消费者,当然也存在一定的缺点,当消费者下线时,生产的消息会丢失。

Redis如何实现延时队列(就八股文没法实际操作)

使用 sortedset,使用时间戳做score, 消息内容作为key,调用zadd来生产消息,消费者使用zrangbyscore获取n秒之前的数据做轮询处理。

脑图

参考Redis脑图
在这里插入图片描述

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/76453.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!