对象

Set一个已有的数据会发生什么?

  • 原来数据的元素被覆盖掉

浮点型在String是用什么表示?

  • 用字符串表示,进行自增加减操作转化为浮点型操作

String可以有多大?

  • 512MB

Redis字符串是怎么实现的?

  • int整型通过int编码实现,

  • 小于等于39(redis设计与实现32)字节是embstr编码(只是可读的,修改的话变为raw编码)

  • 否则为raw编码

    raw和embstr编码底层都是SDS实现,embstr一次分配到redisObject上,raw动态分配到redisObject

为什么EMBSTR的阈值是44?

  • 初始redisObject 分配64字节,redisObject对象占16字节—>48字节
  • 3.2版本之前:len和free使用unsigned int类型一共占用8个字节,‘/0’占一个字节,剩余48-8-1=39字节
  • 3.2之后:len和alloc使用uint8_t类型一共两个字节,flags(表示数组类型sdshdr8还是sdshdr16)使用unsigned char类型占用1个字节,‘/0’一个字节,剩余48-2-1-1=44字节

你知道为什么EMBSTR曾经的阈值是39吗?

  • 3.2之前,int型len和free占8个字节,‘/0’占1个字节,redisObject占16个字节,所以是39字节

SDS有什么用?

  • SDS存储有数组长度,所以字符串长度时间复杂度是o(1)
  • SDS能够支持二进制字符串,因为SDS不是以’\0’来判断字符串是否结束,而是以长度判断
  • SDS减少内存重分配,每次增加减少字符串通过修改free的方式来修改

List是完全先入先出吗?

  • 不是,list底层紧凑列表(5.0之前压缩列表)或者双向队列,不完全是先进先出

List对象底层编码方式是什么?

  • 底层是压缩列表或者双向链表
  • 压缩列表小于64字节或者元素数量小于512

ZIPLIST是怎么压缩数据的?

  • 没有使用指针,物理上相连的内存

ZIPLIST下List可以从后往前遍历吗?

  • 可以从后往前遍历,因为ZIPLIST里面entry结构存储的有上一个数据的长度,可以根据长度找出上一个节点的起始位置,进行遍历

在ZIPLIST数据结构下,查询节点个数的时间复杂度是多少?

  • O(1),因为ZIPLIST里面存储有节点个数的数据结构

LINKEDLIST编码下,查询节点个数的时间复杂度是多少?

  • o(1),LINKEDLIST里面存储有节点个数的数据结构

Set编码方式?

  • 整数集合(元素全是整数或者数量小于512)
  • 字典

Set是有序的吗?

  • 不是有序的,整型集合排列是按大小顺序的,而不是插入顺序
  • 字典不是有序的

HSet的编码方式是什么?

  • 字典
  • 紧凑列表(3.2之前压缩列表,小于512元素,或者小于64字节)

HSet查找某个key的平均时间复杂度是多少?

  • 字典o(1)
  • 压缩列表o(n)

Redis中HashTable查找元素总数的平均时间复杂度是多少?

o(1)

跳表中一个节点的层高是怎么决定的?

每一个节点插入会生成一个随机数,如果随机数大小小于25%,增加一层高度,否则就为当前高度

Redis执行

Redis是单线程还是多线程

Redis工作线程是单线程,IO操作线程是多线程,后台清理脏数据,大key清楚(4.0之后)

Redis为什么选择单线程做核心处理

Redis是基于内存的操作的,Redis的上限取决于网络IO的速度,而不是CPU的速度,所以单线程能更好的利用CPU资源

Redis单线程性能如何

单线程进行数据操作很快,写性能大概11w,读大概15w

为什么单线程还能这么快

  • 因为redis是基于内存的
  • redis内存结构非常高效
  • IO多路复用让网络IO这块的短板提升很多性能

Redis6.0之后引入了多线程,你知道为什么吗?

避免Redis由于网络io而影响性能

Redis6.0的多线程是默认开启的吗?

默认禁用的,需要在conf文件开启多线程

Redis6.0的多线程主要负责命令执行的哪一块

主要负责网络IO那块,从网卡读取数据到本地工作队列,交由主线程进行数据操作

Redis持久化

RDB和AOF本质区别是什么?

  • RDB是快照,将这个时刻的数据以二进制形式复刻备份成文件
  • AOF是将每次数据操作加入到日志文件中

如果RDB和AOF只能选一种,你选哪个?

  • 如果接收一定的数据丢失换取性能可以用RDB
  • 如果要求数据必须可靠,混合使用

RDB的触发时机?

  • redis关闭前
  • 客户端执行save或者bgsave
  • 主从进行全量复制

AOF的触发时机?

  • redis关闭前
  • 事件循环时

RDB对主流程有什么影响?

  • save命令会阻塞主线程
  • bgsave会fork一个子进程,有时间开销,另外bgsave是写时复制,如果数据量大的话,复制就会有cpu损耗

AOF混合持久化方案是什么?

  • 在AOF重写的时候,原来数据使用二进制记录,新增数据使用命令格式记录

简单描述AOF重写流程

  • 首先fork一个子进程,从数据库里读取所有数据
  • 新增的数据放入AOF缓冲文件和AOF重写缓冲文件中,另外通过管道将重写缓冲文件数据传递给给子进程
  • 子进程将重写后的文件覆盖到原文件上

AOF重写你觉得有什么不足之处么?

  • 父进程同时写AOF缓冲日志和AOF重写缓冲日志,额外的开销
  • 将AOF重写缓冲日志通过管道写到子进程

针对AOF重写的不足,你有什么优化思路呢?

  • 开一个子进程将当前数据重写进AOF日志文件
  • 父进程将当前新的数据写进AOF新增日志文件
  • 然后将两个日志文件合并

Redis场景

你有实际使用过Redis做什么应用么?

  • 一般用来存储session数据
  • 存储一些不厂修改的数据

Redis缓存是如何应用的?

Redis做旁路缓存,如果MySQL更新了,此时何去何从?

  • 如果要求强一致性,先加读写锁,修改数据库数据,删除缓存,释放锁
  • 要求最终一致性,先更新数据库,再删除缓存

Redis做秒杀场景可以吗?讲讲思路

Redis可以做消息队列吗?什么时候能用Redis做消息队列?

分布式锁实现要点是什么(其实就是怎么加锁、怎么解锁、怎么用)?

缓存问题(缓存穿透,缓存击穿,缓存雪崩)

  • 缓存穿透:

    当前请求数据未在缓存中存储,因此会到数据库中访问,但数据库也没有该数据,通过这个请求恶意攻击服务器,导致所有请求全部打到数据库中,引起数据库宕机

    解决方法:

    • 缓存null值:当请求到数据库时,没有该数据,将该数据缓存到redis中,值为null,以后所有数据就只访问到缓存,而不会影响数据库

    • 布隆过滤器:通过若干个hash函数,将请求的数据求出对应hash值,如果对应hash值在对应数组都为1,则表示存在该数据

      数值全部为1不一定存在,但不全为1,一定不存在

  • 缓存击穿:

    某个热点数据在缓存中过期,此刻大量请求同时访问该数据,由于缓存中没有该数据,所有数据就会打到数据库中,导致服务器宕机

    解决办法:

    • 加锁:只能一个请求访问数据库,但会导致请求响应时间过长

    • 设置逻辑过期:在缓存中查询到该数据,如果逻辑过期,新开一个线程,加一个互斥锁,之前所有线程返回旧数据,新增线程访问数据库

      缺点:数据没有一致性

  • 缓存雪崩:

    多个热点数据同时过期,大量请求同时访问多个数据,导致所有请求打到数据库上,导致数据库宕机

    解决办法:

    • 随机时间:将所有缓存数据设置随机过期时间,防止同一时间同时过期
更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

anoxia 微信支付

微信支付

anoxia 支付宝

支付宝